-
Notifications
You must be signed in to change notification settings - Fork 14
Detector Documentation
List of detectors
- Check:
is-deletable
- Applicable to:
Stateful
- Severity:
High
- Confidence:
High
Application can be deleted by sending an DeleteApplication
type application call.
@router.method(delete_application=CallConfig.CALL)
def delete_application() -> Expr:
return Assert(Txn.sender() == Global.creator_address())
Eve steals application creator's private key and deletes the application. Application's assets are permanently lost.
Do not approve DeleteApplication
type application calls.
- Check:
is-updatable
- Applicable to:
Stateful
- Severity:
High
- Confidence:
High
Application can be updated by sending an UpdateApplication
type application call.
@router.method(update_application=CallConfig.CALL)
def update_application() -> Expr:
return Assert(Txn.sender() == Global.creator_address())
Creator updates the application and steals all of its assets.
Do not approve UpdateApplication
type application calls.
- Check:
unprotected-deletable
- Applicable to:
Stateful
- Severity:
High
- Confidence:
High
Application can be deleted by anyone. More at building-secure-contracts/not-so-smart-contracts/algorand/access_controls.
@router.method(delete_application=CallConfig.CALL)
def delete_application() -> Expr:
return Approve()
Eve calls delete_application
method and deletes the application making its assets permanently inaccesible.
- Avoid deletable applications.
- Add access controls to the vulnerable method.
- Check:
unprotected-updatable
- Applicable to:
Stateful
- Severity:
High
- Confidence:
High
Application can be updated by anyone. More at building-secure-contracts/not-so-smart-contracts/algorand/access_controls.
@router.method(update_application=CallConfig.CALL)
def update_application() -> Expr:
return Approve()
Eve updates the application by calling update_application
method and steals all of its assets.
- Avoid upgradable applications.
- Add access controls to the vulnerable method.
- Check:
group-size-check
- Applicable to:
Stateless, Stateful
- Severity:
High
- Confidence:
High
Contract's execution depends on multiple transactions in the group and it uses absolute index to access information of other transactions in the group. Attacker can exploit the contract by abusing the lack of validations on GroupSize
. More at building-secure-contracts/not-so-smart-contracts/algorand/group_size_check
def mint_wrapped_algo() -> Expr:
validations = Assert(
And(
Gtxn[0].receiver() == Global.current_application_address(),
Gtxn[0].type_enum() == TxnType.Payment,
)
)
transfer_op = transfer_wrapped_algo(Txn.sender(), Gtxn[0].amount())
return Seq([validations, transfer_op, Approve()])
Eve sends the following group transaction:
0. Payment of 1 million ALGOs to application address
1. Call mint_wrapped_algo
2. Call mint_wrapped_algo
...
15. Call mint_wrapped_algo
Eve receives 15 million wrapped-algos instead of 1 million wrapped-algos. Eve exchanges the Wrapped-algo to ALGO and steals 14 million ALGOs.
- Avoid using absolute indexes. Validate GroupSize if used.
- Favor using ARC-4 ABI and relative indexes for group transactions.
- Check:
can-close-account
- Applicable to:
Stateless
- Severity:
High
- Confidence:
High
LogicSig does not validate CloseRemainderTo
field. Attacker can submit a transaction with CloseRemainderTo
field set to their address and steal all of account's ALGOs. More at building-secure-contracts/not-so-smart-contracts/algorand/closing_account
def withdraw(...) -> Expr:
return Seq(
[
Assert(
And(
Txn.type_enum() == TxnType.Payment,
Txn.first_valid() % period == Int(0),
Txn.last_valid() == Txn.first_valid() + duration,
Txn.receiver() == receiver,
Txn.amount() == amount,
Txn.first_valid() < timeout,
)
),
Approve(),
]
)
Alice signs the logic-sig to allow recurring payments to Bob. Eve uses the logic-sig and submits a valid transaction with CloseRemainderTo
field set to her address. Eve steals Alice's ALGO balance.
Validate CloseRemainderTo
field in the LogicSig.
- Check:
can-close-asset
- Applicable to:
Stateless
- Severity:
High
- Confidence:
High
LogicSig does not validate AssetCloseTo
field. Attacker can submit a transaction with AssetCloseTo
field set to their address and steal account's assets. More at building-secure-contracts/not-so-smart-contracts/algorand/closing_asset
def withdraw(...) -> Expr:
return Seq(
[
Assert(
And(
Txn.type_enum() == TxnType.AssetTransfer,
Txn.first_valid() % period == Int(0),
Txn.last_valid() == Txn.first_valid() + duration,
Txn.asset_receiver() == receiver,
Txn.asset_amount() == amount,
Txn.first_valid() < timeout,
)
),
Approve(),
]
)
Alice signs the logic-sig to allow recurring payments to Bob in USDC. Eve uses the logic-sig and submits a valid transaction with AssetCloseTo
field set to her address. Eve steals Alice's USDC balance.
Validate AssetCloseTo
field in the LogicSig.
- Check:
missing-fee-check
- Applicable to:
Stateless
- Severity:
High
- Confidence:
High
LogicSig does not validate Fee
field. Attacker can submit a transaction with Fee
field set to large value and drain the account balance. More at building-secure-contracts/not-so-smart-contracts/algorand/unchecked_transaction_fee
def withdraw(...) -> Expr:
return Seq(
[
Assert(
And(
Txn.type_enum() == TxnType.Payment,
Txn.first_valid() % period == Int(0),
Txn.last_valid() == Txn.first_valid() + duration,
Txn.receiver() == receiver,
Txn.amount() == amount,
Txn.first_valid() < timeout,
)
),
Approve(),
]
)
Alice signs the logic-sig to allow recurring payments to Bob. Eve uses the logic-sig and submits a valid transaction with Fee
set to 1 million ALGOs. Alice loses 1 million ALGOs.
Validate Fee
field in the LogicSig.
- Check:
rekey-to
- Applicable to:
Stateless
- Severity:
High
- Confidence:
High
Logic signature does not validate RekeyTo
field. Attacker can submit a transaction with RekeyTo
field set to their address and take control over the account. More at building-secure-contracts/not-so-smart-contracts/algorand/rekeying
def withdraw(...) -> Expr:
return Seq(
[
Assert(
And(
Txn.type_enum() == TxnType.Payment,
Txn.first_valid() % period == Int(0),
Txn.last_valid() == Txn.first_valid() + duration,
Txn.receiver() == receiver,
Txn.amount() == amount,
Txn.first_valid() < timeout,
)
),
Approve(),
]
)
Alice signs the logic-sig to allow recurring payments to Bob.Eve uses the logic-sig and submits a valid transaction with RekeyTo
field set to her address.Eve takes over Alice's account.
Validate RekeyTo
field in the LogicSig.