People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
UnpackLog() to get further information, we have a problem though. UnpackLog() is used to take an Ethereum event log into a Golang struct. However, there is a missing check for the Topic of the code. Each event type has its own selector, just like functions do. From parsing, the only restriction was that it had to have the same amount of indexed parameters. With this, we have a type confusion vulnerability.StakeUpdate is call is the most interesting one to exploit but this affected a bunch of other issues. The goal is to use a SignerChange() event to trigger an StakeUpdate() function to steal all of the funds. The validatorIds correspond to the same field and the address in SignerChange is the amount (which would be a crazy large value). The final thing that lines up is the nonce from the change with the address on the update.MsgStakeUpdate() event.State-Sync is a mechanism used by Polygon PoS to push events from Ethereum L1 to the network. Since it processes incoming transfers from the Polygon bridge to Plasma bridge, it's a super interesting attack surface. The state sync is a feature that allows users to participate in Consensus even if there's an RPC outage by agreeing with the super majority. sendFrom() function is responsible for sending staked users' tokens across chains. Additionally, a user can allocate allowance to another user for these cross-chain calls. Inversely, the function _debtFrom() checks that the user calling sendFrom() has been allocated the proper allowance from the send address. If this is true, it burns the tokens then sends them off to another chain.spender->spender->amount. Since an attacker now controlled both of these, they could allow themselves to spend their own value then spend the funds of other users arbitrarily. Yikes!random library from Python. Since this is known to NOT be cryptographically secure, this is a red flag. However, breaking this remotely is feasible in some scenarios but not all. So, now what?seed. So, if you know the seed then you can predict what numbers are going to be used going forward, regardless of the randomness of the algorithm. In a crazy turn of events, the author found a way to leak the seed of the randomness.delegateCall() to share storage.Initializer pattern.initializer() modifier for us. This will allow the initialize function to be called once and only once during the lifespan of the proxy. initializer() is implemented with the functionality, this will not automatically call the children constructors like a real constructor will do. So, we must do that manually. To prevent these from being called by ours, we can use the onlyInitializing() modifier. There is another function called reinitializer() that can be used to allow for initializations after the initial one.ParseCoinNormalized, which is part of the Coin implementation. Fuzzers can quickly find issues in stateless code like this but it becomes harder to find weird issues in the combined and stateful ecosystem.Rand. They found a few bugs, which is awesome. To me, you always hear I modified their fuzzer to do XYZ because different fuzzers find different bugs. thp_get_unmapped_area() for backing memory. This function recently had a changed to make allocations of larger than 2MB use huge pages instead. Boom, that's the issue! Flask_Session, which was used for server-side session application management. This can be Redis or Memcached as the backend for it.set and get. save_session() to store the information in memcached the set() call doesn't escape CSRF. As a result, a controlled session can be used to get control over arbitrary commands.\015\012 works for this.