Due to the lack of seed validation on borrow_collateral function, the borrower can steal all SOL from the lender by paying almost nothing as a collateral. This can be done as follows:
The borrower opens two positions.
Pos#1 is a small one. So, the borrowed and the collateral amounts are small.
Pos#2 is a big one. So, the borrowed and the collateral amounts are big.
The borrower repays Pos#1.borrowed (small amount) while withdrawing Pos#2.collateral (big amount)
Thus, the protocol now has Pos#2.borrowed (not backed by any collateral), and Pos#1.collateral not withdrawn.
The borrower got away with Pos#1.borrowed and Pos#2.collateral amounts.
Check the PoC below, It demonstrates how a thief could perform the scenario above.
Note: this is different from the other issue reported (completly different root cause and slightly different impact)
Proof of Concept
Please create a file tests/poc_steal_sol_lavarage.spec.ts) , then run the following command:
ORACLE_PUB_KEY=ATeSYS4MQUs2d6UQbBvs9oSNvrmNPU1ibnS2Dmk21BKZ anchor test
You should see the following output:
console.log
===== Initial Amounts======
at tests/poc_steal_sol_lavarage.spec.ts:308:13
console.log
Pos#1.collaterel : 0n
at tests/poc_steal_sol_lavarage.spec.ts:310:13
console.log
Pos#2.collaterel : 0n
at tests/poc_steal_sol_lavarage.spec.ts:311:13
console.log
Borrower Collaterel : 200000000000000000n
at tests/poc_steal_sol_lavarage.spec.ts:312:13
console.log
Node Sol : 500001294560
at tests/poc_steal_sol_lavarage.spec.ts:314:13
console.log
Borrower Sol : 499999499996989200
at tests/poc_steal_sol_lavarage.spec.ts:315:13
console.log
===== After Borrow #1 and #2======
at tests/poc_steal_sol_lavarage.spec.ts:333:13
console.log
Pos#1.collaterel : 100000000n
at tests/poc_steal_sol_lavarage.spec.ts:353:13
console.log
Pos#2.collaterel : 100000000000000000n
at tests/poc_steal_sol_lavarage.spec.ts:354:13
console.log
Borrower Collaterel : 99999999900000000n
at tests/poc_steal_sol_lavarage.spec.ts:355:13
console.log
Node Sol : 495001294555
at tests/poc_steal_sol_lavarage.spec.ts:359:13
console.log
Borrower Sol : 499999504967719600
at tests/poc_steal_sol_lavarage.spec.ts:360:13
console.log
>>===== Now, repay Pos#1 and withdraw collateral of Pos#2 ======>>
at tests/poc_steal_sol_lavarage.spec.ts:399:13
console.log
===== After Successful Repay ======
at tests/poc_steal_sol_lavarage.spec.ts:403:13
console.log
Pos#1.collaterel : 100000000n
at tests/poc_steal_sol_lavarage.spec.ts:421:13
console.log
Pos#2.collaterel : 0n
at tests/poc_steal_sol_lavarage.spec.ts:422:13
console.log
Borrower Collaterel : 199999999900000000n
at tests/poc_steal_sol_lavarage.spec.ts:423:13
console.log
Node Sol : 495001294560
at tests/poc_steal_sol_lavarage.spec.ts:427:13
console.log
Borrower Sol : 499999504967714600
at tests/poc_steal_sol_lavarage.spec.ts:428:13
PASS tests/poc_steal_sol_lavarage.spec.ts (8.149 s)
lavarage
✓ Should mint new token! (1776 ms)
✓ Should create lpOperator node wallet (464 ms)
✓ Should create trading pool (455 ms)
✓ Should fund node wallet (456 ms)
✓ Should set maxBorrow (456 ms)
✓ Hacker can steal funds from lenders (2319 ms)
Test Suites: 1 passed, 1 total
Tests: 6 passed, 6 total
Snapshots: 0 total
Time: 8.227 s, estimated 9 s
Ran all test suites.
Lines of code
https://github.com/code-423n4/2024-04-lavarage/blob/main/libs/smart-contracts/programs/lavarage/src/processor/swapback.rs#L43-L63
Vulnerability details
Impact
Due to the lack of seed validation on
borrow_collateral
function, the borrower can steal all SOL from the lender by paying almost nothing as a collateral. This can be done as follows:Check the PoC below, It demonstrates how a thief could perform the scenario above.
Note: this is different from the other issue reported (completly different root cause and slightly different impact)
Proof of Concept
Please create a file
tests/poc_steal_sol_lavarage.spec.ts
) , then run the following command:You should see the following output:
Summary of balances:
Test file
Tools Used
Manual analysis
Recommended Mitigation Steps
Add this to
borrow_collateral
function to validate the seedAfter adding this mitigation, if you run the attack above, it will fail.
Assessed type
Invalid Validation