Kuboid
Open Luck·Kuboid.in

Web2 Meets Web3: Hacking Decentralized Applications

DEFCONConference3,412 views24:15over 1 year ago

This talk demonstrates how traditional Web2 vulnerabilities, such as XSS, DNS hijacking, and business logic errors, can be leveraged to compromise decentralized applications (dApps) and their associated smart contracts. It analyzes the attack surface of dApps, focusing on the interaction between client-side interfaces, backend APIs, and on-chain smart contract functions. The speaker highlights how improper handling of transaction states and asset classes in backend systems can lead to critical financial losses. Practical examples include exploiting race conditions in gaming dApps and bypassing address validation in cross-chain bridges.

Why Your Web2 Backend is the Biggest Vulnerability in Your Web3 Stack

TLDR: Decentralized applications are increasingly relying on complex Web2 backends to manage user interactions, creating a massive, often overlooked, attack surface. By exploiting traditional vulnerabilities like race conditions, business logic flaws, and improper API validation, attackers can drain funds or manipulate state without ever touching a smart contract. Pentesters should pivot their focus from purely on-chain auditing to the integration points between traditional web infrastructure and blockchain protocols.

Security researchers often treat smart contracts as the only point of failure in the decentralized ecosystem. While auditing Solidity code is necessary, it ignores the reality that most modern dApps are essentially Web2 applications with a blockchain-based database. When you look at the architecture of a typical dApp, you find a standard stack: a frontend, a backend API, and a database, all communicating with an on-chain smart contract. The vulnerability isn't always in the contract itself; it is often in the glue that connects the two worlds.

The Illusion of On-Chain Security

Many developers assume that because a transaction is eventually recorded on a public ledger, the backend logic handling that transaction is inherently secure. This is a dangerous misconception. If a backend API is responsible for triggering a smart contract function, it acts as a gatekeeper. If that gatekeeper is poorly implemented, the entire security model collapses.

Consider the case of a cross-chain bridge. These systems rely on a backend to monitor events on a source chain and trigger a release of funds on a destination chain. If the backend fails to validate the smart contract address on the source chain, an attacker can deploy a malicious contract that mimics the interface of the legitimate one. By making a deposit into their own malicious contract, they can trick the backend into believing a legitimate deposit occurred, triggering the release of funds on the destination chain. This is not a bug in the bridge's smart contract; it is a failure of the backend to perform basic input validation, a classic OWASP A03:2021-Injection scenario.

Exploiting Backend Logic

The most effective attacks on dApps today leverage the latency inherent in blockchain networks. Because block times are non-zero, there is a window of opportunity between a transaction being submitted and it being confirmed. If a backend updates a user's internal balance only after a transaction is confirmed, but fails to lock that balance during the pending state, you have a race condition.

An attacker can initiate multiple withdrawal requests in rapid succession. If the backend does not account for the pending state of the first request, it may authorize subsequent withdrawals based on an outdated balance. This is a standard business logic error that has been exploited in traditional banking systems for decades. In the context of a dApp, the impact is immediate and irreversible financial loss.

The Asset Class Mismatch

Another critical area for researchers is how backends handle different asset classes. A backend might be configured to recognize a specific token, like ETH or a stablecoin, as a valid deposit. However, if the backend logic is too broad, it might treat any token sent to a deposit address as a valid deposit.

Attackers can exploit this by sending worthless tokens or even malicious NFTs to a deposit address. If the backend uses a generic API like the Fireblocks API to query transaction data, it might misinterpret the incoming asset. If the backend fails to check the token type or the contract address of the incoming asset, it may credit the user's account with the value of a legitimate token, effectively allowing them to mint their own balance. This is a failure of OWASP A01:2021-Broken Access Control, where the system fails to enforce the boundary between authorized and unauthorized assets.

Testing the Integration Point

When you are on an engagement, stop treating the dApp as a black box. Start by mapping the API endpoints that interact with the blockchain. Use Burp Suite to intercept the traffic between the frontend and the backend. Look for requests that trigger on-chain actions. Are these requests properly authenticated? Does the backend perform server-side validation of the transaction parameters, or does it blindly trust the data provided by the client?

If you find an API that accepts an address as a parameter, test it for standard injection vulnerabilities. If you find an API that handles deposits, test it with various token types to see how the backend responds. The goal is to find the discrepancy between what the backend thinks is happening on-chain and what is actually happening.

Defensive Hardening

Defending against these attacks requires a shift in mindset. Backend developers must treat all data coming from the blockchain as untrusted, just as they would treat data coming from a user. Every interaction with a smart contract must be verified on the backend. This means checking the transaction status, the sender and receiver addresses, the token type, and the amount, and ensuring that the smart contract involved is the one the team actually deployed.

Furthermore, implement strict state management. If a user initiates a withdrawal, their balance must be locked or decremented immediately in the backend database, regardless of the blockchain's confirmation time. This prevents the race conditions that lead to double-spending or unauthorized withdrawals.

The next time you are auditing a dApp, look past the Solidity code. The most interesting bugs are often found in the mundane Web2 code that developers thought was safe because it was "just an API." The blockchain is immutable, but the code that drives it is just as fragile as any other software. Keep digging into those integration points, because that is where the real value is hidden.

Talk Type
talk
Difficulty
intermediate
Category
web security
Has Demo Has Code Tool Released


DEF CON 32

260 talks · 2024
Browse conference →
Premium Security Audit

We break your app before they do.

Professional penetration testing and vulnerability assessments by the Kuboid Secure Layer team. Securing your infrastructure at every layer.

Get in Touch
Official Security Partner
kuboid.in