Insufficient Signature Verification
id: LS18C
title: Insufficient Signature Verification
baseSeverity: C
category: authentication
language: solidity
blockchain: [ethereum, polygon, bsc, arbitrum, optimism]
impact: Unauthorized access, forged approvals, stolen funds
status: draft
complexity: medium
attack_vector: external
mitigation_difficulty: medium
versions: [">=0.6.0", "<=0.8.25"]
cwe: CWE-347
swc: SWC-117
π Description
- Insufficient signature verification vulnerabilities arise when a contract improperly checks digital signatures, either by:
- Failing to verify that the signer is the authorized party.
- Omitting replay protection (e.g., nonce).
- Allowing incorrect or incomplete message construction.
- This flaw can result in unauthorized access, fund transfers, or malicious relays of signed messages.
- It commonly affects permit functions, off-chain authorization flows, and meta-transactions.
π¨ Vulnerable Code
contract InsecureSigner {
function execute(address target, bytes calldata data, bytes memory signature) external {
bytes32 message = keccak256(abi.encodePacked(target, data));
address signer = recoverSigner(message, signature);
// β No check to ensure signer is authorized
(bool success, ) = target.call(data);
require(success, "Execution failed");
}
function recoverSigner(bytes32 message, bytes memory sig) public pure returns (address) {
return ECDSA.recover(ECDSA.toEthSignedMessageHash(message), sig);
}
}
π§ͺ Exploit Scenario
Step-by-step exploit process:
- Attacker generates a signature offline or reuses a leaked one.
- Sends the signature with execute() call to the vulnerable contract.
- Contract recovers a valid signer address but never checks if the signer is authorized.
- Attacker hijacks execution to arbitrary target with crafted calldata.
Assumptions:
- Weak or incomplete signature verification can allow malicious actors to execute unauthorized transactions.
- If the contract does not enforce nonce or timestamp validation, replay attacks become feasible.
β Fixed Code
contract SecureSigner {
mapping(address => bool) public authorizedSigners;
mapping(bytes32 => bool) public usedMessages;
function execute(address target, bytes calldata data, bytes memory signature) external {
bytes32 message = keccak256(abi.encodePacked(msg.sender, target, data));
require(!usedMessages[message], "Replay detected");
address signer = recoverSigner(message, signature);
require(authorizedSigners[signer], "Invalid signer");
usedMessages[message] = true;
(bool success, ) = target.call(data);
require(success, "Execution failed");
}
function recoverSigner(bytes32 message, bytes memory sig) public pure returns (address) {
return ECDSA.recover(ECDSA.toEthSignedMessageHash(message), sig);
}
}
π§ Contextual Severity
- context: "Permit-based approval, meta-transactions, or bridge authentication"
severity: C
reasoning: "Leads to total compromise of user assets or impersonation"
- context: "Testnet demo or UI-only logic"
severity: L
reasoning: "No meaningful risk beyond demonstration scope"
- context: "System uses EIP-712 with domain separation and nonce"
severity: I
reasoning: "Fully mitigated"
π‘οΈ Prevention
Primary Defenses
- Always verify the identity of the recovered signer.
- Use nonces or message hashes to prevent replay attacks.
- Include contextual domain data (e.g., msg.sender, chainId, contract address) in the signed message.
Additional Safeguards
- Implement EIP-712 structured data signatures for clarity and security.
- Use OpenZeppelinβs SignatureChecker and ECDSA libraries.
- Add expiry timestamps to signed messages.
Detection Methods
- Manual review of recover and ecrecover logic.
- Static analysis using Slither (insecure-signature) or Mythril symbolic execution.
- Check for presence of replay protection and signer verification logic.
π°οΈ Historical Exploits
- Name: Odos Protocol Exploit
- Date: 2024-04-15
- Loss: Approximately $50,000
- Post-mortem: Link to post-mortem
- Name: Wormhole Bridge Hack
- Date: 2022-02-02
- Loss: Over $320 million
- Post-mortem: Link to post-mortem
π Further Reading
- SWC-122: Insecure Signature Verification
- OpenZeppelin β ECDSA Utilities
- EIP-712: Structured Data Hashing and Signing
β Vulnerability Report
id: LS18C
title: Insufficient Signature Verification
severity: H
score:
impact: 5
exploitability: 4
reachability: 4
complexity: 3
detectability: 3
finalScore: 4.25
π Justifications & Analysis
- Impact: Can allow arbitrary contract execution, minting, or asset transfer.
- Exploitability: Easily triggered if signature recovery lacks validation.
- Reachability: Common in relayers, permit()-style flows, and governance voting.
- Complexity: Medium; requires signing knowledge, but scripts and tools exist.
- Detectability: Partially detectable via audit tools; full coverage needs manual review.