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!

Two Bytes is Plenty: FortiGate RCE with CVE-2024-21762- 1373

AssetNotePosted 2 Years Ago
  • FortiGate is an SSL VPN. Recently, they described a vulnerability in their firmware that could lead to RCE. So, the authors of this post diffed the two versions, found the bug and exploited it.
  • First, they obtained the firmware from somewhere (likely online) between the newest and a previous version of the software. Once they had decompiled the code, they looked for changes in different locations. One of them that caught their eye was an HTTP parsing change.
  • In particular, some changes to the amount of chunks that were allowed on transfer-encoding and the size of these chunks. So, with this, they had a potential vulnerability. After some effort with playing with these values, they got a crash. What was the crash about? The value 0x0a0d could be written to an arbitrary offset on the stack.
  • The debugging environment was interesting to me. The standard shell was very restricted and there were various protections in place to prevent changes. After reviewing the /bin/init binary, they found a signature check being performed but assumed more checks were in it. So, they patched the function do_halt() to not exit.
  • For the kernel checks, they modified the kernel build to allow for debugging with GDB. In GDB, they found the check, wrote a script to setup a breakpoint then specified a proper return value. From there, they copied a bunch of binaries to make their life easier.
  • The primitive was only a two byte write to an arbitrary address on the stack with the bytes 0xXXXXX0a0d. With this return addresses, saved base points and locals did not seem like get paths to hit. So, they decided to target a heap address that was on the stack that contained function pointers.
  • The binary didn't have PIE setup. So, they used this static address alongside heap spraying to reference the system function. Eventually, they got this working with a payload to run one of the limited commands in the shell. They eventually came up with a more complicated ROP chain to get a shell though.
  • Overall, an interesting post! Taking a seemingly difficult primitive to code execution is pretty nice!