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!

BatBadBut: You Can't securely execute commands on Windows- 1425

RyotaK - Flat Security    Reference →Posted 1 Year Ago
  • The vulnerability is a known issue that was originally processed over 10 years ago. However, it's such a common mistake that languages keep making the mistake again and again. When executing system commands via a subshell, it's important escape these characters. Otherwise, command injection can be used to control the system. Most languages have this feature and it works well.
  • In order to prevent command injection, the malicious inputs are commonly escaped. Additionally, the inputs can be processed with a unique argument context, preventing the meaningful bash metacharacters from doing anything on Linux and Mac. On Windows, the process is entirely different though.
  • When executing a .bat (batch) file on Windows, the OS will automatically do C:\Windows\System32\cmd.exe .\test.bat within CreateProcess. Most languages want to escape the input being used in order to prevent command injection. However is this escaping done? Using backslashes! However, unlike Linux, Windows doesn't process these as an escape - it uses ^. So, \" is insufficient.
  • This leads to shell metacharacters being able to break out of the escaping! For instance, using "&calc.exe as the input for a spawn in NodeJS will execute calc. This leads to command injection on Windows systems whenever a batch file is used and inputs can be provided to it.
  • The obvious way to fix this would be using a caret(^) instead of backslash. However, the command prompt will expand variables inline before other parsing. So, it's possible to use substring of ENV variables to add in your own quotes once again, which is bad. How do we actually fix this then?
  • As a developer, fixing this issue is super tricky because of the issue mentioned above. It involves disabling the automatic escaping then replacing a bunch of dangerous characters by hand. As a runtime maintainer, no extra info was added but was something that just needs to be fixed... weird.
  • Overall, a weird vulnerability in the interoperability of different systems. The bug has been around for a while! I enjoyed the debunking of the obvious fix in my mind as well.

Parser Bugs of the Year- 1424

LangSec    Reference →Posted 1 Year Ago
  • Parser bugs can be real bad, given the wide spread use of them. The article has a few awards: most impactful, parser differential, hardest to fix and weirdest machine.
  • For most impactful, it was the webp bug. The huffman compression was absolutely everywhere. The runner up was a H.264 file format set of bugs.
  • For hardest to fix, it was binarly post. Since they deal with low level firmware, it's non-trivial to fix. It was a memory safety issue in image parsing (of course).
  • Personally, I found the BatBadBut cooler as a parsing command injection bug. Bash and C tokenize arguments for invoked programs the same way. However, Windows bat batch do something entirely different, which most languages, including Rust and Java, didn't account for. In Windows, backslashes are NOT an escape for quotes - the carat is. So, the normal escaping didn't work.
  • The winner for best parser diff was a Gitlab parsing issue related to YAML processing in Ruby vs Golang. The runner up was a request smuggling vulnerability in NodeJS and several other servers via differences in the interpretation of carriage return within optional whitespace.
  • The winner for weirdest machine was the NSO groups exploitation of a parser bug to create their own architecture in a PDF parser, as researched by P0. Probably the craziest blog post I've ever read.
  • I appreciate the author grouping these all together! I hadn't read all of these so it was good for me to get.

Abusing URL Parsing Confusion to Exploit XXE on SharePoint Server and Cloud - 1423

Piotr Bazydlo - ZDI    Reference →Posted 1 Year Ago
  • XML eXternal Entity (XXE) injection is a vulnerability in XML parsing that allows for the adding of entities for file reads, SSRF and other issues. Most of the time, XXE bugs are fairly simple but this one was a weird URL parsing issue.
  • Microsoft.SharePoint.WebControls.BaseXmlDataSource is a class in Microsoft Sharepoint for loading data source objects on a Sharepoint page. The DataSource URL can be controlled as an arbitrary URL. While reading the code with claimed XXE protections, they tried to include a DTD and it surprisingly worked! According to the author, code that properly blocks DTD inclusion in .NET is pretty rare.
  • So, what was going on? The resolver will try to handle the entities THEN will perform a prohibit check. So, an exception ends up being thrown but NOT before the request is actually made. When doing the check for DTD inclusion within XmlSecureResolver, it does a check to URL check to prevent arbitrary domains from being used. In particular, the domain being pulled from MUST be the same as the data being requested.
  • The end goal was to get a XmlSecureResolver policy that allows for the reading of local files and allows for HTTP requests. The goal is to trick the policy writer to give us an unrestricted policy yet still be able to request data. This is a classic situation where URL parsing differences really matter.
  • After tinkering around for a few hours, they came to file://localhost\c$/sites/mysite/test.xml. Since this is a file URI, it gets ignored. Next, it looks for the ending of the file path, which is a local file system path, which we can freely write to anyway.
  • With this, the XXE bug becomes exploitable. Here are the steps:
    1. Upload the malicious XML file to sharepoint as part of a website. This requires a low privileged user to do.
    2. Next, create a page with the datasource being the malformed URL above.
    3. Step 2 will retrieve the malicious XML.
    4. The XmlSecureResolver creates a policy based upon the URL without any restrictions.
    5. The malicious XML trigger the XXE bug.
  • Even though an error is triggered on the XXE bug with a DTD exception, it is too late in the processing. The requests to retrieve arbitrary files, such as win.ini, are already done. I found the error being triggered after the processing so fun. It's a good reminder to always look for side effects on a request that are not directly returned in the response.
  • Overall, a really good write up! I enjoyed the images throughout, as it was a difficult bug to think about.

Devfile file write vulnerability in GitLab- 1422

Gitlab Security    Reference →Posted 1 Year Ago
  • devfiles are a mechanism for describes Workspaces in Kubernetes environments for Gitlab. Workspaces are isolated environments. The parent field can be used as a base for a workspace, but was banned in the devfile for security reasons.
  • At this point, the author noticed that two parsers existed: Ruby for Gitlab and Go for the Workspaces. So, if the author found a difference between the two parsers where Ruby didn't see something but workspaces did, it would be possible to smuggle in the parent field.
  • Prior to this, they had found a difference between Python and Go with the !!binary option. This didn't work but something similar did - !binary. The Go parser will decode the binary data for the key but the Ruby parser doesn't not. So, it's possible to add a parent but ONLY within the Go parser.
  • The author needed another bug to make this worthwhile. The devfile tar.gz parsing had a directory traversal issue. They had told the Go linter to ignore the opening of an arbitrary file because it was cleared. However, with relative paths, filepath.Clean does NOT actually clean the path. So, this directory traversal allows for the writing outside of the intended area.
  • They add a few more notes... First, parser differentials are everywhere and should be looked for. Second, don't trust the comments. Third, you can't find all the bugs, as they missed a go-git vulnerability while auditing this that was reported afterwards. Overall, a good writeup on an interesting bug!

ANSI Escape Injection Vulnerability in WinRAR- 1421

Siddharth Dushantha    Reference →Posted 1 Year Ago
  • WinRAR is a Windows specific compression tool. It also has a terminal version as well. ANSI is the escapes sequences used in terminals to change the color, orientation and many other things about text.
  • If the ANSI escape sequences can be included into text printed out to the terminal then it can be weaponized to change the screen. When WINRAR outputs the data to the screen, a malicious file could rewrite the entire screen by adding the escape sequences to the comment of the file.
  • Because escape sequences can be used to rewrite the entire screen (like in VIM), the author of the post was able to use the comment of a file in WinRAR to rewrite everything. In particular, change the file name output to be something that's different than the original. This could be used to hide viruses or something like that.
  • Interesting bug with awesome context. Good write up!

CVE-2024-23108: Fortinet FortiSIEM 2nd Order Command Injection Deep-Dive- 1420

Zach Hanley - Horizon AI    Reference →Posted 1 Year Ago
  • CVE-2023-34992 was for FortiSIEM command injection vulnerability. The phMonitor takes in a server_ip variable. This was being used to execute a python script via os.system that led to a command injection.
  • The vulnerability was fixed by just validating the IP address being passed in, solving the immediate issue. Within the same request as the original command injection, there is another field called mount_point. This field is saved then used in another script when testing the mount.
  • With this, we have a second order command injection that we first make a request to save the data then another request to execute the exploit from the saved data. I enjoyed this aspect of the exploit, as second order bugs are commonly forgotten about. Overall, good bug report :)

Taking Down Cosmos Chains- 1419

Jacob Gadikian    Reference →Posted 1 Year Ago
  • A while ago, Jacob reported a bug named p2p storms that ICF deemed wasn't worth fixing. If the blocks are 20mb each and the mempool is full, then the chain liveness are severely impacted. The author claims that this affects all chains and can be done cheaply with lots of large MsgUpdateClient
  • Basically, lots of data being processed will take down the chain. At the bottom of the article, they claim that the default maximum size of blocks should be lower and we shouldn't use the Sentry node architecture because of the large network propagation times.
  • Now, if we fast forward to today, the author decided to take day some public chains to prove his point. From the arguments that they had with folks on Twitter, it appears that he's doing this to force the community to fix the bug. He took down Teritori Network, Archway and Terra using this.
  • He keeps saying to increase the price of gas to make it economically unviable, faster block times and smaller blocks. According to Archway, it's a p2p networking problem rather than a block size thing; it's important to have the capability to have large. blocks for CosmWasm contract uploads. Overall, an interesting bug with a real world showcase.

The Art of Judging Bug Bounties- 1418

Trust Security    Reference →Posted 1 Year Ago
  • In bug bounties, judges are a party between the auditor and the development team who reviews and handles disputes on the findings. Trust, the author of the post, has audited thousands of findings in contests who is giving their opinion on the matter.
  • The judges are like referees in baseball: both teams hate them. Sponsors want to downplay bugs for both money and publicity. Competitors want to inflate their findings in order to profit more. Additionally, none of these people face any consequences for pushing their submissions in one direction or the other.
  • What's the role of the judge? First, they need to go off of the rules designated by the platform. Second, apply their understanding of the bug to get the true impact of the issue to the project. Finally, ignore anything besides the content, including identity of the person, time constraints and other things.
  • When reviewing a finding, there are many things to consider. First, the technical validity. Can the issue actually happen? Hopefully there is a PoC to demonstrate this. Next, the proof is on the reporter and not the judge. If a bug is found, then the line of code or design needs to be explicitly pointed out.
  • Likelihood and impact are the two often considered things with a matrix that generates the total severity from this. Some of these are loss of funds, theft of yield and other things. However, the two layered matrix is not always correct. For instance, low is uncapped - how low is too low for likelihood? There's always debate on this matrix.
  • Within the period of a contest there is an escalation period where finding severity can be challenged. Since there is almost no impact for a user to NOT escalate findings, there is a likelihood of a high ratio. So, they need to filter out the noise and evaluate legit reasons that were provided for changes.
  • When judging, similar to being an umpire, you just always need to make the right call. Don't hesitate to fix mistakes or make an unpopular decision.
  • An interesting view into judging! It's not for the faint of heart but is important to the community. In the only C4 contest I did, I had a bug be considered out of scope when I felt it was in but couldn't argue much for it because it was my first contest. Any time I report a bug, it's immediately downgraded as well, which is a bummer. So, I appreciate the role of the judge to help out :)

iframe and window.open magic - 1417

Huli    Reference →Posted 1 Year Ago
  • An iFrame tag is used to bring in other web pages into your own. Some pages restrict this (to prevent clickjackin and phishing, among other things) but can be awesome for developers. The src attribute is used for the location of the page. Placing a javascript: URI can lead to XSS here and in forms and anchor tags.
  • Interestingly, the data used in the URI can be HTML encoded and will still render as we want. When using data: URIs here the code can be executed but it's executed on the null origin. To prevent attacks on the URLs, a developer can restrict the domain to only contain http/s: in it. Still, redirects can be made from the page.
  • Cross origin pages normally cannot access the page. However, there is some data still accessible. The only callable functions are focus, blur and postMessage. There are also readable properties like frames, top, opener, parent and others. Additionally, the location.href property is writable.
  • iFrame has a srcdoc attribute as well. It's similar to the src but the iFrame will take in data for the doc and share the same origin as the original page. These can be HTML encoded as much as you want as well.
  • Iframes have a sandbox property which is off by default. If just "sandbox" is used then all protections are on but can also have explicit protections turned on. There are several flags that change how the upper layer can be redirected. There are some function related ones, like allow-downloads.
  • allow-popups allows window.open() to be called in order to open new pages, but this page is still sandboxed. Adding allow-modals allows for the escaping of the sandbox on calls with a null origin. allow-popups-to-escape-sandbox will remove the sandbox on popped windows.
  • allow-same-origin will set the origin to non-null it will keep the original origin of the call instead of a unique origin with separate cookies. allow-scripts allows JavaScript to be executed within the frame. There is also a CSP sandbox attribute for the iFrame as well.
  • window.open has three parameters. URL is the obvious one. The second one is the name of the window. If there already is a window with the same name as provided then it will provide a reference to the other one named this way.
  • There are six ways to generate named windows. Anchors, forms, iframes, objects and embed tags, as well as the window.open.
  • There are some other details on detecting page loading and other things. Overall, just a great references for iframe protections and windows in the browser.

Parallel Code Security: The Challenge of Concurrency- 1416

Stefan Schiller - Sonar Source    Reference →Posted 1 Year Ago
  • Apache Guacamole is a remote Desktop gateway used for accessing hosts and isolated applications from the webs browser. The application itself contains a client facing server written in Java and a local server that the client server interacts with written in C.
  • The server makes heavy use of parallelism to make it fast. There are 8+ threads that do various things, from handling a connection to communications back to the client and much more. Since there were so many different threads running, they were curious about the security of this. In general, mutexes were used and threads were loosely coupled, making it mostly secure. From a developers perspective, reasoning about multithreaded code is very hard to do, meaning that there are likely bugs in this area.
  • Staring at the audio processing seems to be a fruitful area because there were three threads involved with it. One thread (the user thread) creates two buffers: one for the user and one for the socket connection, with the user structure having a pointer to the socket. After this, a third thread, called the rdp_client_thread, is created for a RDP connection. This structure holds a pointer to the user structure, creating a pointer chain.
  • These different objects can be closed or destroyed at any point. By disconnecting from a session (after using the microphone), the user_thread is torn down - this frees the socket and user structures. However, the rdp_client_thread still has a pointer to this object! So, if a message is sent to close the audio channel, this is accessing a freed pointer! This creates a classic use after free vulnerability.
  • To exploit this, the author looked into overlaying this object over the top of something else. However, the thread was closed quickly afterwards, making this approach not very helpful. So, we'll have to dive into threads and glibc malloc clean up to make this work! There is a function pointer at slot 8 in the user object to another poitner. So, if we could edit this and call it from the other thread, it would be game over.
  • By abusing some functionality within glibc's freeing process, it was possible to stick the freed user chunk into the unsorted bin, which references some data controlled by the attacker. Although we don't have a memory leak, the pointer to a function pointer now goes from our freed data, to free data that we control (since it's never cleaned up in malloc). To get control over the execution, an attacker can call strdup() with a size of 0x90. But, this is limited to zero nullbytes, making it infeasible. So, now what?
  • malloc is limited to a small amount of arenas or heaps. By sharing connections on Apache Guacamole, we can create lots of arenas, until we hit the limit. This means that we can use the UAF on a different thread that is much more useful! The author found that getting the input_thread allocated with arena4 was the best thing for controlling the data within for our UAF.
  • With control over RIP on the function pointer, we need to setup a ROP chain. The lock_handler() function pointer is called on an argument provided by itself. Since the data after the function pointer gets corrupted, they use a pivot gadget before proceeding. Once done, they called system with their provided parameter to pop a shell. Pretty neat!
  • Being a big fan boy of malloc heap exploitation, I really enjoyed this article! The knowledge required to exploit this was super high, which was cool to see. I found the simplicity of the UAF interesting as well - just a simple dangling pointer with no race conditions. Amazing post! :)