Fehlender Schreibschutz für parametrische Datenwerte
Beschreibung
Der fehlende Schreibschutz für parametrische Datenwerte tritt auf, wenn das Gerät die parametrischen Datenwerte für Sensoren, die den Sensorwert skalieren, nicht schreibschützt, wodurch nicht vertrauenswürdige Software das angezeigte Ergebnis manipulieren und möglicherweise Hardware beschädigen oder Betriebsausfälle verursachen kann. Hardware-Geräte verwenden Sensoren zur Überwachung von Betriebsparametern wie Temperatur, Leistung, Spannung, Strom und Frequenz. Während Schwellenwertgrenzen typischerweise über Hardware-Fuses oder vertrauenswürdiges BIOS geschützt sind, können die Sensorkalibrierungsdaten für die Einheitenumrechnung ungeschützt bleiben. Nicht vertrauenswürdige Software kann diese parametrischen Skalierungswerte ändern, um Sicherheitsgrenzen zu umgehen und Sensormesswerte zu fälschen.
Risiko
Ungeschützte Sensorparameter haben schwerwiegende Auswirkungen. Physische Hardwareschäden möglich. Thermische Grenzen umgangen, was zu Überhitzung führt. Leistungsgrenzen umgangen, was zu Komponentenschäden führt. Falsche Sensormesswerte verschleiern gefährliche Zustände. Denial of Service durch induzierte Ausfälle. Sicherheitsmechanismen unwirksam gemacht. Hardware-Lebensdauer reduziert. Hohe Verfügbarkeitsauswirkung.
Lösung
Implementieren Sie während der Architektur- und Entwurfsphase Zugriffskontrollen, die die Änderung von Schwellenwertgrenzen und Sensor-Parameterdaten auf vertrauenswürdige Software beschränken. Speichern Sie Kalibrierungsdaten in geschützten Speicherbereichen. Erfordern Sie privilegierten Zugriff für Parameteränderungen. Erwägen Sie Hardware-Fuses für kritische Kalibrierungswerte. Validieren Sie Parameteränderungen gegen sichere Bereiche auch für vertrauenswürdige Software.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Verfügbarkeit | Bereich: Verfügbarkeit Denial of Service durch Hardwareschäden, falsche Abschaltungen oder induzierte Instabilität. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Sensor mit ungeschützten Kalibrierungsparametern
module vulnerable_temperature_sensor (
input wire clk,
input wire rst_n,
// Roher Sensoreingang (Oszillatorfrequenz)
input wire [15:0] oscillator_freq,
// Kalibrierungsparameter (VERWUNDBAR: von jedem beschreibbar)
input wire param_write_enable,
input wire [31:0] param_write_data,
input wire [3:0] param_write_addr,
// Temperaturausgabe
output reg [15:0] temperature_celsius,
output reg over_temp_alarm,
output reg shutdown_required
);
// Kalibrierungsparameter für Temperaturberechnung
// Temperatur = a * freq + b (lineare Näherung)
reg signed [15:0] param_a; // Steigungskoeffizient
reg signed [15:0] param_b; // Offset-Koeffizient
// Schwellenwert (typischerweise durch Fuse geschützt)
localparam SHUTDOWN_THRESHOLD = 16'd100; // 100 Grad C
// VERWUNDBAR: Kalibrierungsparameter ohne Einschränkung beschreibbar
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Standard-Kalibrierungswerte
param_a <= 16'h0010; // Standard-Steigung
param_b <= 16'hFF00; // Standard-Offset
end else if (param_write_enable) begin
// VERWUNDBAR: Jede Software kann Parameter ändern
case (param_write_addr)
4'h0: param_a <= param_write_data[15:0];
4'h1: param_b <= param_write_data[15:0];
endcase
end
end
// Temperatur aus Oszillatorfrequenz berechnen
reg signed [31:0] temp_calc;
always @(posedge clk) begin
// Temperatur = a * freq + b
temp_calc <= param_a * $signed({1'b0, oscillator_freq}) + param_b;
temperature_celsius <= temp_calc[15:0];
// Gegen Schwellenwert prüfen
if (temperature_celsius >= SHUTDOWN_THRESHOLD) begin
over_temp_alarm <= 1'b1;
shutdown_required <= 1'b1;
end else begin
over_temp_alarm <= 1'b0;
shutdown_required <= 1'b0;
end
end
// Angriff:
// 1. Angreifer setzt param_a = 0, param_b = 0
// 2. Temperatur zeigt immer 0 Grad C an
// 3. Hardware überhitzt auf gefährliche Werte
// 4. Abschalt-Schwellenwert wird nie ausgelöst
// 5. Physischer Hardwareschäden
endmodule
// VERWUNDBAR: Leistungssensor mit ungeschützter Skalierung
module vulnerable_power_sensor (
input wire clk,
input wire rst_n,
// Roher ADC-Messwert
input wire [11:0] adc_reading,
// Skalierungsparameter (VERWUNDBAR: ungeschützt)
input wire scale_write_en,
input wire [15:0] scale_multiplier,
input wire [15:0] scale_divisor,
// Leistungsausgabe
output reg [15:0] power_watts,
output reg power_limit_exceeded
);
// VERWUNDBAR: Skalierungsfaktoren ohne Authentifizierung beschreibbar
reg [15:0] multiplier;
reg [15:0] divisor;
localparam POWER_LIMIT = 16'd150; // 150W-Grenze
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
multiplier <= 16'd100; // Standard-Kalibrierung
divisor <= 16'd1024;
end else if (scale_write_en) begin
// VERWUNDBAR: Keine Zugriffskontrolle
multiplier <= scale_multiplier;
divisor <= scale_divisor;
end
end
// Leistung berechnen
always @(posedge clk) begin
if (divisor != 0) begin
power_watts <= (adc_reading * multiplier) / divisor;
end else begin
// VERWUNDBAR: Division durch Null wenn Angreifer divisor=0 setzt
power_watts <= 16'hFFFF; // Überlauf!
end
power_limit_exceeded <= (power_watts > POWER_LIMIT);
end
// Angriff:
// multiplier=0 setzen -> Leistung zeigt immer 0W
// Oder divisor=0 setzen -> verursacht undefiniertes Verhalten
// Leistungsgrenzen werden nie ausgelöst, Komponentenschäden möglich
endmodule
// VERWUNDBAR: Software-Sensortreiber ohne Parameterschutz
#include <stdint.h>
#include <stdbool.h>
// VERWUNDBAR: Kalibrierungsstruktur für alle Software zugänglich
typedef struct {
int16_t slope;
int16_t offset;
uint16_t threshold;
} sensor_calibration_t;
// VERWUNDBAR: Globale, ungeschützte Kalibrierungsdaten
static sensor_calibration_t thermal_calibration = {
.slope = 16,
.offset = -256,
.threshold = 100
};
// VERWUNDBAR: Jeder Code kann Kalibrierung ändern
void vulnerable_set_calibration(int16_t slope, int16_t offset) {
// Keine Berechtigungsprüfung!
thermal_calibration.slope = slope;
thermal_calibration.offset = offset;
}
int16_t vulnerable_read_temperature(uint16_t raw_reading) {
// Verwendet möglicherweise kompromittierte Kalibrierung
int32_t temp = (thermal_calibration.slope * raw_reading) +
thermal_calibration.offset;
return (int16_t)temp;
}
bool vulnerable_check_thermal_limit(uint16_t raw_reading) {
int16_t temp = vulnerable_read_temperature(raw_reading);
// VERWUNDBAR: Gibt false zurück wenn Kalibrierung beschädigt wurde um niedrige Temperatur anzuzeigen
return temp >= thermal_calibration.threshold;
}
// Angriff:
// malicious_code() {
// vulnerable_set_calibration(0, 0); // slope=0, offset=0 setzen
// // Jetzt geben alle Temperaturmesswerte 0 zurück
// // System löst keinen Thermalschutz aus
// }
Sichere Lösung
// SICHER: Sensor mit geschützten Kalibrierungsparametern
module secure_temperature_sensor (
input wire clk,
input wire rst_n,
// Roher Sensoreingang
input wire [15:0] oscillator_freq,
// Kalibrierungs-Schreibschnittstelle (eingeschränkt)
input wire param_write_enable,
input wire [31:0] param_write_data,
input wire [3:0] param_write_addr,
input wire privileged_access, // SICHER: Berechtigungssignal
input wire boot_complete, // SICHER: Lebenszyklus-Signal
// Temperaturausgabe
output reg [15:0] temperature_celsius,
output reg over_temp_alarm,
output reg shutdown_required,
output reg param_write_denied
);
// Kalibrierungsparameter
reg signed [15:0] param_a;
reg signed [15:0] param_b;
// SICHER: Schreibsperre nach Boot
reg calibration_locked;
// SICHER: Gültige Parameterbereiche
localparam MIN_SLOPE = 16'sh0001;
localparam MAX_SLOPE = 16'sh00FF;
localparam MIN_OFFSET = 16'shFC00;
localparam MAX_OFFSET = 16'sh0400;
localparam SHUTDOWN_THRESHOLD = 16'd100;
// SICHER: Kalibrierung nach Boot sperren
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
calibration_locked <= 1'b0;
end else if (boot_complete) begin
// SICHER: Nach Boot-Abschluss Kalibrierung sperren
calibration_locked <= 1'b1;
end
end
// SICHER: Geschützte Kalibrierungsparameter-Schreibzugriffe
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Standard-Kalibrierung aus OTP/Fuse laden
param_a <= 16'h0010;
param_b <= 16'hFF00;
param_write_denied <= 1'b0;
end else if (param_write_enable) begin
param_write_denied <= 1'b0;
// SICHER: Berechtigungen und Lebenszyklus prüfen
if (!privileged_access || calibration_locked) begin
// SICHER: Schreibzugriff von nicht-privilegiert oder nach Sperre ablehnen
param_write_denied <= 1'b1;
end else begin
// SICHER: Parameterbereiche validieren
case (param_write_addr)
4'h0: begin
if ($signed(param_write_data[15:0]) >= MIN_SLOPE &&
$signed(param_write_data[15:0]) <= MAX_SLOPE) begin
param_a <= param_write_data[15:0];
end else begin
param_write_denied <= 1'b1; // Außerhalb des Bereichs
end
end
4'h1: begin
if ($signed(param_write_data[15:0]) >= MIN_OFFSET &&
$signed(param_write_data[15:0]) <= MAX_OFFSET) begin
param_b <= param_write_data[15:0];
end else begin
param_write_denied <= 1'b1; // Außerhalb des Bereichs
end
end
default: begin
param_write_denied <= 1'b1;
end
endcase
end
end
end
// Temperatur berechnen
reg signed [31:0] temp_calc;
always @(posedge clk) begin
temp_calc <= param_a * $signed({1'b0, oscillator_freq}) + param_b;
temperature_celsius <= temp_calc[15:0];
if (temperature_celsius >= SHUTDOWN_THRESHOLD) begin
over_temp_alarm <= 1'b1;
shutdown_required <= 1'b1;
end else begin
over_temp_alarm <= 1'b0;
shutdown_required <= 1'b0;
end
end
endmodule
// SICHER: Leistungssensor mit geschützten und validierten Parametern
module secure_power_sensor (
input wire clk,
input wire rst_n,
// Roher ADC-Messwert
input wire [11:0] adc_reading,
// Geschützte Skalierungsparameter-Schnittstelle
input wire scale_write_en,
input wire [15:0] scale_multiplier,
input wire [15:0] scale_divisor,
input wire privileged_access,
input wire boot_complete,
// Leistungsausgabe
output reg [15:0] power_watts,
output reg power_limit_exceeded,
output reg param_error
);
reg [15:0] multiplier;
reg [15:0] divisor;
reg params_locked;
// SICHER: Sichere Parameterbereiche
localparam MIN_DIVISOR = 16'd100; // Divisionsprobleme verhindern
localparam MAX_MULTIPLIER = 16'd1000;
localparam POWER_LIMIT = 16'd150;
// SICHER: Nach Boot sperren
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
params_locked <= 1'b0;
end else if (boot_complete) begin
params_locked <= 1'b1;
end
end
// SICHER: Geschützte Parameter-Schreibzugriffe
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
multiplier <= 16'd100;
divisor <= 16'd1024;
param_error <= 1'b0;
end else if (scale_write_en) begin
param_error <= 1'b0;
if (!privileged_access || params_locked) begin
// SICHER: Nicht-privilegierte oder gesperrte Schreibzugriffe ablehnen
param_error <= 1'b1;
end else begin
// SICHER: Divisor validieren um Division durch Null zu verhindern
if (scale_divisor >= MIN_DIVISOR &&
scale_multiplier <= MAX_MULTIPLIER) begin
multiplier <= scale_multiplier;
divisor <= scale_divisor;
end else begin
param_error <= 1'b1;
end
end
end
end
// Leistung berechnen (sicher mit validiertem Divisor)
always @(posedge clk) begin
power_watts <= (adc_reading * multiplier) / divisor;
power_limit_exceeded <= (power_watts > POWER_LIMIT);
end
endmodule
// SICHER: Software-Sensortreiber mit geschützten Parametern
#include <stdint.h>
#include <stdbool.h>
typedef struct {
int16_t slope;
int16_t offset;
uint16_t threshold;
bool locked; // SICHER: Sperr-Flag
} sensor_calibration_t;
// SICHER: Statische Kalibrierung, nicht direkt zugänglich
static sensor_calibration_t thermal_calibration = {
.slope = 16,
.offset = -256,
.threshold = 100,
.locked = false
};
// SICHER: Gültige Parameterbereiche
#define MIN_SLOPE 1
#define MAX_SLOPE 255
#define MIN_OFFSET -1024
#define MAX_OFFSET 1024
// SICHER: Nur privilegierte Kalibrierungseinstellung
bool secure_set_calibration(int16_t slope, int16_t offset, bool privileged) {
// SICHER: Berechtigung erfordern
if (!privileged) {
return false;
}
// SICHER: Änderung nach Sperre verhindern
if (thermal_calibration.locked) {
return false;
}
// SICHER: Parameterbereiche validieren
if (slope < MIN_SLOPE || slope > MAX_SLOPE) {
return false;
}
if (offset < MIN_OFFSET || offset > MAX_OFFSET) {
return false;
}
thermal_calibration.slope = slope;
thermal_calibration.offset = offset;
return true;
}
// SICHER: Kalibrierung nach Initialisierung sperren
void secure_lock_calibration(void) {
thermal_calibration.locked = true;
}
int16_t secure_read_temperature(uint16_t raw_reading) {
int32_t temp = (thermal_calibration.slope * raw_reading) +
thermal_calibration.offset;
return (int16_t)temp;
}
bool secure_check_thermal_limit(uint16_t raw_reading) {
int16_t temp = secure_read_temperature(raw_reading);
return temp >= thermal_calibration.threshold;
}
// SICHER: Initialisierungssequenz
void secure_sensor_init(int16_t cal_slope, int16_t cal_offset) {
// Nur während des Boots, aus vertrauenswürdigem Code
if (secure_set_calibration(cal_slope, cal_offset, true)) {
secure_lock_calibration();
} else {
// Sichere Standardwerte verwenden wenn Kalibrierung fehlschlägt
// Nicht sperren - ermöglicht Wiederherstellung mit gültigen Parametern
}
}
CVE-Beispiele
- CVE-2020-8703: Unsachgemäße Eingabevalidierung im Thermalsubsystem ermöglichte Manipulation von Temperaturmesswerten.
- CVE-2019-0151: Unzureichende Zugriffskontrolle auf Leistungssensorparameter in bestimmten Intel-Prozessoren.
Verwandte CWEs
- CWE-862: Missing Authorization (Eltern)
- CWE-1299: Missing Protection Mechanism for Alternate Hardware Interface (Peer)
- CWE-1198: Privilege Separation and Access Control Issues (Kategorie)
- CWE-1206: Power, Clock, Thermal, and Reset Concerns (Kategorie)
Referenzen
- MITRE Corporation. "CWE-1314: Missing Write Protection for Parametric Data Values." https://cwe.mitre.org/data/definitions/1314.html
- Intel. "Thermal Management Specifications"
- JEDEC. "Power Management Standards"