Inclusion of Undocumented Features or Chicken Bits
Description
Inclusion of Undocumented Features or Chicken Bits occurs when a device includes chicken bits or undocumented features that can create entry points for unauthorized actors. Devices often incorporate undocumented bits—colloquially called "chicken bits"—to disable functional security features for debugging and testing purposes. These mechanisms facilitate quick identification of faulty components or features that negatively impact performance. Similar vulnerabilities arise through implementation of undocumented features themselves. When these features remain in production devices, they can be discovered and exploited by attackers.
Risk
Undocumented features and chicken bits have severe security implications. Security features may be disableable through hidden bits. Debug access may be available in production. Backdoors may exist in hardware or firmware. Secure boot may be bypassable. Memory protection may be disableable. Encryption may be bypassable. Privilege escalation may be possible. Supply chain attacks may exploit hidden functionality.
Solution
The implementation of chicken bits in a released product is highly discouraged. If implemented, ensure they remain disabled in production devices. Document all device interfaces comprehensively. Remove or fuse-disable debug features before production. Conduct thorough security audits for undocumented functionality. Implement secure manufacturing processes. Test for undocumented feature discovery. Use hardware fuses to permanently disable debug features.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality, Integrity, Availability, Access Control | Scope: All Multiple impacts including memory modification, unauthorized reads, execution of unauthorized code, privilege escalation, identity assumption, and bypass of protection mechanisms. |
Example Code
Vulnerable Code
// Vulnerable: Chicken bits to disable security features
module vulnerable_security_controller (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [7:0] register_addr,
// Security features
output reg secure_boot_enabled,
output reg memory_encryption_enabled,
output reg debug_locked,
output reg access_control_enabled
);
// VULNERABLE: Undocumented register at address 0xFF
// Contains "chicken bits" to disable security
reg [31:0] chicken_bits;
// Normal security configuration
reg [31:0] security_config;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
security_config <= 32'hFFFFFFFF; // All security enabled
chicken_bits <= 32'h0;
end
else if (write_enable) begin
case (register_addr)
8'h00: security_config <= write_data;
// VULNERABLE: Undocumented address
8'hFF: chicken_bits <= write_data;
endcase
end
end
// Security features can be disabled via chicken bits!
always @(*) begin
// Normal security setting AND NOT chicken bit override
secure_boot_enabled = security_config[0] && !chicken_bits[0];
memory_encryption_enabled = security_config[1] && !chicken_bits[1];
debug_locked = security_config[2] && !chicken_bits[2];
access_control_enabled = security_config[3] && !chicken_bits[3];
end
// Attack: Write 0xF to address 0xFF to disable all security
endmodule
// Vulnerable: Hidden UART debug interface
module vulnerable_hidden_debug (
input wire clk,
input wire reset_n,
input wire uart_rx,
output reg uart_tx,
// Memory interface
output reg [31:0] debug_addr,
output reg [31:0] debug_wdata,
output reg debug_write,
output reg [31:0] debug_rdata
);
reg [7:0] command_buffer [0:15];
reg [3:0] cmd_index;
// VULNERABLE: Undocumented UART commands
parameter CMD_READ_MEM = 8'hA5;
parameter CMD_WRITE_MEM = 8'h5A;
parameter CMD_EXEC_CODE = 8'hE0; // Execute arbitrary code!
parameter CMD_DISABLE_SEC = 8'hD5; // Disable security!
always @(posedge clk) begin
if (uart_byte_received) begin
command_buffer[cmd_index] <= uart_data;
cmd_index <= cmd_index + 1;
// Process command when complete
if (cmd_index == 5) begin
case (command_buffer[0])
CMD_READ_MEM: begin
debug_addr <= {command_buffer[1], command_buffer[2],
command_buffer[3], command_buffer[4]};
// Returns memory contents via UART
end
CMD_WRITE_MEM: begin
debug_addr <= {command_buffer[1], command_buffer[2],
command_buffer[3], command_buffer[4]};
debug_wdata <= uart_data;
debug_write <= 1'b1;
end
CMD_DISABLE_SEC: begin
// VULNERABLE: Disables security without authentication!
security_disabled <= 1'b1;
end
endcase
end
end
end
endmodule
// Vulnerable: Undocumented test mode
module vulnerable_test_mode (
input wire clk,
input wire reset_n,
input wire [3:0] gpio_pins,
output reg test_mode_active,
output reg security_bypass
);
// VULNERABLE: Secret GPIO sequence enables test mode
parameter SECRET_SEQUENCE = 12'hA5A;
reg [11:0] gpio_history;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
gpio_history <= 12'h0;
test_mode_active <= 1'b0;
security_bypass <= 1'b0;
end
else begin
gpio_history <= {gpio_history[7:0], gpio_pins};
// VULNERABLE: Secret sequence activates test mode
if (gpio_history == SECRET_SEQUENCE) begin
test_mode_active <= 1'b1;
security_bypass <= 1'b1; // All security disabled!
end
end
end
endmodule
// Vulnerable: Firmware with undocumented features
// VULNERABLE: Hidden debug command interface
#define SECRET_DEBUG_PORT 0xDEAD
#define SECRET_COMMAND_KEY 0xCAFEBABE
struct hidden_command {
uint32_t magic; // Must be SECRET_COMMAND_KEY
uint8_t command;
uint32_t address;
uint32_t data;
};
void process_network_packet(uint8_t* data, size_t len) {
// Normal packet processing
handle_normal_packet(data, len);
// VULNERABLE: Check for hidden debug commands
if (len >= sizeof(struct hidden_command)) {
struct hidden_command* cmd = (struct hidden_command*)data;
if (cmd->magic == SECRET_COMMAND_KEY) {
// Undocumented debug commands - no authentication!
switch (cmd->command) {
case 0x01: // Read memory
send_response(*(uint32_t*)cmd->address);
break;
case 0x02: // Write memory
*(uint32_t*)cmd->address = cmd->data;
break;
case 0x03: // Disable secure boot
disable_secure_boot_check = true;
break;
case 0x04: // Execute code
((void(*)(void))cmd->address)();
break;
}
}
}
}
// VULNERABLE: Chicken bit in configuration
#define SECURITY_CONFIG_REG 0x40001000
#define CHICKEN_BIT_DISABLE_ENCRYPTION (1 << 31) // Undocumented!
void vulnerable_init(void) {
// Someone might discover and set the chicken bit
// Disables encryption entirely
}
Fixed Code
// Fixed: No chicken bits in production hardware
module secure_security_controller (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [7:0] register_addr,
input wire production_fuse, // Blown in production
// Security features - always enabled in production
output wire secure_boot_enabled,
output wire memory_encryption_enabled,
output wire debug_locked,
output wire access_control_enabled
);
reg [31:0] security_config;
`ifdef DEBUG_BUILD
// Debug chicken bits - ONLY in debug builds
reg [31:0] debug_override;
`endif
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
security_config <= 32'hFFFFFFFF;
`ifdef DEBUG_BUILD
debug_override <= 32'h0;
`endif
end
else if (write_enable) begin
case (register_addr)
8'h00: security_config <= write_data;
`ifdef DEBUG_BUILD
8'hFF: if (!production_fuse) debug_override <= write_data;
`endif
// No chicken bits at 0xFF in production!
endcase
end
end
// Security features - no override in production
`ifdef DEBUG_BUILD
assign secure_boot_enabled = production_fuse ?
security_config[0] : (security_config[0] && !debug_override[0]);
// etc.
`else
// FIXED: Production build has no override capability
assign secure_boot_enabled = security_config[0];
assign memory_encryption_enabled = security_config[1];
assign debug_locked = security_config[2];
assign access_control_enabled = security_config[3];
`endif
endmodule
// Fixed: Debug interface removed or properly secured
module secure_debug_interface (
input wire clk,
input wire reset_n,
input wire debug_fuse_blown, // Permanent disable
input wire [255:0] debug_challenge,
input wire [255:0] debug_response,
input wire debug_auth_request,
output reg debug_authenticated,
output reg debug_enabled
);
// Debug only available if:
// 1. Fuse not blown (development only)
// 2. Proper cryptographic authentication
wire [255:0] expected_response;
wire response_valid;
crypto_auth auth (
.challenge(debug_challenge),
.response(debug_response),
.valid(response_valid),
.expected(expected_response)
);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
debug_authenticated <= 1'b0;
debug_enabled <= 1'b0;
end
else if (debug_fuse_blown) begin
// FIXED: Fuse permanently disables debug
debug_enabled <= 1'b0;
debug_authenticated <= 1'b0;
end
else if (debug_auth_request && response_valid) begin
// FIXED: Cryptographic authentication required
debug_authenticated <= 1'b1;
debug_enabled <= 1'b1;
end
end
endmodule
// Fixed: All registers documented, no hidden addresses
module secure_register_bank (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [7:0] register_addr,
output reg [31:0] read_data
);
// All registers are documented
reg [31:0] config_reg; // 0x00 - Documented
reg [31:0] status_reg; // 0x04 - Documented
reg [31:0] control_reg; // 0x08 - Documented
// No hidden registers!
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
config_reg <= 32'h0;
status_reg <= 32'h0;
control_reg <= 32'h0;
end
else if (write_enable) begin
case (register_addr)
8'h00: config_reg <= write_data;
8'h04: status_reg <= write_data;
8'h08: control_reg <= write_data;
// FIXED: Unknown addresses ignored, no hidden functionality
default: ; // Do nothing
endcase
end
end
always @(*) begin
case (register_addr)
8'h00: read_data = config_reg;
8'h04: read_data = status_reg;
8'h08: read_data = control_reg;
default: read_data = 32'h0; // Unknown returns zero
endcase
end
endmodule
// Fixed: No undocumented features in production firmware
// All commands documented, authenticated
typedef enum {
CMD_STATUS = 0x01,
CMD_CONFIG = 0x02,
CMD_RESET = 0x03
// No hidden commands!
} command_t;
void process_command(uint8_t cmd, void* data) {
// All commands require authentication
if (!is_authenticated()) {
return;
}
switch (cmd) {
case CMD_STATUS:
send_status();
break;
case CMD_CONFIG:
update_config(data);
break;
case CMD_RESET:
system_reset();
break;
default:
// FIXED: Unknown commands logged and rejected
log_security_event("Unknown command: %02x", cmd);
break;
}
}
// Production verification
void verify_no_debug_features(void) {
// Check debug fuses are blown
if (!is_debug_fuse_blown()) {
panic("Debug fuse not blown in production!");
}
// Verify no chicken bits exist
// (This is a compile-time check via build system)
#ifdef CHICKEN_BITS_ENABLED
#error "Chicken bits must not be enabled in production!"
#endif
// Verify all register addresses return expected values
for (uint32_t addr = 0; addr < 0x100; addr++) {
if (!is_documented_address(addr)) {
uint32_t value = read_register(addr);
if (value != 0 && value != 0xFFFFFFFF) {
panic("Undocumented register at 0x%02x has value!", addr);
}
}
}
}
CVE Examples
- Skorobogatov & Woods: "Breakthrough Silicon Scanning Discovers Backdoor in Military Chip"
- Domas: "God Mode Unlocked: Hardware Backdoors in x86 CPUs"
- Research on Siemens S7 silicon vulnerabilities
Related CWEs
- CWE-912: Hidden Functionality (parent)
- CWE-1198: Privilege Separation and Access Control Issues (category member)
- CWE-1371: ICS Supply Chain: Poorly Documented Features (category member)
- CWE-1209: Failure to Disable Reserved Bits (related)
References
- MITRE Corporation. "CWE-1242: Inclusion of Undocumented Features or Chicken Bits." https://cwe.mitre.org/data/definitions/1242.html
- CAPEC-212: Functionality Misuse
- CAPEC-36: Using Unpublished Interfaces or Functionality