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!

Safemoon 8.9M Hack- 1115

DeFi Mark    Reference →Posted 3 Years Ago
  • SafeMoon is a blockchain company that trades on the BNB chain. They are trying to put crytocurrency into the future, such as a debit card and some other products.
  • SafeMoon was just hacked for 8.9M dollars. The contract has a burn function, which is used for removing tokens from the total supply in circulation.
  • Since the cost is commonly associated with the total supply of tokens, being able to make or destroy tokens at will has effects in other places. In this case, the attacker used this to remove the SFM (SafeMoon) tokens from the Safemoon-WBNB Liquidity Pool to raise the price of SFM. They then sold SFM into the LP at a very overpriced rate to steal money.
  • What's interesting about this bug, it that the security issue was deployed only hours before being exploited. It is super crazy how this code was published without being audited first.
  • Public burns are bad. Being able to burn arbitrary tokens from users accounts is a massive access control issue. Somebody plugged this into ChatGPT, which even found the bug!

DeFi Glossary- 1114

Bytes032    Reference →Posted 3 Years Ago
  • The author of this post is a prominent blockchain security researcher. This post contains a large list of blockchain and finance words explained. For me, the weird ones are the finance words with explanations.

Web Cache Deception on OpenAI- 1113

Nagil    Reference →Posted 3 Years Ago
  • Caching is customized all over the place and many developers don't consider the ramifications of their actions. As a result, if sensitive data can be cached, then an attacker can steal this information.
  • Web Cache Deception relies on two quirks: caching by file extension and relaxed routing. The first one is obvious and common: cache based upon the extension, such as .js or other static files. Secondly, the routing needs to accept requests that are not exactly the expectation, including things with random file endings. For instance, /auth/test.css could still route to /auth.
  • With the combination of these two actions, a new vulnerability is born! If both of these are meant, then we can force specific routes to be cached that are unintended! This can lead to a major information disclosure.
  • In the case of OpenAI, they were using Cloudflare for caching. They will cache all static file types, such as .css and .js. OpenAI's website also had relaxed routing. The route /auth/sesssion/test.css and /auth/session/ would both be accepted by the web server.
  • The route /api/auth/session would return a users account information, including a session token. To exploit this, the Twitter user Nagil used the technique above and added victim.css to the end of it. The full link for the victim to click on is https://chat.openai.com/api/auth/session/victim.css.
  • Once the link was clicked on by the user, the item would be cached! Then, an attacker could go view the request to steal the session information. With the session JWT, they could likely takeover the account.
  • The fix was to not cache this specific endpoint. However, I find this extremely brittle. There are likely other endpoints with sensitive data that could be abused in this way. Overall, interesting finding on a new and hip website.

Euler Finance Incident Post-Mortem- 1112

Omniscia    Reference →Posted 3 Years Ago
  • When handling loans in the land of DeFi, extra considerations need to be taken compared to the real world.
  • There are two main parties with loans: lender and borrower. The lender is the entity allowing a user to borrow their funds. The borrower is the entity using the other entities funds.
  • In order to ensure the lender gets their money back, a user must provide collateral, otherwise known as an asset that can be kept if the value is not returned. To ensure that the borrower doesn't lose money, the borrower needs to provide more money than what they are borrowing.
  • What if the asset of the collateral drops in value? The borrower has no incentive to give the money back, since the asset they borrowed is worth more. To prevent this problem, loans can be liquidated by the liquidator. The liquidator can pay back the lender of the original asset and purchase the collateral at a discount.
  • Euler Finance protocol is a lending and borrowing DeFi protocol. The function for donation had a vulnerability in it that is very subtle. When making a donation, there is no check to see if the value being donated makes a loan underwater (bad). This can be abused to dramatically skew the loan.
  • Now, the interesting part: since the loan is in a bad state, somebody can come and liquidate it. However, the discount on the collateral is proportional to how bad the state of the loan is. As a result, if we donate a large amount of our loan, the state of the loan will be drastically skewed.
  • When the liquidator comes to purchase the assets back, the percentage discount can be pushed to 20%. From the attack, the author made 8.7M USD in funds by getting the very large discount on the liquidation.
  • Overall, a really interesting post on a huge hack. The loan system explained in this post is super helpful as well.

Demystifying Exploitable Bugs in Smart Contracts- 1111

Zhuo Zhang & Others    Reference →Posted 3 Years Ago
  • This article dives into finding exploitable smart contract vulnerabilities. In particular, it tries to find methodologies for vulnerability classes that are missed by static and dynamic analysis tools. Several classes, such as integer overflows and reeentrancy, can be detected with analysis, while others cannot.
  • The paper uses vulnerabilities from Code4rena and real world exploits. It compares the bugs that were discovered between the two locations, making a distinction on difficulty from these two. Unfortunately, there are only are handful of bugs on the real world exploit-side though.
  • They group the bugs that cannot be found by automated analysis into a several categories, with clear and defined ways to identify them. First, they talk about Price Oracle Manipulation. When operating an AMM or using money, a price must be generated for this. If this is done insecurely, then the price of an asset can be manipulated somehow. For finding this vulnerability, the author mentions looking at how prices are generated and see if any of the variables in the algorithm can be changed quickly.
  • The next one is privilege escalation, a sequence of events to bypass access controls. In the example contract, there is a proposal vote that forces action to be in separate blocks (vote and end). The passing of a proposal is calculated based upon the amount of votingToken given to the contract. Although the vote function is the only way to send tokens directly, a user can manipulate the funds in a single block by taking out a flash loan, transfer the funds to the contract, end the proposal then claim all of the locked funds.
  • For finding these bugs, the author talks about critical access controls checks being violated by internal or external calls to this contract. The difficultly in identifying this bug was that it requires domain specific knowledge in order to understand the implications.
  • The final bug class with a good example is atomic violations. In the world of Ethereum, this means demanding that state variables cannot be accessed by other flows while they are on-going. An example of this is a lottery system which tries to force lottery number picking to be different than submitting. However, a bug in the contract allows a user to look in the mempool (by frontrunning) to see if a number has been placed. If this is true, then they can place the correct number. Looking for proper use of booleans and lock variables is how to find these bugs.
  • The author also mentions a few other bug classes:
    • Erroneous Accounting: Complex math operations going wrong. This can be a bad yield percentage, inflation, infinite burn and weird numerical issues.
    • ID Uniqueness: Orders and NFT IDs should be unique in order to ensure the owner can act on it. If IDs can be duplicated in some way, a major problem can occur, similar to access control violations.
    • Inconsistent State Updates: Many variables are correlated with each other for a user, such as credit limit being proportional to a user collateral. If some state is updated but another is not, major problems occur.
  • To me, a lot of these violations can be solved with three questions: what are the threats for this contract, what are the security controls to prevent these threats and how can these controls be violated? The authors of this post used this knowledge to find 100K worth of bugs. They found two oracle manipulations, two erroneous accounting bugs, four privilege escalation bugs, two atomicity violations, one of both bad state updates and ID uniqueness and three contract implementation specific bugs. Pretty awesome paper with good thoughts on discovery!

The Uniswap Skim() token balance attack- 1110

Ancilia Inc.    Reference →Posted 3 Years Ago
  • In Uniswap, the skim function is used for a recovery mechanism in the case of the reserves storage (uint112) failing. If the difference between the current balance of the pair (balanceOf on the ERC20 token) and the reserves are different, the sender of the request gets the difference. Although this can save the contract, this is a very dangerous function to have in.
  • In the case of this particular coin, the balanceOf function is controlled the true balance of the user, _largeTotal, and _totalSupply. If any of these change, the balanceOf call will also change.
  • The function transfer will update the totalSupply whenever a transfer occurs. The problem is that there is no validation on whether the sender and recipient are the same! This means that the _totalSupply can be inflated indefinitely.
  • Since the price of the balanceOf function relies upon the totalSupply, it will increase the result! This means that the cost of the reserves and the amount that the tokens has is different. Using the skim function allows a user to withdraw funds now.
  • In particular, an attacker needs to call skim using the contract address over and over again. Since the totalSupply is updated over and over again and this changes the price, the funds of the Uniswap pool can be stolen using the skim. Overall, a very interesting attack exploiting how Uniswap works in conjunction with a bad vulnerability within the ERC20 token.

OpenBSD system-call-origin verification- 1109

Jake Edge - LWN    Reference →Posted 3 Years Ago
  • This post is from 2019, not was a defense-in-depth measure that I had not seen before. So, I thought it was worth making a note about!
  • In OpenBSD, the system will block all system calls (syscall) NOT made by LibC wrappers. This prevents the usage of shellcode with syscalls in it. One could make the argument that an attacker could simply use Return Oriented Programming, right?
  • The OpenBSD kernel relinks libc into a randomize location at boot. This means that the offsets into LibC are not obvious. So, ROPing into LibC isn't nearly as much of an option.
  • The overall goal is to remove all syscalls that are outside of libc. The main program text segment needs to be in the list of memory regions where system calls are allowed to come from. The kernel can mark regions are valid for syscalls with the msyscall, since it can only be called once per process.
  • For static binaries, the valid regions to make the calls would only be the text segment and the signal trampoline page. For dynamic binaries, ld.so/libc.so text, signal trampoline and the main programs text are the only regions.
  • Together, these features are a powerful protection against ROP. Being able to restrict where syscalls can be run in combination with libc function stub randomization, PIE and everything else would be major blockers in the binary exploitation front.

How was Dynamic Finance Exploited? - 1108

Shashank    Reference →Posted 3 Years Ago
  • Dynamic is a money market aggregator built that helps to enhance the DeFi lending experience.
  • DYNA is the token of the ecosystem. When staking this token, a user can earn interest on it. The amount of interest is directly correlated to the length of time the token has been staked.
  • If the more funds are added, then the portion should be changed. For instance, if I stake 5 DYNA then wait a month, I should get that interest. However, if I add funds to the contract after this point, the rewards of the new tokens should start from that point on.
  • The code was not updating the information related to time. As a result, an attacker could stake a little amount of funds to rake up some time. Then, stake a HUGE amount of funds to make the contract believe we had staked these funds for a while. With this, we could extract wayyyy more value from the contract than we should be able to.
  • In the real world, the attacker has a flash loan to make the amount of tokens much larger. Interesting hack when the time is not properly updated.

Readline crime: exploiting a SUID logic bug- 1107

Rory M - Trail of Bits    Reference →Posted 3 Years Ago
  • After Qualys posted a sudo vulnerability that shook the world a while ago, the author of the post was wondering what other setuid binaries installed have vulnerabilities. They specifically decided to look into how environmental variables for programs were being used. They tried this ENV being set with all of the setuid binaries on their system.
  • To test for environment variables, they added preloaded a library that simply logged all requests to getenv(). After going through a bunch of dead ends, the variable INPUTRC appeared. This is used for a configuration file.
  • They set the environment variable to /etc/shadow, hoping that something interesting could be leaked. While running chfn, the output of the program indicated that it was read! However, nothing useful was outputted.
  • The author decided to search through the source code to finding something interesting. Within the readline library was where this environment variable was doing its damage. While parsing through the configuration file, it will output the errors and badly parsed data. So, what gets outputted in the errors? Can we trick it to output something useful?
  • A line that begins with a quotation mark without a closing mark will get outputted. Additionally, a line that starts with a colon with no whitespace. Finally, and the most useful, a line without a space, tab or colon will output the entire line! SSH keys match this pattern, since its base64 encoded data.
  • What's the punch line? Don't use readline in setuid binaries. The binary could simply just clear this ENV variable as well. To me, the blame on the bug is hard to put. Is it reasonable for the maintainers of chfn to know this quirk? Additionally, is it reasonable for readline to output this errors? To me, the blame isn't on any of these devs.
  • Overall, great article that is concise, well-written and has many good jokes. setuid bugs aren't dead!

Yearn BribeV2 Voting Power Bug- 1106

Yearn    Reference →Posted 3 Years Ago
  • Yearn is a decentralized suite of products for managing yield of digital assets. The Yearn system was using Curve creation called veCRV (vote-escrowed CRV). Users will lock their tokens away for an extended period of time. As the balance decays of veCRV, the relative voting power for the system does as well.
  • Yearn comes into play here with BribeV2. The idea was to incentivize veCRV voters to make their votes to increase the emissions of CRV. A user could post their tokens into BribeV2 and the contract calculates how much relative voting power they should have. It should be noted that the gauge weights are determined by their veCRV balance instead of the users locked amount.
  • While viewing the SPELL bribes, the authors of Yearn noticed an irregularity. While calculating the amount of control of the system, Yearn was using the slope value instead of the bias value. The slope value is the veCRV is the decay rate per second of their locked amount without their lock duration. This is terrible, because a user would get paid out an equal rate compared to somebody who has locked their tokens away for a long time.
  • Because CRV can be withdrawn after a week, an attacker can cycle the same CRV through multiple wallets to perform the attacks mentioned above. Yikes! How did the devs miss something this bad? Interesting finding none-the-less.