-
-
Notifications
You must be signed in to change notification settings - Fork 819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ABI decoding byte array offsets allows overflows #1602
Comments
Thanks for the report! I am having trouble why this is a vyper issue. What is the expected behavior when the caller provides malformed data? |
The data isn't really malformed. It's valid, ABI-encoded data that points outside of the range of calldata. Vyper should detect this and revert. |
I guess I still don't understand. Doesn't the spec say that the offset word points to |
Sorry, I don't think my initial reply was particularly clear. The example I gave shows that Vyper accepts an overflow during ABI decoding which leads to it reading the first 32 bytes of calldata and treating it as an array size. In every variation I tried, this led to the call failing because |
My understanding of the spec is that the offset word must point to where the data is. If it doesn't, it is ipso facto invalid input. Unless I am misunderstanding the spec. |
That is certainly true, but my point is that (because of the overflow) Vyper is not reading from where the offset points. If there were data there (nevermind the cost of accessing it), Vyper would not read it correctly. |
Yes but the same would hold true if the offset pointed to any other location. I suppose that Vyper could validate that all the offsets are valid (i.e., start at |
What attack vectors are you beginning to suspect? I'm very curious! Regardless of the existence of a tangible attack vector - this is the type of edge-case in behavior that can exacerbate other issues. Cleaning it up allows you to make much stronger statements about the behavior of the abi decoder, which is why I recommend it! |
I don't have it fully fleshed out but an attacker might be able to take advantage of the offset pointing somewhere unexpected. So for example, let's say you have a contract which checks some bytearrays against some value. For instance, def check_withdraw(sig1: bytes[100], sig2: bytes[100]) :
if sig1 == sig2 :
send(msg.sender, balance) Using the technique in this issue, an attacker could set the offset of |
Yes, that's actually allowed in Solidity - and you don't need to do any overflow weirdness. Just set them to the same offset. By the ABI specification, those are the same array :) |
Well then maybe there are some solidity contracts which are susceptible to this attack. I don't think that calldata which has the offset of
|
After thinking about it some more, I don't think this would result in a serious attack vector (any more than a caller switching two variables). |
@charles-cooper what's the outcome of this issue? |
@fubuloubu not sure, let's bring it up at another meeting |
i don't think we need to check for the calldata case since calldata is always user-controlled. however, there is an issue with abi_decode when it decodes from memory, since that can allow introspection of memory. closing this issue as wontfix, see #3899 for the memory case. |
Version Information
vyper --version
): 0.1.0-beta.12What's your issue about?
The ABI uses calldata offsets to point to the location of dynamically-sized data. Vyper does not check for overflow when evaluating these offsets. For example:
The above contract does not correctly decode calldata provided by this Solidity contract:
Specifically, this line in the LLL contains the overflow issue:
[calldatacopy, 320, [add, 4, [calldataload, 4]], 1056]
. This is located here in the code.How can it be fixed?
Check offset calculations for overflow, or make sure offsets are pointing within the bounds of
CALLDATASIZE
The text was updated successfully, but these errors were encountered: