How Was Socket Protocol Exploited?

Learn how Socket Protocol was exploited, resulting in a loss of assets worth $3.3 million.

Neptune Mutual
Neptune Mutual
4 min readJan 18, 2024

--

TL;DR

On January 16, 2024, the Socket Protocol was exploited on the Ethereum Mainnet, which resulted in a loss of over $3.3 million worth of assets.

Introduction to Socket

Socket is an interoperability protocol that powers seamless asset and data transfers for apps across blockchains.

Vulnerability Assessment

The root cause of the exploit is the incomplete validation of user inputs, which was exploited to steal funds from users who had token approvals for the vulnerable contracts.

Steps

Step 1:

We attempt to analyze one of the attack transactions executed by the exploiter.

Step 2:

The vulnerable WrappedTokenSwapperImpl contract was deployed just a couple of days prior to the occurrence of the incident.

Step 3:

In this contract, the performAction function uses the swapExtraData parameter without validating it before calling the target with this data.

function performAction(address fromToken, address toToken, uint256 amount, address receiverAddress, bytes32 metadata, bytes calldata swapExtraData) external payable override returns (uint256) {
uint256 _initialBalanceTokenOut;
uint256 _finalBalanceTokenOut;

// Swap Native to Wrapped Token
if (fromToken == NATIVE_TOKEN_ADDRESS) {
_initialBalanceTokenOut = ERC20(toToken).balanceOf(socketGateway);
(bool success, ) = toToken.call{value: amount}(swapExtraData);

if (!success) {
revert SwapFailed();
}

_finalBalanceTokenOut = ERC20(toToken).balanceOf(socketGateway);

require((_finalBalanceTokenOut - _initialBalanceTokenOut) == amount, "Invalid wrapper contract");

// Send weth to user
ERC20(toToken).transfer(receiverAddress, amount);
} else {
_initialBalanceTokenOut = address(socketGateway).balance;

// Swap Wrapped Token To Native Token
ERC20(fromToken).safeTransferFrom(msg.sender, socketGateway, amount);

(bool success, ) = fromToken.call(swapExtraData);

if (!success) {
revert SwapFailed();
}

_finalBalanceTokenOut = address(socketGateway).balance;

require((_finalBalanceTokenOut - _initialBalanceTokenOut) == amount, "Invalid wrapper contract");

// send ETH to the user
payable(receiverAddress).transfer(amount);
}

emit SocketSwapTokens(fromToken, toToken, amount, amount, Identifier, receiverAddress, metadata);

return amount;
}

Step 4:

As a result, the exploiter could craft a payload to invoke an arbitrary call to the transferFrom function from anyone that provided token approvals of a specified amount to the SocketGateway contract and then transfer these tokens directly to the attacker’s address.

Step 5:

Essentially, the affected function didn’t consider the case where the caller transfers in 0 WETH worth of assets, allowing the caller to specify other functions in the call and still bypassing the balance check.

Step 6:

The attacker used the fallback inside the SocketGateway contract to call and trigger the performAction function with routeId 406.

/// @notice fallback function to handle swap, bridge execution
/// @dev ensure routeId is converted to bytes4 and sent as msg.sig in the transaction
fallback() external payable {
address routeAddress = addressAt(uint32(msg.sig));

bytes memory result;

assembly {
// copy function selector and any arguments
calldatacopy(0, 4, sub(calldatasize(), 4))
// execute function call using the facet
result := delegatecall(gas(), routeAddress, 0, sub(calldatasize(), 4), 0, 0)
// get any return value
returndatacopy(0, 0, returndatasize())
// return any return value or error back to the caller
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}

Step 7:

The stolen funds are held at this address and include assets worth 1,138 ETH, amounting to approximately $2.91 million; 165,356 MATIC, which are worth $138,651; 2.8896 WBTC, worth $123,659; 42.4753 WETH, worth $108,645; and 13,821 DAI, all of which total $3,295,768.

Aftermath

The team acknowledged the occurrence of the incident and stated that the exploit affected wallets with infinite approvals for the Socket contracts. The team had subsequently paused the contract to minimize the extent of the damage caused.

The attack impacted approximately 712 users of the protocol that had granted unlimited approvals to the Socket contracts. As viewed in this transaction, the Socket Admin has already disabled the vulnerable contract with routeId 406.

Solution

To mitigate and prevent similar exploits in the future, it’s essential to adopt a comprehensive approach that encompasses both developer practices and user awareness. First and foremost, smart contract developers must not deploy contracts without thorough auditing by reputable audit firms. These audits help identify potential security vulnerabilities and weaknesses in the contract’s code that might otherwise go unnoticed.

Additionally, smart contract developers should always practice rigorous input validation. This means sanitizing all inputs to the contract, ensuring that they are of the expected type, format, and within expected ranges. Proper input validation can prevent attackers from exploiting vulnerabilities that arise from improperly validated inputs, such as the one seen in the Socket Protocol exploit.

From the user’s perspective, it is crucial to revoke approvals to the affected contracts immediately upon learning of such exploits. Users should regularly review and manage the token approvals they have granted to various third-party applications or protocols. This oversight reduces the risk of their assets being misused if a contract they interact with is compromised.

Despite the best efforts in implementing stringent security protocols, the risk of vulnerabilities being exploited remains. In such situations, Neptune Mutual plays an indispensable role. By setting up a dedicated cover pool with Neptune Mutual, the repercussions of incidents similar to the Socket Protocol attack can be significantly mitigated. Neptune Mutual offers coverage for losses stemming from smart contract vulnerabilities through its parametric policies.

Collaborating with Neptune Mutual streamlines the process for users by removing the need for them to submit extensive proof of loss. Once an incident has been confirmed and resolved using our comprehensive incident resolution framework, our priority shifts to swiftly compensating those impacted and providing them with immediate financial support.

Our marketplace extends across multiple major blockchain networks, including Ethereum, Arbitrum, and the BNB chain. This extensive coverage enables us to cater to a diverse array of DeFi users, offering them protection against potential vulnerabilities and thereby reinforcing their trust in the ecosystem.

Reference Source Hacken

About Us

Neptune Mutual project safeguards the Ethereum community from cyber threats. The protocol uses parametric cover as opposed to discretionary insurance. It has an easy and reliable on-chain claim process. This means that when incidents are confirmed by our community, resolution is fast.

Join us in our mission to cover, protect, and secure on-chain digital assets.

Official Website: https://neptunemutual.com
Blog:
https://neptunemutual.com/blog/
Twitter:
https://twitter.com/neptunemutual
Forums:
https://community.neptunemutual.com/
Telegram:
https://t.me/neptunemutual
Discord:
https://discord.gg/2qMGTtJtnW
YouTube:
https://www.youtube.com/c/NeptuneMutual
LinkedIn:
https://www.linkedin.com/company/neptune-mutual

--

--

Neptune Mutual
Neptune Mutual

Neptune Mutual provides you with guaranteed stablecoin liquidity to reduce risk exposure by hedging against capital risks and smart contract vulnerabilities.