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
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Modify Memory; Modify Application Data - Hardware manipulation can cause memory corruption through techniques like Rowhammer. |
| Integrity | Scope: Integrity Bypass Protection Mechanism - Fault injection can bypass security checks including cryptographic operations. |
| Confidentiality | Scope: 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
Related CWEs
- 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
- MITRE Corporation. "CWE-1256: Improper Restriction of Software Interfaces to Hardware Features." https://cwe.mitre.org/data/definitions/1256.html
- Plundervolt: Software-based Fault Injection Attacks against Intel SGX
- PLATYPUS: Software-based Power Side-Channel Attacks on x86
- Rowhammer: Flipping Bits in Memory Without Accessing Them