Skip to content

Commit

Permalink
all attack vectors explained
Browse files Browse the repository at this point in the history
  • Loading branch information
harendra-shakya committed Dec 1, 2022
1 parent 9398457 commit 0d7e490
Show file tree
Hide file tree
Showing 50 changed files with 420 additions and 87 deletions.
139 changes: 60 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
// TODO: Add and explain all the attack vectors exists on this planet.

## List of Security Vulnerabilities

> Author: Harendra Shakya ([LinkTree](https://linktr.ee/harendra_shakya))
- Reentrancy
- Oracle Manipulation
- Access Control
- [Access Control](attack-vectors/Access_Control.md)
- Authentication With tx.origin
- Default Visibility
- Signature Verification
Expand All @@ -15,96 +11,81 @@
- Missed Modifier
- Incorrect Modifier Names
- Overpowered Roles
- Signature Replay
- Unsafe Delegatecalls
- Sandwich Attacks
- Flash Loan Attacks
- Griefing
- Force Feeding
- Account Existence Check for low level calls
- Cross-Chain Bridge manipulation
- Insecure Randomness
- Accessing Private Data
- Authentication With tx.origin
- Delegatecall
- Integer Arithmetic
- Block timestamp Manipulation
- Unsafe external calls
- Unchecked return values
- Proxy Storage Collision
- Floating Point Arithmetic
- Code Injection via delegatecall
- Unchecked External Calls
- Insufficient Gas Attacks
- DOS
- [Account Existence Check for low level calls](attack-vectors/Account_Existence_Check_for_low_level_calls.md)
- [Arbitrary Jumps with Function Variables](attack-vectors/Arbitrary_Jumps_with_Function_Variables.md)
- [Assert Violation](attack-vectors/Assert_Violation.md)
- [Bypass Contract Size Check](attack-vectors/Bypass_Contract_Size_Check.md)
- [Code With No Effects](attack-vectors/Code_With_No_Effects.md)
- [Complex Modifiers](attack-vectors/Complex_Modifiers.md)
- [DOS](attack-vectors/DOS.md)
- Unexpected Revert
- Block Gas Limit
- External Calls without Gas Stipends
- Offline Owner
- Entropy Illusion
- Privacy Illusion
- Miner Attacks
- Transaction Ordering / Frontrunning
- Timestamp Manipulation
- Unexpected Ether
- External Contract Referencing
- Uninitialized Storage Pointers
- Writes to Arbitrary Storage Locations
- Incorrect Interface
- Arbitrary Jumps with Function Variables
- Variable Shadowing
- Assert Violation
- Dirty Higher Order Bits
- Complex Modifiers
- Outdated Compiler
- Use of Deprecated Solidity Functions
- Function Selector Abuse
- Experimental Language Features
- Constructor call
- Frontend (Off Chain) Attacks
- [Dirty Higher Order Bits](attack-vectors/Dirty_Higher_Order_Bits.md)
- [Entropy Illusion / Insecure Randomness](attack-vectors/Entropy_Illusion.md)
- [Experimental Language Features](attack-vectors/Entropy_Illusion.md)
- [External Contract Referencing](attack-vectors/External_Contrac_Referencing.md)
- [Flash Loan Attacks](attack-vectors/Flash_Loan_Attack.md)
- [Floating Point Arithmetic](attack-vectors/Floating_Point_Arithmetic.md)
- [Frontend (Off Chain) Attacks](<attack-vectors/Frontend_(Off_Chain)_Attacks.md>)
- Short Address Attack
- Historic Attacks
- [Force Feeding](attack-vectors/Force_Feeding.md)
- [Function Selector Abuse](attack-vectors/Function_Selector_Abuse.md)
- [Griefing](attack-vectors/Griefing.md)
- [Hiding Malicious Code](attack-vectors/Hidden_malicious_code.md)
- [Historic Attacks](attack-vectors/Historic_Attacks.md)
- Constructor Names
- Call Depth Attack
- Constantinople Reentrancy
- Solidity Abi Encoder v2 Bug
- Payable Multicall
- Bypass Contract Size Check
- Code With No Effects
- Logical Issues
- Floating Pragma
- Hash Collisions With Multiple Variable Length Arguments
- Improper Array Deletion
- Insufficient gas griefing
- Unsafe Ownership Transfer
- Loop through long arrays
- Message call with hardcoded gas amount
- Precision Loss in Calculations
- Hiding Malicious Code with External Contract
- Public burn
- Requirement Violation
- Right-To-Left-Override control character (U+202E)
- Signature Malleability
- Transaction Order Dependence
- Typographical Error
- Unprotected Upgrades
- Unused Variable
- Wrong inheritance
- Governance Attack
- Honeypot
- [Improper Array Deletion](attack-vectors/Improper_Array_Deletion.md)
- [Incorrect Interface](attack-vectors/Incorrect_Interface.md)
- [Insufficient Gas Attacks](attack-vectors/Insufficient_Gas_Attacks.md)
- [Integer Arithmetic](attack-vectors/Integer_Arithmetic.md)
- [Loop through long arrays](attack-vectors/Loop_through_long_arrays.md)
- [Message call with hardcoded gas amount](attack-vectors/Message_call_with_hardcoded_gas_amount.md)
- [Miner Attacks](attack-vectors/Miners_Attack.md)
- Transaction Ordering / Frontrunning
- Timestamp Manipulation
- [Offline Owner](attack-vectors/Offline_Owner.md)
- [Oracle Manipulation](attack-vectors/Oracle_Manipulation.md)
- [Outdated Compiler](attack-vectors/Outdated_Compiler.md)
- [Payable Multicall](attack-vectors/Payable_Multicall.md)
- [Precision Loss in Calculations](attack-vectors/Precision_Loss_in_Calculations.md)
- [Privacy Illusion](attack-vectors/Privacy_Illusion.md)
- [Proxy Storage Collision](attack-vectors/Proxy_Storage_Collision.md)
- [Reentrancy](attack-vectors/Reentrancy.md)
- [Right-To-Left-Override control character (U+202E)](<attack-vectors/Right-To-Left-Override_control_character_(U%2B202E).md>)
- [Sandwich Attacks](attack-vectors/Sandwich_Attack.md)
- [Signature Replay](attack-vectors/Signature_Replay.md)
- [Unchecked External Calls](attack-vectors/Unchecked_External_Calls.md)
- [Uninitialized Storage Pointers](attack-vectors/Uninitialized_Storage_Pointers.md)
- [Unprotected Upgrades](attack-vectors/Unprotected_Upgrades.md)
- [Unsafe Delegatecalls](attack-vectors/Unsafe_Delegatecall.md)
- [Unused Variable](attack-vectors/Unused_Variable.md)
- [Use of Deprecated Solidity Functions](attack-vectors/Use_of_Deprecated_Solidity_Functions.md)
- [Variable Shadowing](attack-vectors/Variable_Shadowing.md)
- [Writes to Arbitrary Storage Locations](attack-vectors/Writes_to_Arbitrary_Storage_Locations.md)
- [Wrong inheritance](attack-vectors/Wrong_inheritance.md)

#

# References

[Rekt news](https://rekt.news/)

[SWC Registry](https://swcregistry.io/)

[DeFi-Threat](https://github.com/manifoldfinance/defi-threat)
[Sigmaprime Solidity Security](https://blog.sigmaprime.io/solidity-security.html)

[Runtimeverification - List-of-Security-Vulnerabilties](https://github.com/runtimeverification/verified-smart-contracts/wiki/List-of-Security-Vulnerabilities)
[Consensys Best Practices](https://consensys.github.io/smart-contract-best-practices/known_attacks/)

[DASP-Top 10](https://www.dasp.co/)

[SCSVS](https://github.com/securing/SCSVS)
[Solidity Documentation: Security Considerations](https://docs.soliditylang.org/en/latest/security-considerations.html)

[Ethereum Wiki: Safety](https://github.com/ethereum/wiki/wiki/Safety)

[Trail of Bits Reference List](https://github.com/crytic/awesome-ethereum-security)

[DeFi-Threat](https://github.com/manifoldfinance/defi-threat)

[Runtimeverification - List-of-Security-Vulnerabilties](https://github.com/runtimeverification/verified-smart-contracts/wiki/List-of-Security-Vulnerabilities)
5 changes: 0 additions & 5 deletions attack vectors/Frontrunning.md

This file was deleted.

3 changes: 0 additions & 3 deletions attack vectors/Honeypoy.md

This file was deleted.

File renamed without changes.
5 changes: 5 additions & 0 deletions attack-vectors/Account_Existence_Check_for_low_level_calls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
As written in the solidity documentation, the low-level functions call, delegatecall and staticcall return true as their first return value if the account called is non-existent, as part of the design of the EVM. Account existence must be checked prior to calling if needed.

## Remediation

Check before any low-level call that the address actually exists, for example before the low level call in the callERC20 function you can check that the address is a contract by checking its code size.
5 changes: 5 additions & 0 deletions attack-vectors/Arbitrary_Jumps_with_Function_Variables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Solidity supports function types. That is, a variable of function type can be assigned with a reference to a function with a matching signature. The function saved to such variable can be called just like a regular function.

The problem arises when a user has the ability to arbitrarily change the function type variable and thus execute random code instructions. As Solidity doesn't support pointer arithmetics, it's impossible to change such variable to an arbitrary value. However, if the developer uses assembly instructions, such as `mstore` or assign operator, in the worst case scenario an attacker is able to point a function type variable to any code instruction, violating required validations and required state changes.

- [SWC Registry: Arbitrary Jump with Function Type Variable](https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-127)
5 changes: 5 additions & 0 deletions attack-vectors/Assert_Violation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Properly functioning code should never violate an `assert` statement. This can occur if developers mistakenly use `assert` instead of `require`.

-[ SWC Registry: Assert Violation](https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-110)

- [SWC Registry: Assert Violation](https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-123) -[Solidity Documentation: Error Handling](https://solidity.readthedocs.io/en/latest/control-structures.html?highlight%3Dassert#error-handling-assert-require-revert-and-exceptions)
3 changes: 3 additions & 0 deletions attack-vectors/Bypass_Contract_Size_Check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
It is possible to create a contract with code size returned by extcodesize equal to 0. This can lead to bypass of 0-address check in a contract, which may lead to lost of fund or locking of funds.

- [Solidity By Example: Bypass Contract Size Check](https://solidity-by-example.org/hacks/contract-size/)
3 changes: 3 additions & 0 deletions attack-vectors/Code_With_No_Effects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In Solidity, it's possible to write code that does not produce the intended effects. Currently, the solidity compiler will not return a warning for effect-free code. This can lead to the introduction of "dead" code that does not properly performing an intended action.

For example, it's easy to miss the trailing parentheses in `msg.sender.call.value(address(this).balance)("");`, which could lead to a function proceeding without transferring funds to msg.sender. Although, this should be avoided by checking the return value of the call.
3 changes: 3 additions & 0 deletions attack-vectors/Complex_Modifiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Use modifiers only for input validation with `require`. Modifiers should not contain any substantive logic, because that logic will be executed before any input validation done at the start of function bodies.

- [Consensys Best Practices: Use Modifiers Only for Assertions](https://consensys.github.io/smart-contract-best-practices/recommendations/#use-modifiers-only-for-assertions)
27 changes: 27 additions & 0 deletions attack-vectors/DOS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# DOS (Denial of Service)

This is a broad category of attacks where an attacker may render a contract inoperable, temporarily or permanently.

- [DASP: Denial of Service](https://www.dasp.co/#item-5)
- [Sigmaprime: Denial of Service](https://blog.sigmaprime.io/solidity-security.html#dos)
- [Trail of Bits: Denial of Service](https://github.com/crytic/not-so-smart-contracts/tree/master/denial_of_service)

## Unexpected Revert

An attacker may be able to exploit the fact that `transfer`(alternatively `require(addr.send(amount))`) reverts on failure to prevent a function from ever completing execution.

- [Consensys Best Practices: DOS with Unexpected Revert](https://consensys.github.io/smart-contract-best-practices/attacks/denial-of-service/#dos-with-unexpected-revert)
- [SWC Registry: DOS with Failed Call](https://swcregistry.io/docs/SWC-113)

## Block gas limit

In cases where the users of a system can manipulate how much computation (gas) is necessary for the execution of some function, it may be possible to DOS the system by causing the required gas to exceed the block gas limit. This is often the case in systems that loop over an array or mapping that can be enlarged by users at little cost.

- [Consensys Best Practices: DOS with Block Gas Limit](https://consensys.github.io/smart-contract-best-practices/attacks/denial-of-service/#dos-with-block-gas-limit)
- [SWC Registry: DOS with Block Gas Limit](https://swcregistry.io/docs/SWC-128)

## External Calls without Gas Stipends

In some cases, developers may want to make a transfer and continue execution regardless of the result. One way to achieve this is with `call.value(v)()`, however this may allow the recipient to consume all the gas of the calling function, preventing execution from continuing. See example 1 here:

- [Sigmaprime: Denial of Service](https://blog.sigmaprime.io/solidity-security.html#dos)
3 changes: 3 additions & 0 deletions attack-vectors/Dirty_Higher_Order_Bits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
If `keccak256(msg.data)` or some similar hash functionality is used (for example to log past calls), be aware that functions of types that don't occupy 32 bytes may be called with identical arguments but different hashes.

- [Solidity Documentation: Minor Details](https://solidity.readthedocs.io/en/latest/security-considerations.html#minor-details)
5 changes: 5 additions & 0 deletions attack-vectors/Entropy_Illusion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The EVM does not have support for uncertainty/random number generation. Contracts may try to simulate uncertainty in a way that is in fact predictable and exploitable.

- [Sigmaprime: Entropy Illusion](https://blog.sigmaprime.io/solidity-security.html#entropy)
- [DASP: Bad Randomness](https://www.dasp.co/#item-6)
- [SWC Registry: Weak Sources of Randomness from Chain Attributes](https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-120)
1 change: 1 addition & 0 deletions attack-vectors/Experimental_Language_Features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Avoid experimental language features, as these are not properly tested and have contained [vulnerabilities](https://blog.ethereum.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug) in the past.
3 changes: 3 additions & 0 deletions attack-vectors/External_Contrac_Referencing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
When a contract delegates some of its functionality to an external contract whose address is either inaccessible or subject to change, a benign implementation may be swapped out for a malicious one.

- [Sigmaprime: External Contract Referencing](https://blog.sigmaprime.io/solidity-security.html#contract-reference)
File renamed without changes.
3 changes: 3 additions & 0 deletions attack-vectors/Floating_Point_Arithmetic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fixed point numbers are not yet fully supported by solidity. User implementations may contain errors.

- [Fixed point numbers are not yet fully supported by solidity. User implementations may contain errors.](https://blog.sigmaprime.io/solidity-security.html#precision)
82 changes: 82 additions & 0 deletions attack-vectors/Force_Feeding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
Forcing a smart contract to hold an Ether balance can influence its internal accounting and security assumptions.
There are multiple ways a smart contract can receive Ether. The hierarchy is as follows:

1. Check whether a payable external `receive` function is defined.
2. If not, check whether a payable external `fallback` function is defined.
3. Revert.

The precedence of each function is explained in this great graphic from the [Solidity by Example](https://solidity-by-example.org/sending-ether/) article:

```
Which function is called, fallback() or receive()?
send Ether
|
msg.data is empty?
/ \
yes no
/ \
receive() exists? fallback()
/ \
yes no
/ \
receive() fallback()
```

Consider the following example:

```sol
pragma solidity ^0.8.13;
contract Vulnerable {
receive() external payable {
revert();
}
function somethingBad() external {
require(address(this).balance > 0);
// Do something bad
}
}
```

The contract's logic seemingly disallows direct payments and prevents "something bad" from happening.
However, calling `revert` in both `fallback` and `receive` **cannot prevent the contract from receiving Ether**.
The following techniques can be used to force-feed Ether to a smart contract.

### Selfdestruct

When the `SELFDESTRUCT` opcode is called, funds of the calling address are sent to the address on the stack, and execution is immediately halted.
Since this opcode works on the EVM-level, Solidity-level functions that might block the receipt of Ether [will not be executed](https://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether).

### Pre-calculated Deployments

Additionally, the target address of newly deployed smart contracts is generated in a deterministic fashion.
The address generation can be looked up in any EVM implementation, such as the [py-evm reference implementation](https://github.com/ethereum/py-evm/blob/e924f63992a35212616b4e20355d161bc4348925/eth/_utils/address.py#L17-L18) by the Ethereum Foundation:

```python
def generate_contract_address(address: Address, nonce: int) -> Address:
return force_bytes_to_address(keccak(rlp.encode([address, nonce])))
```

An attacker can send funds to this address before the deployment has happened.
This is also illustrated by [this 2017 Underhanded Solidity Contest submission](https://github.com/Arachnid/uscc/tree/master/submissions-2017/ricmoo).

### Block Rewards and Coinbase

Depending on the attacker's capabilities, they can also start proof-of-work mining.
By setting the target address to their `coinbase`, block rewards will be added to its balance.
As this is yet another EVM-level capability, checks performed by Solidity are ineffective.

### Solution

The above effects illustrate that relying on exact comparisons to the contract's Ether balance is unreliable.
The smart contract's business logic must consider that the actual balance associated with it can be higher than the internal accounting's value.

**In general, we strongly advise against using the contract's balance as a guard.**

More information can be found in [SWC-132](https://swcregistry.io/docs/SWC-132).

## References

- [Force Feeding | Consensys](https://consensys.github.io/smart-contract-best-practices/attacks/force-feeding/#)
10 changes: 10 additions & 0 deletions attack-vectors/Frontend_(Off_Chain)_Attacks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
These are possible vulnerabilities in frontends to ethereum contracts, not vulnerabilities in the contracts themselves. (Possibly out of scope.)

## Short Address Attack

Short address attacks are a side-effect of the EVM itself accepting incorrectly padded arguments. Attackers can exploit this by using specially-crafted addresses to make poorly coded clients encode arguments incorrectly before including them in transactions. Is this an EVM issue or a client issue? Should it be fixed in smart contracts instead? While everyone has a different opinion, the fact is that a great deal of ether could be directly impacted by this issue. While this vulnerability has yet to be exploited in the wild, it is a good demonstration of problems arising from the interaction between clients and the Ethereum blockchain. Other off-chain issues exist: an important one is the Ethereum ecosystem's deep trust in specific Javascript front ends, browser plugins and public nodes. An infamous off-chain exploit was used in the hack of the Coindash ICO that modified the company's Ethereum address on their webpage to trick participants into sending ethers to the attacker's address.

Frontends should validate any input used to make transactions on chain.

- [Sigmaprime: Short Address / Parameter Attack](https://blog.sigmaprime.io/solidity-security.html#short-address)
- [DASP: Short Address Attack](https://www.dasp.co/#item-9)
Loading

0 comments on commit 0d7e490

Please sign in to comment.