Improper Restriction of Software Interfaces to Hardware Features

Description

Improper Restriction of Software Interfaces to Hardware Features occurs when a product allows software control over device functionality like power and clock management without properly restricting access. This can enable attackers to modify hardware memory/registers or exploit physical side channels without requiring physical device access. Modern chipsets include software-accessible power and frequency scaling for mobile devices, but these features create security risks including fault injection attacks and side-channel analysis using built-in power metering.

Risk

Unrestricted hardware interfaces have severe security implications. Voltage manipulation enables fault injection (Plundervolt). Power metering allows side-channel attacks (PLATYPUS). Rowhammer attacks cause memory bit flips. CPU frequency manipulation disrupts timing. Thermal controls may cause instability. Debug interfaces may be accessible. Security enclaves may be compromised. Privilege escalation becomes possible through hardware manipulation.

Solution

Ensure proper access control mechanisms protect software-controllable features altering physical operating conditions such as clock frequency and voltage. Restrict access to DVFS interfaces. Limit power metering precision. Implement memory refresh rate controls. Require privileges for hardware control interfaces. Monitor for abnormal hardware manipulation. Implement rate limiting on hardware control operations. Use hardware security modules for sensitive operations.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Modify Memory; Modify Application Data - Hardware manipulation can cause memory corruption through techniques like Rowhammer.
IntegrityScope: Integrity

Bypass Protection Mechanism - Fault injection can bypass security checks including cryptographic operations.
ConfidentialityScope: Confidentiality

Read Memory - Power side-channel attacks can extract cryptographic keys and sensitive data.

Example Code

Vulnerable Code

// Vulnerable: Unrestricted access to voltage control

#include <stdint.h>

// Plundervolt-style attack vector
#define MSR_VOLTAGE_CONTROL 0x150

void vulnerable_voltage_interface(void) {
    // VULNERABLE: Any process can read/write voltage MSR
    // No privilege check or access restriction

    uint64_t voltage = rdmsr(MSR_VOLTAGE_CONTROL);

    // Attacker can undervolt to cause faults
    wrmsr(MSR_VOLTAGE_CONTROL, voltage - 0x100);

    // Execute security-critical operation during undervolt
    // Fault may cause incorrect computation/bypass
}

// Vulnerable: Unrestricted RAPL (power metering) access
#define MSR_RAPL_POWER_UNIT 0x606
#define MSR_PKG_ENERGY_STATUS 0x611

void vulnerable_rapl_access(void) {
    // VULNERABLE: High-precision power readings available
    // Can be used for power side-channel attacks (PLATYPUS)

    uint64_t energy_before = rdmsr(MSR_PKG_ENERGY_STATUS);

    // Target operation (e.g., AES encryption)
    perform_crypto_operation();

    uint64_t energy_after = rdmsr(MSR_PKG_ENERGY_STATUS);

    // VULNERABLE: Energy difference reveals operation details
    uint64_t energy_consumed = energy_after - energy_before;
    // Attacker correlates power with key bits
}

// Vulnerable: Unrestricted cache flush
void vulnerable_cache_control(void) {
    // VULNERABLE: CLFLUSH available to unprivileged code
    // Enables Rowhammer attacks and cache timing attacks

    volatile char* target = (volatile char*)0x12340000;

    while (1) {
        // Repeatedly flush and access to cause bit flips
        _mm_clflush((void*)target);
        *target;
        _mm_clflush((void*)(target + 4096));
        *(target + 4096);
        // VULNERABLE: Can cause DRAM bit flips (Rowhammer)
    }
}

// Vulnerable: Unrestricted frequency scaling
void vulnerable_frequency_control(void) {
    // VULNERABLE: Software can change CPU frequency
    // Can be used for timing attacks or fault injection

    // Request maximum frequency
    write_freq_request(MAX_FREQ);

    // Or request minimum to slow security checks
    write_freq_request(MIN_FREQ);

    // Rapid switching may cause instability
}
// Vulnerable: Hardware with unrestricted control interfaces

module vulnerable_power_controller (
    input wire clk,
    input wire reset_n,
    // VULNERABLE: No privilege checking
    input wire [7:0] voltage_request,
    input wire [7:0] frequency_request,
    input wire control_valid,
    output reg [7:0] voltage_setting,
    output reg [7:0] frequency_setting
);

    // VULNERABLE: Direct control without restrictions
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            voltage_setting <= 8'd128;    // Nominal voltage
            frequency_setting <= 8'd128;  // Nominal frequency
        end
        else if (control_valid) begin
            // VULNERABLE: Accept any voltage/frequency without checking
            // - No minimum/maximum bounds
            // - No privilege verification
            // - No rate limiting
            voltage_setting <= voltage_request;
            frequency_setting <= frequency_request;
        end
    end

    // No monitoring for fault injection patterns
    // No protection against rapid changes

endmodule

// Vulnerable: Unrestricted power metering
module vulnerable_power_meter (
    input wire clk,
    input wire reset_n,
    input wire [15:0] power_sense,
    input wire read_request,
    output reg [31:0] energy_counter,
    output reg [15:0] power_reading
);

    // VULNERABLE: High-resolution power readings accessible
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            energy_counter <= 32'h0;
            power_reading <= 16'h0;
        end
        else begin
            // Accumulate high-resolution energy
            energy_counter <= energy_counter + power_sense;

            // VULNERABLE: Return precise power reading
            if (read_request) begin
                power_reading <= power_sense;
            end
        end
    end

    // No access control
    // No resolution limiting
    // Enables power side-channel attacks

endmodule

Fixed Code

// Fixed: Restricted access to hardware control interfaces

#include <stdint.h>

// Fixed: Voltage control with restrictions
int secure_voltage_interface(uint64_t new_voltage, int privilege_level) {
    // FIXED: Require elevated privileges
    if (privilege_level < PRIVILEGE_KERNEL) {
        return -EPERM;
    }

    // FIXED: Validate voltage range
    if (new_voltage < VOLTAGE_MIN || new_voltage > VOLTAGE_MAX) {
        return -EINVAL;
    }

    // FIXED: Rate limiting
    static uint64_t last_change_time = 0;
    uint64_t current_time = get_current_time();

    if (current_time - last_change_time < VOLTAGE_CHANGE_COOLDOWN) {
        return -EAGAIN;
    }

    // FIXED: Log voltage change
    audit_log("Voltage change: %llx by privilege %d", new_voltage, privilege_level);

    // Perform controlled voltage change
    wrmsr(MSR_VOLTAGE_CONTROL, new_voltage);
    last_change_time = current_time;

    return 0;
}

// Fixed: Restricted RAPL access
int secure_rapl_access(uint64_t* energy, int privilege_level) {
    // FIXED: Require elevated privileges for precise readings
    if (privilege_level < PRIVILEGE_ADMIN) {
        return -EPERM;
    }

    uint64_t raw_energy = rdmsr(MSR_PKG_ENERGY_STATUS);

    // FIXED: Reduce resolution to prevent side-channel attacks
    // Round to nearest 1mJ instead of microjoule precision
    *energy = (raw_energy / 1000) * 1000;

    // FIXED: Add noise to readings
    *energy += get_random() % 1000;

    return 0;
}

// Fixed: Restricted cache control
int secure_cache_flush(void* addr, size_t size, int privilege_level) {
    // FIXED: Require kernel privilege for cache flush
    if (privilege_level < PRIVILEGE_KERNEL) {
        return -EPERM;
    }

    // FIXED: Validate address range
    if (!is_valid_kernel_address(addr, size)) {
        return -EFAULT;
    }

    // FIXED: Rate limit to prevent Rowhammer
    static int flush_count = 0;
    static uint64_t window_start = 0;
    uint64_t current_time = get_current_time();

    if (current_time - window_start > RATE_LIMIT_WINDOW) {
        flush_count = 0;
        window_start = current_time;
    }

    if (++flush_count > MAX_FLUSHES_PER_WINDOW) {
        audit_log("Cache flush rate limit exceeded");
        return -EBUSY;
    }

    // Perform cache flush
    for (size_t i = 0; i < size; i += CACHE_LINE_SIZE) {
        _mm_clflush((char*)addr + i);
    }

    return 0;
}

// Fixed: Secure frequency control
int secure_frequency_control(uint64_t requested_freq, int privilege_level) {
    // FIXED: Require elevated privileges
    if (privilege_level < PRIVILEGE_ADMIN) {
        return -EPERM;
    }

    // FIXED: Validate frequency range
    if (requested_freq < FREQ_MIN || requested_freq > FREQ_MAX) {
        return -EINVAL;
    }

    // FIXED: Gradual frequency changes only
    uint64_t current_freq = read_current_frequency();
    uint64_t max_step = FREQ_MAX_STEP;

    if (abs(requested_freq - current_freq) > max_step) {
        // Step gradually to prevent fault injection
        requested_freq = current_freq +
            (requested_freq > current_freq ? max_step : -max_step);
    }

    write_freq_request(requested_freq);

    return 0;
}
// Fixed: Hardware with secure control interfaces

module secure_power_controller (
    input wire clk,
    input wire reset_n,
    input wire [1:0] privilege_level,  // 0=user, 1=kernel, 2=secure
    input wire [7:0] voltage_request,
    input wire [7:0] frequency_request,
    input wire control_valid,
    output reg [7:0] voltage_setting,
    output reg [7:0] frequency_setting,
    output reg access_denied,
    output reg rate_limit_exceeded
);

    // FIXED: Privilege level required for hardware control
    parameter REQUIRED_PRIVILEGE = 2'd2;  // Secure mode only

    // FIXED: Valid voltage/frequency ranges
    parameter VOLTAGE_MIN = 8'd96;   // ~75% nominal
    parameter VOLTAGE_MAX = 8'd160;  // ~125% nominal
    parameter FREQ_MIN = 8'd32;
    parameter FREQ_MAX = 8'd224;

    // FIXED: Rate limiting
    reg [15:0] change_cooldown;
    parameter COOLDOWN_CYCLES = 16'd10000;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            voltage_setting <= 8'd128;
            frequency_setting <= 8'd128;
            access_denied <= 1'b0;
            rate_limit_exceeded <= 1'b0;
            change_cooldown <= 16'h0;
        end
        else begin
            // Decrement cooldown
            if (change_cooldown > 0) begin
                change_cooldown <= change_cooldown - 1;
            end

            access_denied <= 1'b0;
            rate_limit_exceeded <= 1'b0;

            if (control_valid) begin
                // FIXED: Check privilege level
                if (privilege_level < REQUIRED_PRIVILEGE) begin
                    access_denied <= 1'b1;
                end
                // FIXED: Check rate limit
                else if (change_cooldown > 0) begin
                    rate_limit_exceeded <= 1'b1;
                end
                // FIXED: Validate voltage range
                else if (voltage_request < VOLTAGE_MIN ||
                         voltage_request > VOLTAGE_MAX) begin
                    access_denied <= 1'b1;
                end
                // FIXED: Validate frequency range
                else if (frequency_request < FREQ_MIN ||
                         frequency_request > FREQ_MAX) begin
                    access_denied <= 1'b1;
                end
                else begin
                    // FIXED: Apply controlled change
                    voltage_setting <= voltage_request;
                    frequency_setting <= frequency_request;
                    change_cooldown <= COOLDOWN_CYCLES;
                end
            end
        end
    end

endmodule

// Fixed: Secure power metering with reduced precision
module secure_power_meter (
    input wire clk,
    input wire reset_n,
    input wire [15:0] power_sense,
    input wire read_request,
    input wire [1:0] privilege_level,
    input wire [7:0] random_noise,  // External TRNG
    output reg [31:0] energy_counter,
    output reg [15:0] power_reading,
    output reg access_denied
);

    parameter REQUIRED_PRIVILEGE = 2'd1;  // Kernel required

    // Internal high-resolution counter
    reg [47:0] internal_energy;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            internal_energy <= 48'h0;
            energy_counter <= 32'h0;
            power_reading <= 16'h0;
            access_denied <= 1'b0;
        end
        else begin
            // Always accumulate (internal)
            internal_energy <= internal_energy + power_sense;

            access_denied <= 1'b0;

            if (read_request) begin
                // FIXED: Check privilege
                if (privilege_level < REQUIRED_PRIVILEGE) begin
                    access_denied <= 1'b1;
                    power_reading <= 16'h0;
                    energy_counter <= 32'h0;
                end
                else begin
                    // FIXED: Reduce precision (top 32 of 48 bits)
                    // FIXED: Add noise to prevent side-channel
                    energy_counter <= internal_energy[47:16] +
                                     {24'h0, random_noise};

                    // FIXED: Coarse power reading only
                    power_reading <= {power_sense[15:8], 8'h00} +
                                    {8'h0, random_noise};
                end
            end
        end
    end

endmodule

CVE Examples

  • CVE-2019-11157 (Plundervolt): Intel processor voltage setting vulnerability enabling privilege escalation and security enclave bypass
  • CVE-2020-8694/8695 (PLATYPUS): RAPL interface access control issues allowing power side-channel attacks
  • CVE-2015-0565: NaCl allowed CLFLUSH instruction, enabling Rowhammer attacks

  • CWE-285: Improper Authorization (parent)
  • CWE-1300: Improper Protection of Physical Side Channels (related)
  • CWE-1247: Improper Protection Against Voltage and Clock Glitches (related)
  • CAPEC-624: Hardware Fault Injection (attack pattern)
  • CAPEC-625: Mobile Device Fault Injection (attack pattern)

References

  1. MITRE Corporation. "CWE-1256: Improper Restriction of Software Interfaces to Hardware Features." https://cwe.mitre.org/data/definitions/1256.html
  2. Plundervolt: Software-based Fault Injection Attacks against Intel SGX
  3. PLATYPUS: Software-based Power Side-Channel Attacks on x86
  4. Rowhammer: Flipping Bits in Memory Without Accessing Them