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!

Response Header Injection in SAP HTTP Content Server- 1275

Hero Lab    Reference →Posted 2 Years Ago
  • A URL parameter within a call was being used within the headers of a request. In particular, the pVersion parameter of the request. It was being copied into the x-errordescription header without checking the content of it.
  • Since an attacker controls this and the web server does not protect against it, an attacker can add in newlines to change the meaning of the request. This is called CRLF injection.
  • Since they can added content to the headers (and to the body!) they can change the Content-Type of the request! Additionally, they can add in their own body, which will be interpreted as HTML. So, the authors get XSS using this technique, which is pretty sick. Flask prevents this by default, citing that "Header values must not contain newline characters".

Tsshock- 1274

Verichain    Reference →Posted 2 Years Ago
  • At the core of Multi-party Computation (MPC) wallets are Threshold Signature Schemes (TSS). This allows for the decentralized ownership of a single key, which is pretty amazing. The TSS scheme is used to generate keys and sign then (t of n) with no trusted dealer.
  • The TSS system used in major blockchains commonly uses Elliptic Curve Digital Signature Algorithm (ECDSA). A protocol for TSS using ECDSA utilizing homomorphic encryption and zero knowledge proofs was created in 2019.
  • In an audit from Kudelshi Security of the TSS-lib of Binance, a report was made titled interface prone to collisions. Aka, hash collision by improperly concatenating values together. The issue was that a single array of values, such as [a,$,b,$] could be interpreted the same as two independent arrays like [a] and [b]. Originally, this was flagged as only a low severity finding.
  • The authors of this post found that the ambiguous encoding scheme could be used to recover the private key. When performing a Fiat-shamir transformation, an encoding scheme is involved to serialize the to-be-hashed transcript to bytes. Hence, if the encoding is ambiguous, major issues can occur.
  • Under the hood, this attacked the dlnproof mechanism. By attacking the alpha value with our ambiguous number issue, a bits can be leaked from the key one by one. This takes a lot of computation and interactions between all of the owners of the key but can be done.
  • The next issue was with the optimizations being made by the projects. In one project, the number of iterations for the dlnproof was reduced from 128 to 1. By guessing challenge bits when computing this proof with small iterations, we can forge the response. I don't understand the protocol but this seems to give us information about the key being used.
  • The final issue was another optimization problem. When doing the dlnproof, they only ran the check a single time in some projects. The challenge being performed here is similar to a log proof for a group of prime order. But, with this, the order is not prime but composite. As a result, it's possible to brute force a value that fits the mold. Now, the secret values are mod e instead of mod n. To recover the secret, another signing phase alongside lattice attacks can be performed.
  • Many of these issues come from the unsoundness of optimizations and a bad implementation flaw. For the optimization problems, following the paper would be have sufficient. It is worth modifying cryptographers algorithms? 100% not! Even the auditors looking at these protocols are probably not qualified to find those types of novel issues; these attacks are very complicated and take months to full of.

Crosschain Risk Framework - 1273

Crosschain Risk Framework     Reference →Posted 2 Years Ago
  • Ethereum was a great prototype for a blockchain that can execute arbitrary code. However, at this point, it's fairly slow and pricey. As a result, many projects are trying to scale Ethereum and move assets to/from it.
  • Doing so is very complicated! This wiki describes many of the patterns used for this, use cases and security threats. Just wanted to put here as documentation for later.

Uncovering a ZK-EVM Soundness Bug in zkSync Era- 1272

ChainLight    Reference →Posted 2 Years Ago
  • zkSync Era is one of the most popular l2 blockchains. It utilizes zero knowledge proofs to demonstrate knowledge of something without giving up said information. zk-SNARKs are a variant of ZK proofs that don't require any special interactions between users. The authors of this post found a substantial vulnerability in how this was done that is explained.
  • ZK Circuits are similar to boolean circuits with computers that have both gates and wires. Instead of using boolean, these use polynomials. With the arithmetic gates, the boolean operations become things like addition or multiplication. To do the proof, inputs are provided to a system which produce a specific output. By doing this in a zero-knowledge way, we can create arbitrary logic within the system.
  • In this ecosystem, they used it to build a zk EVM with some modifications to the opcode set and how the stuff functions. These circuits are incredibly complicated with a ton of stuff going on. The memory queue is where the bugs live at. This is all about reading and writing to memory. The main VM circuit cannot constrain the memory operations so its stored in a queue instead.
  • When calling creating the constraints in this library, specific functions need to be called. This takes the circuits and ensures that the expected values are being outputted.
  • When performing memory write operations, the constraint was NOT properly added on top of a linear combination. In particular, something like lc.enforce_zero(cs) was missing from the code. Practically, this meant that the upper 128 bits of the MemoryWriteQuery are unconstrained! To make this more clear, the upper 128 bits of any value in memory can be altered!
  • Having the ability to edit the upper 128 bits of memory is a trivial game over. The authors decided to exploit the L2EthToken within the bridge functionality. By sending a little amount of ETH to this contract then modifying the 128 upper bits, a small amount can be transitioned into a large amount! Turning 0.00002 ETH into 100K ETH.
  • Overall, it's a really interesting vulnerability with crazy impact. The creation of Circuits and constraints is very complicated with many footguns along the way. Good find by the chainlight people!

Super Hexagon: A Journey from EL0 to S-EL3- 1271

Grant Hernandez    Reference →Posted 2 Years Ago
  • This CTF challenge was a series of 6 challenges pertaining to AArch64 privilege escalation, which is similar to ARM64. The main differences are removal of Thumb instructions and doubling the general purpose registers. There are four exception levels for this: EL0, EL1, EL2 and EL3. EL0 is user mode, EL1 is supervisor, EL2 is hypervisor and EL3 is the firmware. On top of this, everything has a secure and non-secure world as well using ARM TrustZone.
  • To run this, the particpiants had to use QEMU (with patches) with a BIOS image. The first stage is a statically linked ELF binary with an arbitrary call vulnerability via a back of index checking. To get code execution within this stage, an attacker can call the gets() with stdin to overwrite the function pointers within the .bss section.
  • The LIBC is a modified version (of course), since it runs a custom minified OS. To attack the kernel, we're going to need the ability to execute arbitrary code easily. To do this, they wrote some shellcode then used the overflow to call mprotect() to make a section of memory executable. With this, we have escaped EL0 and can start attacking EL1.
  • They detail their process of reversing the EL1 code, including an IDAPython extension that comments about MSRs and very low level instructions. Once they understood the memory mapping they began hunting for SVC handler (syscall) vulnerabilities. There is a classic vulnerability: missing validation on the destination address. This is similar to copy_to_user in Linux. using this, it's an easy write-what-where primitive within the kernel without any KASLR.
  • Unfortunately, the read() syscall can only write a single byte at a time. This means we can't simply corrupt the return address on the stack to get code execution; we'll need to do something else. Eventually, they found a gadget that allows them to corrupt a single byte but jump to an arbitrary location on the PC. Before this, they need to write their shellcode into the kernel using the syscalls.
  • Right now, there is only a limited payload that can be run. So, the author wanted to go from having a flag to full on code execution. Modern kernels have Supervisor Mode Execution Prevention (SMEP) which prevents the kernel from executing code on userland pages. While stepping in GDB, they found that this setting was not turned on but got a page fault. Why is this?
  • When a processor receives a request to go from a virtual address to a physical address it does a page walk with multiple lookups. As a result, there is a Translation Lookaside Buffer (TLB) to speed up this process. These page tables have attributes like access permissions, execution permissions and more. After learning all of this, the author realized that their userland memory had bad permissions. So, they simply used their arbitrary write primitive to corrupt these bit to make the page executable from EL1. Nice!
  • To communicate with EL2, there are hypervisor calls (hvc). The only functions into EL2 were for memory allocation is via mmap(). This takes in two parameters: an address and attributes. While looking at this functionality, there is a check to ensure that the hypervisor memory region cannot be written. However, the check is performed on the physical address and attributes separately before oring the bytes together. So, we can put swap the inputs to bypass the validation but map the intended address!
  • This creates a window between the EL2 and EL1 address spaces. By calling a function in EL1 with the already mapped address from EL2, we can write into EL1 from EL2! They wrote EL2 code byte-by-byte into the RESET vector of the hypervisor. Then, once they triggered the RESET, their shellcode would execute.
  • This is a fire post on exploiting very low level systems. This is just part 1; we need to go into the secure world now. Overall, loved this post and the challenges.

A MEDIUM Smart Contract Vulnerability in Audit Contest Simple Explained- 1270

Johnny Time    Reference →Posted 2 Years Ago
  • SPARKN is a web3 protocol for people to post a problem where somebody can come up with a solution for them. This is really generally but the intent of the protocol.
  • The ProxyFactory contract serves as a gateway for users to interact with the contests. In particular, a proxy can be made for each contest to distribute rewards to its winners.
  • Within the ProxyFactory there is a function called getProxyAddress(). Given a salt and implementation address, it will return the address that the proxy will be deployed to. This is because users are expected to send funds prior to the proxy deployment to this address.
  • The vulnerability is that there is no validation that the implementation and salt will actually be correct. As a result, if they called this with bad parameters, then the funds would be sent to the wrong location, being lost forever. This was reported as a medium severity finding.
  • Bad user functionality as finding is so weird to me. As a developer, I expect my users to interact with the protocol the proper way. If they mess up, I treat this as an issue on their end. I don't agree with these types of findings. However, it does feel like easy money on contests so I'm not going to complain too loudly.

Numbers turned weapons: DoS in Osmosis’ math library- 1269

Sam Alws - Trail of Bits    Reference →Posted 2 Years Ago
  • Osmosis is a very popular decentralized exchange running on the Cosmos SDK. The authors of this post were looking at the math within this blockchain when they stumbled across an issue.
  • When performing exponentiation(ab), the program was using a Taylor series approximation. There is a point within this series that we need to say "good enough" though. So, what's the stopping point? When the changes to the approximation become so small that they don't matter any more in what the developers choose. They choose a change of less than 0.00000001.
  • There is an issue with this approach though: what if the approximation is never reached? This is bad since there was no maximum iteration on the amount of loops that could occur. For example, 1.999999999999990.1 takes over 2M iterations, taking 0.8 seconds in Go. By doing this multiple times, it leads to a denial of service via resource exhaustion.
  • Thus far, this was done via calling the PowApprox() directly. Can we trigger this on a real transaction? Yes! With the following steps on Osmosis, it was possible:
    1. Make a pool with a token weight of 0.1 and initialize it with 10. of token A.
    2. Deposit 0.99999999999999 more of tokenA.
    3. The above call triggers the approximation functionality.
    4. Do this over and over again to take down the blockchain.
  • What's interesting to me is that this leads to a transient denial of service. The attacker must continually do this in order to perform this attack. By including the new circuit breaker module to turn off this message, the blockchain could have continued for a bit. I enjoy that only two messages could be used to trigger this! Good find friends.

Footguns in Open Zeppelin- 1268

Antonio Viggiano    Reference →Posted 2 Years Ago
  • Open Zeppelin has created a large amount of contracts that are used by every EVM contract. This twitter threat is talking about several of the 'footguns' or easy ways to mess up.
  • ERC-7201 is a standard for what slots variables should go in. The idea is to stop vulnerabilities from storage layout changes when upgrading a contract. The NameSpaced storage is only done on the OpenZeppelin contracts and NOT the users contracts.
  • This means that the same classic bug classes apply. The author made a PR to make this generally available as a base class.
  • Ownable2StepUpgradeable() is a function meant to perform an other swap with an extra step in between. By doing this in 2 steps, if the new owner address is wrong or there is a mistake, then the owner will not be changed.
  • The contract inherits from OwnableUpgradable(). However, the child initializer does NOT automatically call the parent initializer. In a user doesn't call __Ownable2Step_init, then it will be left without an owner. There is a Github thread about doing this better though.
  • The researcher Dacian adds a good note as well. Many NFTs should NOT be transferable. This was done by overriding the _transfer() function. However, in V5 of the contracts, _update() is called instead. So, the previous override does not work.

Behind the Shield: Unmasking Scudo's Defenses - 1267

Kevin Denis - Synack    Reference →Posted 2 Years Ago
  • Scudo is a hardened heap allocator that has the goal of preventing heap-based vulnerability classes. It is the default allocator for Android now-a-days. This article breaks down how the allocator works and the protections in place. First, they go over the primary allocator then through the secondary allocator, which are all chunks larger than 0x10010 that are allocated via mmap() directly.
  • Scudo is made up of blocks. The blocks are compromised of a header and a chunk. The chunk is the actual data while the header contains metadata and size information.
  • The allocations are done in regions; blocks of all the same size. Region 0 keeps track of a list of storage pointers within freelists. Between these regions are guard pages to prevent cross-region corruption
  • The allocator randomizes which blocks are returned from a given region. This makes exploitation harder because heap grooming becomes much more difficult. However, the authors note that there are ways to make it more reproducible in certain situations.
  • When freeing a block, verification is done on the header and the pointer that is returned. Once it's freed, the block enters a quarantine process to make the exploitation of UAFs harder.
  • For heap overflows we can mess with the header bytes. However, the verification of the chunk occurs on free() are quite strict. So, exploit developers can either create fake valid headers or simply not let the chunk go through free via the exploit plan.
  • Standard double frees are detected by the bits within the header of the chunk. However, free-reallocate-free is not caught at all. Use after frees are not caught either; although, there is the protection of the quarantine period.
  • Overall, good post on the allocator. I didn't put every single detail into this write up but put my important points and just wanted the page as a reference.

Platypus Finance - REKT 2- 1266

Rekt    Reference →Posted 2 Years Ago
  • Platypus Finance has joined the leaderboard for a second time! The smart contracts had been audited. However, they recently added some new functionality, which got them pwned.
  • The attack was from a price manipulation issue. The swap price depends on the ratio of cash in the protocol. By manipulating the cash and liability of the protocol, the slippage drastically increases. Eventually, this leads to much less funds than anticipated to be sent for a trade.
  • To do this, the attacker takes out several large flash loans. From there, they deposit wAVAXto LP-AVAX and stake AVAX to LP-sAVAX. This was done in order to increase the liability of both the contracts.
  • Next, the attacker swaps in sAVAX to wAVAX to reduce the cash of the LP-AVAX contract. Finally, they remove all of the available cash by withdrawing the wAVAX. The setup was complete: almost no cash is within the contract.
  • The attacker performs a swap with the manipulated price to steal a bunch of funds. Absolutely wild. I don't fully understand the manipulation, since I'm not familiar with the protocol, but it's interesting none-the-less.