Skip to content

Commit

Permalink
new transferFrom access control rule
Browse files Browse the repository at this point in the history
  • Loading branch information
morsiiik committed Aug 15, 2024
1 parent 75073c2 commit 1e212a0
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
78 changes: 78 additions & 0 deletions solidity/security/bad-transferFrom-access-control.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
contract Test {
function func1(address from, address to) public {
// ruleid: bad-transferFrom-access-control
usdc.transferFrom(from, to, amount);
}

function func2(address from, address to) public {
// ok: bad-transferFrom-access-control
usdc.transferFrom(owner, random, amount);
}

function func3(address from, address to) public {
// ok: bad-transferFrom-access-control
usdc.transferFrom(pool, to, amount);
}

function func4(address from, uint256 amount, address random) public {
// ok: bad-transferFrom-access-control
usdc.transferFrom(pool, owner, amount);
}

function func5(address from, address to) external {
// ruleid: bad-transferFrom-access-control
usdc.transferFrom(from, to, amount);
}

function func6(address from, address to) external {
// ok: bad-transferFrom-access-control
usdc.transferFrom(owner, random, amount);
}

function func7(address from, address to) external {
// ok: bad-transferFrom-access-control
usdc.transferFrom(pool, to, amount);
}

function func8(address from, uint256 amount, address random) external {
// ok: bad-transferFrom-access-control
usdc.transferFrom(pool, owner, amount);
}

function transferFee(uint256 amount, uint256 feeBps, address token, address from, address to)
public
returns (uint256)
{
uint256 fee = calculateFee(amount, feeBps);
if (fee > 0) {
if (token != NATIVE_TOKEN) {
// ERC20 token
if (from == address(this)) {
TransferHelper.safeTransfer(token, to, fee);
} else {
// safeTransferFrom requires approval
// ruleid: bad-transferFrom-access-control
TransferHelper.safeTransferFrom(token, from, to, fee);
}
} else {
require(from == address(this), "can only transfer eth from the router address");

// Native ether
(bool success,) = to.call{value: fee}("");
require(success, "transfer failed in transferFee");
}
return fee;
} else {
return 0;
}
}

function func9(address from, address to) external {
_func10(from, to, amount);
}

function _func10(address from, address to) internal {
// ruleid: bad-transferFrom-access-control
usdc.transferFrom(from, to, amount);
}
}
39 changes: 39 additions & 0 deletions solidity/security/bad-transferFrom-access-control.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
rules:
- id: bad-transferFrom-access-control
languages:
- solidity
severity: ERROR
message: An attacker may perform transferFrom() with arbitrary addresses
pattern-sources:
- label: INPUT_TO
pattern-either:
- patterns:
- pattern: function $F(..., address $FROM, ..., address $TO, ...) public { ... }
- focus-metavariable: $TO
- patterns:
- pattern: function $F(..., address $FROM, ..., address $TO, ...) external { ... }
- focus-metavariable: $TO
- label: INPUT_FROM
pattern-either:
- patterns:
- pattern: function $F(..., address $FROM, ..., address $TO, ...) public { ... }
- focus-metavariable: $FROM
- patterns:
- pattern: function $F(..., address $FROM, ..., address $TO, ...) external { ... }
- focus-metavariable: $FROM
pattern-sinks:
- requires: INPUT_TO and INPUT_FROM
pattern-either:
- patterns:
- pattern: $TOKEN.transferFrom(...,$FROM,...);
- pattern: $TOKEN.transferFrom(...,$TO,...);
- patterns:
- pattern: $TOKEN.safeTransferFrom(...,$FROM,...);
- pattern: $TOKEN.safeTransferFrom(...,$TO,...);
- patterns:
- pattern: $HELPER.transferFrom($TOKEN,...,$FROM,...);
- pattern: $HELPER.transferFrom($TOKEN,...,$TO,...);
- patterns:
- pattern: $HELPER.safeTransferFrom($TOKEN,...,$FROM,...);
- pattern: $HELPER.safeTransferFrom($TOKEN,...,$TO,...);
mode: taint

0 comments on commit 1e212a0

Please sign in to comment.