Resources

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!

How Tornado Cash Works- 1230

Jeffrey Scholz - Rare Skills    Reference →Posted 2 Years Ago
  • Tornado Cash is a smart contract cryptocurrency mixer. This allows users at one address to withdraw funds at another address without creating a traceable link between the two addresses. Seems impossible right? This is all about zero knowledge proofs. This is proof that an operation was carried out with giving the secret value. RSA math says I know two secret prime numbers without ever showing you those prime numbers.
  • The owners of Tornado got sued by the US government because of how well it works for money laundering. A user can put money in and there's no possible way to associate the address on the output. Although, you can associate an address with receiving funds from Tornado cash or depositing funds, you cannot figure out who sent to who.
  • The naive and not privacy preserving solution is to create two secret numbers and put the hash on the chain. If you can reveal the two secret numbers, then you can take the money out. To make this private, we can go over a list of hashes in a loop by ORing all of them together with zero knowledge proof data. This allows us to find a valid hash without revealing which hash is the one we proved.
  • Merkle trees are a common data structure used in blockchain because of the ease of verification. So, instead of iterating through a list of hashes, we can use a merkle tree instead. In particular, the withdrawer must prove knowledge of the preimage of a leaf without revealing the leaf and demonstrate that we have a valid Merkle proof for the node.
  • If we removed a node from the Merkle tree, this would disclose which item we were taking out. So, how do we prevent double spends? The hash from above was two numbers: a nonce and a secret value. The contract code uses a hash of the nonce to determine if this node has been used. So, if you tried to withdraw twice, it would not work. Naturally, this process of knowing the nonce is done as a zk proof. This strategy is called a nullifier scheme.
  • The Merkle tree needs to be faster to be usable. So, some optimizations have been made. First, the tree has a fixed depth of 2^32 deposits with every element starting off as 0s. Second, the left-most node that does not have a value is overwritten.
  • The quirks from above have immense impact on how the program works. Since all updates are performed on the left-most updated node, everything to the right is going to be 0. Because of this, they have recomputed all of these values of different depths to make the program more efficient.
  • The second shortcut is that since we add in a consistent order, we do not have to recalculate the tree all the time. Instead, we can use previously cached values and only update small chunks from the real update. Pretty neat!
  • The rest of the article goes into the code of the project. I still do not understand how the program performs the zero knowledge proofs but understand why they are being used at least. Awesome article!

Smashing the state machine: the true potential of web race conditions- 1229

James Kettle    Reference →Posted 2 Years Ago
  • Race conditions are issues that stem from the timing of requests being made. Historically, most race conditions were time of check vs. time of use (TOCTOU). For instance, redeeming a gift card multiple times by submitting the requests simultaneously. The author calls these limit overrun attacks. However, there are other TOCTOU issues besides limit overruns.
  • James Kettle introduces a new class of race condition bugs beyond limit overrun attacks: state machine races. Best quote of the article: "Every pentester knows that multi-step sequences are a hotbed for vulnerabilities, but with race conditions, everything is multi-step." By considering every operation that the backend performs a state change, new requests between these changes could cause major havoc by accessing unintended substates.
  • The author was testing an application where the flow was Login->Assign Role to token. So, what happens prior to the role being assigned to the user? It's an admin user! So, by making a request while the role assignment process was occurring, the user could briefly become an administrator. This is a perfect example of a sub state causing problems.
  • These race conditions can be extremely tight though. How do we hit these? Network jitter between two requests can cause particular conditions to not work. A common technique is the last byte sync, where the final byte is not send until the very end.
  • HTTP/2 allows for multiple requests to go over a single packet. This was abused for Timing Attacks in the past. Now, James Kettle was abusing this to get the network jitter to be extremely low. On top of this, they combined the last byte sync from before in order to get 20-30 requests interpreted all at the same time. This is implemented into Burp Intruder but they have more details on how to do this yourself as well.
  • Finding these types of vulnerabilities is extremely difficult to do. So, the author came up with a methodology for finding these bugs. First, we need to identify objects, such as users and sessions, with security controls that that we want to bypass. Then, identify functionality that reads or writes to this state, such as profile edits, password resets and more. Finally, race these various types of requests to find a problematic sub-state.
  • The big questions to be ask are:
    1. How is the data stored? Persistent server side state data is what should be tested here.
    2. What's the operation keyed on?. Finding weird sub-states may only be possible in situations where two items share the same key or the state has various operations that change in a single request.
    3. Editing or appending. Editing is much more prune to race conditions.
  • Of course, Kettle went through some case studies. While looking through email invitations functionality, sending the same invitation request 6 times turned up 5 successes and 1 "this has already been taken" message and two emails instead of 1. This was different than doing this sequentially. So, the weirdness of this call indicates that a weird sub-state has been hit.
  • Initially, this did not gather much. However, they came up with a crazy attack scenario. Doing the email resolution process, what if you replaced the email? The email resolution would verify it while the replacement would swap the email. Sadly, the code being sent was for an already verified account and not the new one trying to be added.
  • During the Gitlab process of changing an email, the author noticed that it was incredibly fast; much faster than sending an email is. So, this indicating that another thread was likely being used to send this. The author decided to change their email address twice at the same time. While doing this, they noticed that the To and body did not always match. Sometimes, the confirmation code for one user was included in the other users email! What a crazy bug!
  • Testing for these bugs is complicated via blackbox but impossible to spot via whitebox testing. There are many many many bugs like this waiting to be discovered in the wild. I hope to find some of these in the near future via blackbox testing. Race conditions thrive on complexity.

cypher exploit - 7th august 2023 - post-mortem- 1228

Cypher    Reference →Posted 2 Years Ago
  • Cypher is a protocol for lending, borrowing and trading using margin. Margin is the process of betting on assets using value that you are borrowing from somebody else.
  • There are two types of account: master account and sub accounts. The master account acts as a cache for all sub accounts under it. This information includes asset values, collateral ratio and more. Master accounts are cross-collateralized, meaning that a sub account can use assets from another sub account. This cross collateralization can be turned off on a particular sub account as well.
  • The function EditSubAccountMargining can be used to change the mode of the sub account. However, there is a bug here: the cache of the sub account in the master account is not updated to reflect this. The lack of updating the cache puts the account into a bizarre corrupted state.
  • The goal of a loan managing process is to ensure that a user cannot borrow more money than their entitled to for their collateral. Breaking this logic would result in a complete loss of assets for the protocol.
  • Although this is not fully explained, this is the root cause of the issue. Once in this state, the usage of the sub account will no longer effect the master account. So, removing funds from the sub account would make the master account believe it had more funds than it really did, allowing for more money to be taken out than expected.
  • There is a second bug that allowed this to be exploited though. The functionality for verifying margin on volatile assets had an uninitialized oracle. This led the trade being accepted, even though it should not have been. In the end, this led to $1M in stolen funds from bad loans.

How to trick CSP in letting you run whatever you want- 1227

bo0om - Wallarm Research    Reference →Posted 2 Years Ago
  • The Content Security Policy (CSP) is used to restrict what can be done on a web page. This is useful for defense-in-depth on issues, like XSS, as well as framing. The origin of resources and the types can be restricted as well. In this case, the author had an arbitrary file upload bug but couldn't exploit it because of the CSP not allowing unsafe-inline.
  • Modern browsers will display accessed data as HTML, as long as the Content-Type lines up. This includes images, CSS files and more. If we can load data into an iFrame, then we can trick the page into loading the page for us. A lot of the time, the CSP is conditional; by loading it into an iFrame with a weird page, we can bypass the CSP. This works with weird looking images or JS files.
  • The solution? Put the CSP on all requests. This will gunk things up, which is annoying though.
  • The final payload is confusing to me though; it's using JavaScript to create an iFrame on the page to bypass the CSP. If you can execute JS already then why do you need to bypass the CSP? Regardless, interesting CSP bypass technique; put stuff in iFrames that is not meant to be in iFrames.

Go Fuzz- 1226

Trail of Bits    Reference →Posted 2 Years Ago
  • Trail of Bits was performing a security audit of the Cosmos IBC Go implementation. While doing this audit, they used Go Fuzz, a coverage guided fuzzer for Go. Seems like a pretty rad tool for fuzzing; just build a quick harass and you're ready to go.

Attacks Over The Air — Phreaking HTML Injection- 1225

Jesse Victors    Reference →Posted 2 Years Ago
  • JS8 is a protocol for communicating over vast differences using radio. It's a text based protocol for chat.
  • The protocol is operates at 7MHz-14MHz, which is extremely low. At these frequencies, the E and F layers of the ionosphere reflect the radio signals. This means that line-of-sight is not important for us! Point to point can go from one spot on earth to another, which is truly amazing.
  • Jesse was looking at a website that parsed all JS8 traffic and displayed it. The message can literally contain anything after the callsign. So, they decided to add an HTML injection payload to their JS8 payload and it caused modification of the page! Since the page has no authentication, what could we do that would be useful?
  • Cosmetic change are interesting... logging requests and where the users are located... Even with this, the stored HTML injection has some impact. Overall, a classic vulnerability found in a very bizarre place.

Zunami Protocol- 1224

Rekt    Reference →Posted 2 Years Ago
  • Zunami is a yield aggregator protocol for stablecoin staking. They lost 2.1M dollars in two transactions. How did this happen?
  • The function calcTokenPrice() is used to determine the price of the tokens of the project. This is done by diving the total holdings of the pool by the number of existing tokens.
  • The price of a token calculated this way can increased in price by adding tokens or decreased in price by somehow removing tokens. By donating funds to the pool, the value of LP token can be manipulated.

Chainlink Oracle Security Considerations- 1223

Security Considerations for Integrating Chainlink Price Oracles    Reference →Posted 2 Years Ago
  • Chainlink provides off-chain data to smart contracts in order for users to query them. Integrating with chainlink creates its own set of challenges.
  • The oracles are updated periodically but must be updated by Chainlink. However, the values may be stale or out of date when calling latestRoundData(). As a result, a user could contain money from the out of date oracle. Not checking if an L2 Sequencer is down falls into the same category.
  • When checking if a price feed has been updated, different feeds can have different heartbeats. So, the time for more value may be another. Additionally, simply checking whether the price oracles get updated enough is important. What if a price feed is never updated but we are using it? Real bad!
  • Besides these, it's common to use wrong hardcoded values. For instance, the precision of various feeds may be assumed throughout the contract. Additionally, hardcoding the wrong address for the price is a common problem as well. This may be in a configuration file instead of the contract though.
  • A classic blockchain problem is frontrunning. If updates are too slow and the price deviates too much, then they can be sandwiched. To solve this, adding small fees or delays on withdrawals.
  • Another interesting case is a denial of service (DoS) via bad price feeds. The recommendation is to add functionality to update the price in case something breaks.
  • The final cases are extreme price changes. If an asset is depegged (WBTC to BTC), then we want to ensure that malicious actors cannot benefit from this. The solution is looking at the price of BTC to WBTC. A similar thing can be done to prevent flash crash attacks on the protocol as well.
  • Overall, integrating with Chainlink has it's problems just like everything else. Most of these feel like defense-in-depth, but is super important in the case of failure.

Security Advisory: Clock Fault Injection on Mocor OS – Password Bypass- 1222

One Key    Reference →Posted 2 Years Ago
  • Mocor OS is a proprietary OS from UNISOC. This OS is used in various phone vendros such as Nokia, TCL and others.
  • During the initial boot up process, there is a user-lock password on the phone. Without knowledge of this, it should not be possible to access data on the phone.
  • The author found a weird (and not very well explained) loophole in the code. When a software reboot is triggered on the SoC via a crash, certain permission checks are not done compared to the regular boot.
  • By glitching the chip, this can be done. In fact, it does not require fancy equipment. Simply connect GND to the CLK for 50-100 ms during the password check and it will bypass the check.
  • This article was confusing to me. But, it seems that the soft reboot during the password prompt assumes that the system booted securely. So, it takes a shortcut if a soft reboot occurs after this point. To be honest, not sure if this is true but with the large timing window, this almost appears to be a software bug than a hardware bug.

Cookieless DuoDrop: IIS Auth Bypass & App Pool Privesc in ASP.NET Framework (CVE-2023-36899)- 1221

Soroush Dalili    Reference →Posted 2 Years Ago
  • On the web, the go to method for maintaining state in the stateless HTTP protocol is cookies. The .NET framework included a way of putting cookies into the URL for clients who couldn't support cookies. This had the view of S(aaaaaaaaaaaaaaaaaaaaaaaa) in part of the path of the URL.
  • Historically, this has been real bad for WAFs and session related issues such as session fixation, session hijacking and more. The author includes a link to various posts about previous issues. Due to these security concerns, the feature was removed from the .NET core in newer versions.
  • From the WAF bypasses the author posted on Twitter, it's clear that putting sessions into the middle of a URL causes weird problems. While testing new WAF bypass techniques, they noticed two weird anomalies.
  • The cookieless feature could circumvent the protected directories and URL filters in IIS. Normally, paths in these locations would be blocked. However, by including two sessions in the URL, the validation was bypassed. Why does this occur?
  • In the rewrite portion of the cookieless paths in the .NET framework, it appears to only perform the removal once for verification. Then, during the resolution process, it will remove the second session and allow the user to access the path. At least, this is what it seems like but it's not explained very well.
  • In IIS, there are application pools. Some paths could use one pool while others would use another. By using the double session path from above, it is possible to create pool confusion. This can lead to a privilege escalation, given the right scenario.
  • Interesting bug! It turns out that string parsing is very hard to do correctly. Double adding a value is something I'll be testing for in the future.