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!

BNB Chain’s Cross-Chain Bridge Exploit Explained- 970

samczsun    Reference →Posted 3 Years Ago
  • The cross-chain bridge for the Binance Coin (BNB) on the Binance Smart Chain (BSC) was hacked. An attacker drained 2 million in BNB (566 million in USD). How did this happen? Let's follow the twitter thread!
  • While reviewing the transactions of the attacker account, they noticed a large amount of funds that went into Venus. While reviewing the transaction from the Binance Bridge, it was clear: the bridge had been convinced to send the attacker 1 million BNB. So, it appears that the bridge has a bug in it.
  • What reconnaissance can we do before checking the code of the project? The samczsun noticed that the height of the transaction was always the same and much smaller than expected. Additionally, the withdrawal proof was sustainability shorter. It appears there is something wrong with how the proof is determining if a transaction is valid or not.
  • The Binance bridge was keeping track of the state using a self balancing tree algorithm called an AVL tree, with a twist of being immutable - IAVL While doing the verification of the operations, there are two expected operations: iavl:v and multistore. To succeed, both operations need to succeed.
  • The verification process was busted. But how? The input of the multistore operation is the output for the iavl:v operation. The function COMPUTEHASH is used to go down every path and lead node to do the verification. Since a single bit change will change the way this works, it is not realistic to trick the hash function. In particular, if we want to forge a proof, the path and leaf pair will need to stay the same.
  • For the root node in the Merkle proof, the code needs to verify each node in the chain. However, there is a slight optimization bug. If there is a left node, the right node is NOT validated. As a result, we can place an arbitrary node into the tree WITHOUT it getting validated. This functionality is described in the The PR to fix the vulnerability on Github.
  • Since we can add an arbitrary right node, all we have to do is add a leaf node to the right side with a blank inner node. By tweaking the leaf to exit early, we can still get a correct root hash despite altering the chain maliciously.
  • Wow, this was literally an issue with the core blockchain framework itself. When doing the cross-chain communication, the BSC keeps track of the state of the root hash of the other chain (Binance Chain). The bypass of the verification allowed for the creation of money that never existed.
  • Overall, a super interesting vulnerability that shouldn't have been possible. Things this big and impactful really should be tested thoroughly via dynamic testing and code review.

Cross-chain DEX Aggregator Transit Swap Hacked Analysis- 969

SlowMist    Reference →Posted 3 Years Ago
  • Transit Swap is a cross-chain exchange. It allows for aggregating all of the tokens you owe between the different platforms.
  • When performing a swap, there is a routing contract. Depending on the chain being used, a different contract is called. The routing bridge contract will is where the bug is at.
  • The function claimTokens is used to transfer tokens redeemed by the user to the routing bridge and eventually to the user. This is done by invoking the transferFrom ERC20 call on the specified token contract.
  • The vulnerability is that the user controls all of the parameters provided into the transferFrom() call from the router contract. In particular, they control the users from, to and amount. Additionally, users have to permit the contract to use the funds. Hence, with this control, they can make arbitrary calls to steal funds from all of the users.
  • The vulnerability occurs because there is no input validation on data passed during the token exchange. This is a classic confused deputy problem! A trusted entity is making the call but the input coming in abuses this trust.
  • The exploit led to $23 million in funds being stolen. The pattern for the router making calls to other contracts is a common pattern. Reviewing smart contracts individually doesn't work; the interoperability is extremely important as well. Overall, good report on the bug!

Pixel6: Booting up- 968

Gagnerot Georges - eShard    Reference →Posted 3 Years Ago
  • While reading various security advisories the author missed while on vacation, there noticed a Pixel anti-rollback notice. This indicated that a vulnerability occurred in the bootloader of the device, making it a major risk and adding an anti-rollback feature to it. Since there was no public information besides there being a bug and it says RCE, the author of the post decided to find and exploit the bug.
  • The ARM specification for the boot process is going from the Primary Boot Loader (PBL) ->BL1->->BL2->BL31->Trustzone(TZSW) and ABL. BL1 performs late architectural and platform specific initialization and runs the second BL image, which simply loads BL3. BL3 sets up he runtime services for the CPU and helps pass control to the operating system. The bootloader is in likely in BL1 because its the furthest down in the chain that isn't in ROM.
  • To find the vulnerability, they downloaded versions before and after the patch. By comparing with bindiff, it probably wouldn't be the hardest thing in the world to find the patch for the security issue. They used bindiff on the most of the fastboot commands for each of the binaries. From this, they identified a small bit of code that was removed from the command handlers.
  • There were low level commands that the fastboot console has access to - flash:raw. However, part 2 appears to refer to a vulnerability in the bootloader but doesn't actually mention what it is. Instead, they claim there's a vulnerability that allows for some sort of write primitive. So, I'm a little confused here.
  • To build a working exploit, they setup an emulator with Unicorn. The typical workflow for emulation is creating the emulator, setting up the memory in the same way as the image, initializes the device and execution. To top it off, hooks must added to native functionality that cannot be emulated.
  • With the debugging environment setup, the hacking can be done. To get a nice read/write primitive, we can probably reuse existing code. The internal commands (without handlers) download for reading content and upload for writing content.
  • Overall, the posts are mildly confusing, as not everything is laid out perfectly. In particular, the vulnerability is not defined well and the wording in the second post can be confusing. However, the process for reverse engineering, emulation and exploit methodology was very interesting!

Hacking TMNF: Part 2 - Exploiting a blind format string bug- 967

bricked.tech    Reference →Posted 3 Years Ago
  • In the previous post, a format string vulnerability was found that led to a crash. This post is all about exploiting the vulnerability to get code execution. The vulnerability occurs in the stdout logging because of a call to fprintf taking in a user controlled string with no other parameters.
  • Simply sending a %99999s will crash the program. What else can we do besides crash? With format string bugs, the identifier %n can be used to perform writes. However, the format string is stored on the heap. This means that the simple <target addr>%x$n doesn't work. This is because the format string parser will attempt to find data on the stack for pointers and it will not be our controlled data.
  • Although we cannot control the location being written to via %n, we can still write to ANY pointer on the stack with a user controlled value. What if there are user controlled pointers on the stack though? By design, the Base Pointer (BP) is exactly this.
  • So, here's the trick. Since we can perform this format string vulnerability multiple times, we can abuse that. On the first write, we'll use a pointer on the stack to write a user controlled value on the stack. This will be the address we want to write in the future. On the second write, we will use the <target addr>%x$n trick with this address and other user controlled value by incrementing the amount of spaces in use. With this technique, we have an arbitrary write primitive!
  • Let's make this primitive better! Currently, it is writing 134.5 MB of padding to stdout because of the amount of filler bytes required for %n to write the address. To get around this, the %hhn specifier can be used to write a single byte at a time. This led to a 1/16 chance that the attack would work because of base pointer alignment.
  • The author decided that the speed gain was worth it but wanted to figure out the 1/16 problem beforehand. They noticed that the RPC GetVersion returned a global variable. By performing a write to corrupt the string in the version with the format string bug, we can leak a stack address. In particular, using a relative write on the global address to the name to point to the .bss section argv pointer, we can leak a stack address. This requires a slow 2 byte write but makes this much faster later on.
  • Once we have the arbitrary write primitive, we need something to write! The binary is compiled without PIE, meaning that we can corrupt the global variables for the binary without needing a memory leak. From the arbitrary write and the stack leak, we can trivially ROP the binary. The chain, which is made easier by the binary being statically compiled, calls mprotect to make the stack executable then jumping to shellcode written beforehand. They created a reverse shell with this.
  • The code for the ROP is interesting since it makes heavy use of the pwntools functionality instead of hardcoding addresses and sycalls. Pretty neat to see and something I'd use in the future. Overall, great post on format string exploitation.

Hacking TMNF: Part 1 - Fuzzing the game server - 966

bricked.tech    Reference →Posted 3 Years Ago
  • The author of the post was interested in binary only fuzzing via snapshots and fuzzing highly structured inputs. Given their requirements, they saw Trackmaina Nations Forever from 2008 to be a good target.
  • To fuzz something, you need to write a harness to take in the fuzzing input and process it. Since the application uses XML-RPC over TCP, this is not trivial. Sockets are slow and messy.
  • To get around this, the author takes a snapshot right before the processing of the XML-RPC message occurs. Then, they modify the memory location of the message by updating the size, the buffer and edit the session_object information to bypass auth.
  • LibAFL is an amazing for building these types of fuzzers. There is a magic qemu launcher that is used for fuzzing this, which can be used for the snapshot functionality. To generate XML messages, they use Nautilus. The author links to some good resources for getting this working.
  • To fuzz the XML input, we need to ensure it has a valid XML message. The XML-RPC protocol is well defined by Trackmania, luckily. Additionally, we can reverse engineer the application to find out more messages that can be sent.
  • The fuzzer more so fuzzes the inputs within the XML tags than the XML itself. For instance, the first rule for Nautilus includes the content <?xml version=\"1.0\"?<methodCall>{METHOD_CALL}</methodCall> with a small substitution in it for the method call ({METHOD_CALL}). All other inputs are done in a similar fashion, with only small substitutions done for the values within the XML.
  • After setting up the grammar by adding rules with Nautilus and setting up some test inputs, they fuzzed the application. Additionally, they setup a repro mode that does the same thing as the fuzzer but only for a single input. From fuzzing, they instantly found a bunch of format string bugs! More on this in part 2.
  • They patched the format string bug, which was simply in a logging function, in order to find other bugs. This was done by a simple memory write to the QEMU process. Besides the format string bug, they found a few other crashes.
  • Their favorite bug was an issue where the spectators could be forced to look at a specific player. By forcing the game into a freecam on all of the spectators, it hits an edge case that causes a crash. Pretty interesting edge case that was found! Overall, awesome post on snapshot binary fuzzing, which I didn't have much experience in.

PS5 4.xx Kernel Exploit- 965

Cryptogenic    Reference →Posted 3 Years Ago
  • The PS5 has a vulnerable version of WebKit to a use after free (UAF) bug in the IPv6 stack. The Github repo is an implementation of the exploit to gain a read/write primitive.
  • The PS5 has an interesting binary protection called eXecute Only Memory (XOM). This allows for the code to execute, but never be read out while in the kernel. This stifles ROP because we don't know the gadgets to execute. We simply don't know where we are jumping at!
  • Besides XOM, the PS5 kernel has fine grained CFI, SMAP/SMEP and the hypervisor prevents patching the kernel as well. The PS5 is a masterpiece of defense in depth protections to make the life of exploiters much harder.
  • The actual details of the exploit in the Github are not very thorough. At a high level... a UAF is triggered to overlap a ip6_rthdr object. This object can then be used get an info leak. From there, a fake pktopts option is used in order to gain an arbitrary read/write primitive. Of course, some clean up is required for this. Overall, interesting to read out the complexity of the PS5 kernel!

uClibC and uClibC-ng libpthread linuxthreads memory corruption vulnerabilities- 964

Talos    Reference →Posted 3 Years Ago
  • uClibC and uClibC-ng are both standalone replacements for glibc that are extremely lightweight. These are commonly used on embedded platforms.
  • When creating threads on the platform, the thread must create a stack. This is done with a fixed size memory address and decreases from a fixed address. Because they are using mmap with the MMAP_FIXED flag, it will overwrite all existing mappings if they are asked for.
  • By creating a large amount of threads, other mappings may be overwritten. For instance, the code for libc could be corrupted. If the mapping is RWX, this could be used to get code execution. This attack is only possible on 32-bit because of the limit of threads that can be created.
  • Overall, good bug report for items that are not normally talked about. Normally, if you're using mmap directly, you're probably doing something wrong.

How I Hacked my Car Part 3: Making Software- 963

GreenLuigi1    Reference →Posted 3 Years Ago
  • In the previous two posts, they got root access to the system by breaking the update functionality. So, now what? Let's build some software!
  • ccOS(Connected Car Operating System) is an OS developed by Nvidia and Hyundai for all recent vehicles. While reading the OS, they found several header files for doing development on the OS! The author downloaded VS code, the G++ ARM cross compiler stack and a few other things in order to start compiling. They started off with a simple C++ program to view the status of the door using the library. That's pretty neat!
  • From there, they made a slightly more complicated CLI interface to unlock and lock the doors using the known interface. To finish off the research, they built a simple GUI application with QT in order to pop a screen on the entertainment console. The only complication with this was registering the GUI app with the Helix package manager. With this, they could start up their application from the CLI to display on the screen!
  • Overall, a good blog series on reverse engineering and getting a good setup for hacking. They may wrote more posts in the future, which I'd love to see.

A Deep Dive of CVE-2022–33987 (Got allows a redirect to a UNIX socket)- 962

Chaim Sanders    Reference →Posted 3 Years Ago
  • MediaWiki, which is a PHP, claimed to have a deprecated dependency that was an HTTP web server called got. How does this effect MediaWiki? Some submodules were using this.
  • The got library added support for making requests via Unix domain sockets. This was to allow for requests to be made to a local server, similar to localhost. Unix sockets are extremely powerful so filtering should be done by the end user. This support added the unix:/ and http://unix:/ scheme. The latter scheme was borrowed from the npm request library for implementation.
  • The got library was not considering that redirects could occur to Unix sockets. By using a 30X redirect to our own server then sending it to a Unix socket, it would be possible to hit a Unix socket from the request; this is a real bad SSRF vulnerability. Filtering wouldn't work in this case, since the request would redirect anyway. This issue was present in the request framework as well.
  • How would somebody exploit this? Hitting a locally running unix socket. A common unix socket would be the Docker socket. This can be used for creating and kill containers, getting logs and much more.
  • Overall, interesting dive down the dependency rabbit hole and a trip down how hard URL are to handle in the modern web.

How I Hacked my Car Part 2: Making a Backdoor- 961

GreenLuigi1    Reference →Posted 3 Years Ago
  • Each file is encrypted individually, with the name being enc_{OriginalName}. There is a configuration file with the file name and the SHA224 hash. The hash of the configuration file is signed. Finally, everything is put into an encrypted zip file for the firmware.
  • Knowing all of the information about method for creating the image is vastly important. Since we have the encryption key and the signing key, we can create valid firmware with a backdoor in it.
  • To backdoor the device, they changed a few scripts. The device has Python on it. So, a backdoor shell was added. Additionally, if a USB drive was plugged in, it would search for a special file that would execute. With the backdoor setup, the device needs to be put into engineering mode.
  • But, the password doesn't work for the mode!? With the newest firmware update, they had came from the website, the password had changed. The hash of the pin (parts of the pin) was put into the logs. By brute forcing these individually they part of the new pin to be 02. Additionally, a hardcoded hash was in the binary and found to be 38. Putting these together is our code for engineering mode.
  • A good post on reverse engineering and setting up the process for further security research. A large amount of the time this is in posts, even if it is just as important.