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!

Aave v3 bug bounty part 2: Aave liquidation process uses the wrong value... - 1240

StErMi    Reference →Posted 2 Years Ago
  • Aave is a very common loan protocol in the web3 space. Liquidation is the process of getting back the tokens of a loan in exchange for a discounted rate on the users collateral.
  • For instance, imagine I took out a loan for 1 ETH for 2000 USDC with a threshold of 10% (USDC to ETH is probably around 1800). If I wasn't repaying my interest or the cost of USDC dropped,another user could come in to supply the 1ETH and get 1850 USDC back for this. This keeps the protocol solvant.
  • e-mode (efficiency mode) is an asset that is consistent in price with a pegged value, like USDC. When getting the price of user assets, the program will check to see if the price should be gotten from the default location or the e-mode location. This is done by passing in the collateralPriceSource and debtPriceSource variables.
  • The assumption is that the debtPriceSource should be the price source for the e-mode category. This is imposed by the restriction that if a user is in e-mode, they should only be able to borrow assets that belong to this users e-mode. Can this be violated?
  • If the following situation occurs, this can be violated:
    • E-mode is using a custom oracle.
    • The debt asset that is liquidated has been removed from e-mode.
  • What's the consequence of this? The calculations get messed up on the liquidation process. Because the user being in an e-mode state is checked while adding the tokens, the logic explained above takes a weird turn. It will get the wrong price as a result. The e-mode price returns a nice pegged value, which is much cheaper than using an oracle like chainlink.
  • If USDC was depegged from $1 to $2, then the liquidator would only get half of what they deserve. If it depegged from $1 to $0.5, they would get double they deserve. This is a pretty drastic consequence, especially with large loans.
  • To fix this issue, the e-mode price should only be used if the e-mode flag on both the user and the oracle is set. This felt like a reasonable optimization but the complicated system led to this issue.
  • To me, a single thing stands out: this is a completely crazy situation that the author of this conjured up. However, this is a legit scenario that could happen with an admin acting in a sane manner. Did they see the separation between the user e-mode flag and the oracle e-mode flag and come up with this?

Aave v3 bug bounty part 1: Security concerns and improvements about the `executeFlashLoan` function- 1239

StErMi    Reference →Posted 2 Years Ago
  • Aave is a very common laon protocol in the web3 space. A flashloan is a loan that occurs within a single transaction. By doing this, a user can get access to a large amount of money without the owner risking anything. Usually, there is a fee associated with providing the flash loan.
  • On Aave, this fee is called a premium. The user asks for a specific amount, then a percentage is added on top of this for what they are required to pay back. Aave calls a callback function in the users smart contract for this.
  • Once a user goes to repay the flashloan, the function validates that the original funds were paid back. On the premium, it checks to see if this was paid back OR opens a position on the amount that needs to be repaid.
  • When specifying the position that needs to be taken, there is a miscalculation on the approval price. Some of the funds will not be sent in this case, resulting in leftover funds that Aave could spend. If a hack occurred of Aave, this would be a bad avenue for exploitation. Additionally, this logs a wrong event.
  • USDT does not follow the ERC20 standard for both returning a bool on successful execution or approvals with a value greater than zero. Both of these can lead to reverts, sadly. This issue is present in the standard template for flashloans on Aave, which makes it more interesting of an issue.
  • Overall, this is a defense-in-depth issue that was fairly complicated to encounter and understand. Not a very big problem in Aave.

AMM MEV BACKRUNNING - 1238

@NBFinanceTech - Open Sense    Reference →Posted 2 Years Ago
  • Different types of bot actions with frontrunning/backrunning with various markets:
    • Sandwiching: Increase the price of the asset, let the trade happen, then trade back to make a profit.
    • Sniping: Buy coins or assets as soon as they are listed.
    • Backrunning: Arbitrage price inefficienies within an AMM. Usually the result of large trades.
    • Just in time liquidity: Provide assets for a very short period of time for a single trade. Then, remove the assets after the trade to get the fees for providing liquidity. Only valuable for large trades.
  • This talk is about creating a backrunning bot that are mathematically optimal, which was prior to flashbots. The goal is to arbitrage (go from market A to market B to make a profit from the spread of the price) the differences between various pools. The author treats this as a graph theory problem where each token is a node and each AMM is a line to a different node. Using this, we can find a list of tokens to AMMs that could make a profit.
  • The first step is getting all of the data. These are pairs with tokens that have value (not meme coins) and the ratio (price) of these in the pool. From there, the author does an initial pass of these tokens from WETH to another token to see if the value went up or down in a breadth-first search pattern to see if the trading situation is good. If not, these tokens/pools are simply dropped.
  • Next, a depth first search is performed to find the best cycle possible. With the removal of meme coins and bad pools, this makes the search space tenable. To find the most optimal amount to trade on Uniswap is fairly easy. With Balancer, this is a much more complicated problem with the amount of tokens at place. So, this required using Newton's Method to find the profitability of various operations.
  • To execute this, the transaction is put on the network; but the work isn't done. Now, we need to check to see if there's any competition. If there's a collision in the tx.data, we need to see if our transaction will go through first or not. If it won't then will "fold" our previous transaction sent to minimize the loss, which is done by checking profitability at run time. We could also raise our gas price to see to try to get the transaction executed first.
  • Folds are important because only a single person can win the arbitrage. Additionally, there is some game theory here. The goal isn't to win a single opportunity; it's to win the most over time. So, sometimes, losing money by raising is more optimal than letting your opponent win. Over time, if you have a deeper pocket, you'll knock competitors out of the market. Obfuscating the code that is running to prevent people from doing this as well.
  • To make this more efficient, there are many things that you can do. First, caching is crucial. The paths can be cached and only updated on changes. This also goes for network requests for the pair information as well.
  • How is slippage dealt with on these calls? I'm not 100% sure. However, I've got some thoughts. Putting a transaction in the mempool will result in one of the pools being arbitraged or changed from a simple trade. If we can use the right amount of gas to ensure we're at the beginning of a block, this doesn't matter though. Additionally, there is a time of check vs. time of use (TOCTOU) issue, since the blockchain is always being updated. From my understanding, there's a gap (since transactions happen in blocks) so this isn't as much of a problem though.
  • At the end, the speaker gives advice on how to get into this: find a niche. JaredFromSubway will kill you if you try to start in his territory. So, finding a weird protocol on some sidechain with little competition works well for starting off. Then, you can work your way up to bigger and bigger things as you learn and build out infrastructure.
  • Overall, a good trip into the dark forest of MEV. It's fascinating seeing the optimization that goes into all of this.

From Terminal Output to Arbitrary Remote Code Execution- 1237

solid-snail    Reference →Posted 2 Years Ago
  • Terminals are the most common way for developers to interact with computers. The control codes of this is conveyed in-band to the users. Escape sequences like \x1b[32m are a good example of this. The author decided to look into the iTerm2 emulator.
  • Similar to phone phreaking back in the day, the goal of the attack is to use arbitrary characters printed to the terminal to change the control flow of the terminal itself.
  • The idea behind the attack is sticking characters into stdin via terminal escape codes. By doing this, we can force a command to be executed. The payload is a complete mess to look at. But, the concept is simply this with various twists.
  • For instance, the \x1b[5n code is a Device Status Report (DSR). This will end up pushes the character n to stdin. By using this, and various other things, we craft arbitrary commands.
  • Then, we push the command arg1|m4 using various schengians of pushing data to stdin. The m4 command is a C/C++ macro engine, allowing for code execution via the previous input of syscmd(open -a Calculator).
  • The line \x1bP1000p%session-changed $9 s\n acts a tmux (terminal multiplexor) command that will press enter for us, executing our command now in stdin.
  • I don't fully understand the payload. There's a lot of juggling between things and the actual reason for searching through history isn't very well explained. Regardless, I loved the attack method and hope to see many more of these in the future.

How Cross-Site Frame Counting Exposes Private Repositories on GitHub- 1236

medi    Reference →Posted 2 Years Ago
  • Cross-site frame counting is a technique for counting the amount of window references (iFrames) from external websites. This is not a vulnerability by itself but can be used to leak private information. For instance, if there's an iFrame for a user logged into a site and no iFrame if not, then this leaks that the user is logged in.
  • - While testing VS-Codespaces integration with Github, the author noticed a quirk about the iFrames:
    • 2 iFrames2 iFrames: The private repository exists but the file does not.
    • 1 iFrame: The private repository exists and the file both exist.
    • 0 iFrames: The private repository does not exist.
  • So, we can determine the state of a user based upon the number of frames. Neat! The exploit is a loop of opening a location in the browser by setting the win.location and checking how many frames were loaded.
  • How do you fix this? You load a consistent number of iFrames no matter the state. Overall, interesting bug with pretty significant impact.

When URL parsers disagree (CVE-2023-38633)- 1235

Zac Sims - Canva     Reference →Posted 2 Years Ago
  • URL parsing is super hard to do properly. There is a standard that has been updated and changed over the years. Additionally, if there is a difference in verification vs. use at any point, this can lead to massive security issues. In this article, they were looking at an SVG parser.
  • Previous research has showed that the Inkscape CLI parser is vulnerable to path traversal within rendered SVGs. Within this parser, the XInclude format is also supported, a method of merging XML documents (SVGs are just XML). The underlying library for Inkscape is librsvg, which Canva uses.
  • Within librsvg, every URL goes through validation to ensure it is not malicious. For instance, being able to include arbitrary local files would be a big no-no. The rules are VERY strict, making it relatively safe to use.
  • The parser for validation is done with one parser but the loading of the SVG is done using the parser Gio. Anytime there are two parsers operating on the same data, there is likely many bugs lurking. A slight misunderstanding on one end could lead to the break you need.
  • The authors of the post setup a fuzzer to test the differences in the file resolve process. While doing this, they noticed that current.svg?../../../../../../../etc/passwd passes the validation but can resolve files. How is this? From my understanding, the ? gets stripped from the resolver and is unhandled by the validator.
  • The Gio parser will happily traverse files and traverse further up. A canonicalization process is done on the link. As it turns out, it starts in the directory in which the program is at. So, placing a . at the beginning can be used to force the program to traverse further up.
  • The full SVG link is .?../../../../../../../etc/passwd. To me, this really shows the power of differential fuzzing. Who would have thought about a question mark in the path? Not me, only the fuzzer.
  • At the end, they note some interesting things going forward for similar research. My favorite is that the file URIs support query strings, but this varies depending on the library.

CVE-2016-4484: Cryptsetup Initrd root Shell- 1234

Hector Marco & Ismael Ripoll - Cybersecurity Group    Reference →Posted 2 Years Ago
  • Cryptsetup is used to unlock the system partition when using the Linux Unified Key Setup (LUKS). This is all about full disk encryption!
  • When booting up in Linux, there is a special file system called initramfs that runs before Linux has been fully added but after the bootloader like GRUB. This state initializes the Linux OS and the root partition. So, by design, initramfs is used to decrypt the main file system.
  • When using LUKS, a user must provide a password or one must be given from the TPM. If this fails, then a user can try again. If this fails more than 3 times, then the system reboots. If this fails 30 times on x86 machines, then the machine goes into a state where it feels it's broken.
  • What should the system do if it's broken? By default, this drops into an initramfs shell. In this case, we can modify initramfs, continue the boot process and more. This is NOT supposed to happen if LUKS is being used for file system encryption though.
  • This is where the bug is at. When checking to see if the maximum number of attempts has been checked, the bash statement will always return false, taking the wrong path. This ends up being horrible, since the system drops into the shell when it shouldn't.
  • What can you actually do in this state? By modifying the initramfs state, you could modify the boot procedure. Even worse, with auto-decryption via TPMs, we can bypass the boot policies that would normally restrict decrypting the file system.
  • How do you perform this exploit? Pressing enter 93 times. The authors believed that this bug was added in via new features being introduced into the system without considering the global issues. As people say "Complexity is the worst enemy of security." Overall, a good post on boot security.

Mashing Enter to Bypass Full Disk Encryption with TPM, Clevis, Dracut and Systemd - 1233

Michael Fincham - Pulse Security    Reference →Posted 2 Years Ago
  • Full disk encryption for an unintended computer is a surprising difficult problem to solve. A classic way of doing this is using a TPM to store an encryption key but only having the encryption key accessible if the computer is in the right state via policy sessions. Because of the policy, it's not possible to modify the running code. Because of the FDE, it's not possible to modify the file system, making for a secure system.
  • The above approach has a problem with bus sniffing to get the key but working very well otherwise.
  • An unattended disk encryption setup still allows a user to view the output of the boot process or manually enter the key if something goes wrong. Usually, a screen is presented for interacting with this functionality but quickly goes into the boot process if the TPM is active and working.
  • In the automatic flow, there is room for logic bugs. If an attacker can interact with the system after decryption but before the full load of the OS, then they could cause havoc.
  • In 2016, Debian's cryptsetup startup script allowed for holding the ENTER key to gain root access to an early boot environment. Since this was post decryption, an attacker with a root shell could modify the file system or do whatever they want to compromise the system.
  • The author decided to perform fuzzing to see what would happen. This was using an Atmel Microcontroller to enter key presses very fast, in a similar way to a rubber ducky. The program pressed the ENTER key every 10 milliseconds, which is much faster than just holding down the key on a keyboard.
  • By doing this, the key presses restrict the auto decryption and autoboot from happening. Because of all the failures, it goes into a recovery mode with a root shell in an early boot env. Once there, we can call basic TPM commands to decrypt the drive, bypassing the FDE.
  • Why does this occur? It's super complicated. An agent plugin is used for systemd with a pool of different responders from these plugins. When using both dracut and clevis at the same time, Clevis implements a systemd password agent for unlocking, but the user may also enter a password using the normal interactive agent. For whatever reason (which I don't fully get), this puts it into a very weird state that drops us into an emergency shell at the end.
  • A super interesting flaw in the low level process. It's fascinating that simply pressing enter can bypass the boot process. This architecture seems to be at fault; I'd wonder if similar types of bugs exist in this system from this design.

Commit-Reveal scheme in Solidity- 1232

Srinivas Joshi - Coinmonks    Reference →Posted 2 Years Ago
  • A commit-reveal scheme is a mechanism to have a secret value on chain without actually disclosing it until it's necessary. This is useful since everything on the blockchain is public.
  • The commit is a user setting a hash with unique values to them. This hash is generated from a secret value offline, which will be provided later.
  • The reveal is a user specifying their secret value. Of course, we check that the offline hash matches the contract generated hash to ensure that the value is the proper one. At this point, a decision can be made on whatever values we are operating on.
  • Why is this useful? Frontrunning can be used if a user submits a transaction where they will make a bunch of money from a secret. Additionally, secrets on the blockchain are public.
  • To do this correctly, there is a commit window and a reveal window. These should never overlap; otherwise, frontrunning will be possible. Additionally, the hash should not just be based upon the value but the address making the call; this is to prevent simple replay attacks.
  • The rest of this article is a code implementation of how this works. Overall, interesting scheme to work around a blockchain limitation.

Huckleberry: IBC Event Hallucinations- 1231

Felix Wilhelm - JumpCrypto    Reference →Posted 2 Years Ago
  • The Cosmos SDK is a blockchain development framework for application specific blockchains. Built into its core is blockchain interoperability by IBC (interblockchain communication).
  • Within the Cosmos SDK and most other blockchains, there are events. This makes it easy for off-chain applications to monitor the blockchain and query its state then act on these messages. So, keeping these events valid is important for the security of the system.
  • When communicating via IBC with two blockchains, a relayer sends over the data with a MsgRecvPacket message. If an error occurs within this handling, the blockchain cannot revert. This is because the other chain communicating needs to revert the state changes that were supposed to happen (but failed) from chain A to chain B.
  • So, instead, it uses an IBC acknowledgement message. Successful ack means the call succeeded and a failure indicates that the call to IBC failed for whatever reason. The relayer would then send the result from the target chain back to the original chain to revert the changes.
  • When handling an IBC packet with a failure, the event is still emitted due to poorly written code. Why is this bad? The events are emitted, even though the state changes were never made. As a result, any off-chain program listening would believe this went through when it really didn't.
  • The author calls with a "hallucination", which is a really good name for this. To trigger this, we must force a bad ack event. With CosmWasm, this is trivial through the built in IBC support. Then, to exploit this, an attacker can trigger arbitrary actions through CosmWasm, such as a bridge request. From there, this will have bad events emitted, tricking whatever off-chain applications. For non CosmWasm chains, other methods may be possible to trigger this.
  • What else is vulnerable? A decentralized exchange that requires transfer from one chain to another that is looking for events could be vulnerable. Additionally, various bridges could have been exploited in this way as well.
  • Overall, a really simple issue that was overlooked by the developers that caused a very serious problem. This was a really good find by Felix on the Cosmos SDK side.