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

AuswirkungDetails
VerfügbarkeitBereich: 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

  1. MITRE Corporation. "CWE-1314: Missing Write Protection for Parametric Data Values." https://cwe.mitre.org/data/definitions/1314.html
  2. Intel. "Thermal Management Specifications"
  3. JEDEC. "Power Management Standards"