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!

[CVE-2016-1824] Apple IOHIDFamily kernel race condition as root- 1577

Macro Grassi    Reference →Posted 1 Year Ago
  • XNU kernel and some IOKIT modules have been plagued by race condition issues. Many of these issues have been discussed, including one from Ian Beer. On the surface, these drivers either lack a locking mechanism altogether or use the wrong locks for the type. Because of this concurrent access of data types makes it easy to cause memory corruption.
  • The code in question callsrelease() on the kernel queue and then sets it to NULL. There is no lock provided on this code though. If another thread can access the kernel queue after it's been released but before it's set to NULL, then bad things can happen.
  • What exactly can happen? In the post by Ian Beer that was previously linked, he was able to overwrite a VTable pointer with this same type of bug.
  • The release() and NULL are very close to each other (literally a line apart). The PoC has a loop that tries to hit this. I'm curious how long this would take? Seems like a tough window to hit.
  • The author has a good takeaway: "Sometimes vendors just fix the immediate problem and bug, and don’t investigate carefully about the root cause and search for additional bugs that share the same pattern." If you see an interesting bug, there may be other variants of the same bug waiting to be discovered.

Remotely pwning iOS via WiFi and escaping the Sandbox (OLD UNPUBLISHED 2016 BLOGPOST) - 1576

Macro Grassi    Reference →Posted 1 Year Ago
  • When you log in to a WiFi network, you are automatically native to a captive portal. The browser that opens for the captive portal is not normal Safari—it's Websheet. Naturally, the author had some questions about the control that a user would have over the content and the sandboxing of the application.
  • We can return a malicious page using a malicious WiFi dongle and Linux machine. This page will have a Webkit exploit in it, which is out of the scope of this post. Since this is automatically rendered when connecting, it's a zero-click attack surface.
  • Unlike Safari, WebSheet doesn't use a split process model between the sandbox renderer process. So, if you find a web bug, you have code execution in the context of WebSheet. Once we're in this process, the sandbox is restrictive but the next goal is to see what we can do with it.
  • The entitlement com.apple.managedconfiguration.profiled-access can be used to install a configuration profile, which includes a RootCA and proxy settings. This can also be used to install an additional fake app in the background, silently backdooring the device forever.
  • The next interesting permission is com.apple.springboard.opensensitiveurl. This can be used to open sensitive URL entitlements. For instance, opening Safari. Using this issue, we can force a URL to be open once again and deliver the same WebKit exploit as before.
  • I personally love this post. Most of the time, we say, "How can we get in?" or require a full chain of bugs. This post assumes we have a WebKit bug the extrapolates what we can do with it. Defense-in-depth measures only matter if we properly scrutinize them. The entitlements on this application feel like too much and it's interesting to see how they can be abused.

Subverting Apple Graphics: Practical Approaches to Remotely Gaining Root- 1575

Marco Grassi    Reference →Posted 1 Year Ago
  • Sometimes, the vulnerability is not the issue itself - it's finding a fruitful attack surface. In this paper, the authors discuss the overlooked OS X attack surface of the userland and kernel graphics components. The reason these were likely overlooked was because they are not listed in the sandbox profile. The WindowServer also has very high privileges on the OS.
  • CVE-2014-1314, not found by the authors, was a funny design flaw. When creating a CoreGraphics session, it will send a request to start a process under the user's context. However, user's can specify an arbitrary script to run upon login. So, this creates a process that is outside of the sandboxing. Neat!
  • The first interesting bug they discuss is a double free. This is triggered when setting an invalid ForceConfig for touches. The time window for the two frees is very small. Luckily, triggering the bug without winning the race doesn't crash, allowing for a brute-force attempt on this. The CFPropertyListCreateWithData API takes in Unicode strings, which was a good target for overwriting the memory we wanted. An additional win is that the randomization on large blocks of memory is very bad.
  • The next target is the IOAccelSurface interface used by Apple's Graphics Driver. It represents an area of a rectangle that will be rendered by the GPU. It appears to have been designed for WindowsServer to use but normal processes can also call it. Hence, it's likely a fairly software target. The article discusses the internal workings of this driver, which required a lot of reverse engineering to do.
  • When doing some rectangle scaling, there is a lack of input validation for sane values. The incoming surfaces height is expected to be less than 0x4000. By providing a value larger than this, the condition of y 16705, x 321, height -1, len -1 is possible to hit. Before bailing out, a single out of bounds write will occur.
  • Using linear out-of-bounds write ahead of the current chunk, we need to corrupt something useful. If an IG Vector can be placed ahead of this chunk, we can create a fake IG Vector with pointers to sensitive locations. Also, we control the values being written in these locations, giving us an arbitrary write-what-where primitive. Since floats have a limited range, this does limit the values we can write.
  • In effect, this gives the attacker a relative pointer corruption. Although we can't overwrite the whole thing, we can overwrite parts of pointers. Additionally, these values are good for corrupting a structure's size. In this case, the authors used the OOB write to corrupt a IOUserClient objects pointer. The goal was to corrupt this to point to data that the attacker controls on the heap. Getting this object in the proper spot via feng shui is discussed as well, and it's worth a read!
  • The OOB write is used to get both an infoleak via reading VTable pointers. The trick was to change the offset to be read out to read the pointer byte by byte. Within the same object is a VTable pointer that can also be overwritten to achieve RIP control by pointing it to a spot on the heap that we control.
  • Even though the paper is 8 years old, there is still so much to learn. Good paper!

Millions of Accounts Vulnerable due to Google’s OAuth Flaw- 1574

Dylan Ayrey    Reference →Posted 1 Year Ago
  • OAuth is a common way that websites do authentication. Google OAuth is a identity provider that websites can use to not handle usernames, passwords and such.
  • When you click the Sign in with Google button, Google sends the application a set of cryptographically information about the user in a JWT. Of these fields, is the hd (hosted domain) and email. The application would verify both of these claims to be correct before logging in.
  • Here's an interesting question: what happens when the domain is owned by somebody different? Apparently, there is no verification on then. The sub field could be used for this but it's inherently unreliable on Google OAuth for some reason.
  • By purchasing the domain of an old startup, it's possible to login to these other accounts. You can't see old emails in Google workspace but you can access accounts from previous employees.
  • Initially, Google decided to not fix the issue. They categorized this as an abuse issue. After the talk got accepted to ShmooCon, they decided to pay $1,337 for the bug. They rated this as low likelihood and high impact, which I think is a fair assessment. They claimed they are working on a fix but nothing has been shared yet.
  • The author brings up a good point about password resets. If an attacker controls the email then they could reset the password on an account as well. Unless the only 2FA is on the email, this will not work because of things like Google Authenicator and SMS 2FA.
  • To me, they try to hype up the numbers a little much. They claim millions of accounts but are making assumptions about A) the amount of startups that use Google workspaces, B) each has 10 employee, and C) each has 10 accounts. Although it's technically correct, it feels overhyped. Alongside this, who cares about data of old startups? Not many people. Regardless, it was a cool bug and I appreciated the write up.

Solana Reading List- 1573

mertimus    Reference →Posted 1 Year Ago
  • A list of various Solana articles. Range from Solana internals, MEV, validator setup and more. Just a good resource to have if you want to read about Solana.

TMI — Too Much Information. The less you reveal the better!- 1572

aleksamajkic    Reference →Posted 1 Year Ago
  • Resource enumeration is the process of extracting the existence of a resource, especially usernames, from an application. By itself, it's not a big deal. But, it is often required to further exploit systems. As a result, many people do not care about the vulnerability. This article is going to touch on this bug class.
  • Sometimes, the data is obvious. For instance, @dooflin5 on Twitter is my handle, and it can be seen easily. In other cases, it's more subtle. A different error message being returned on login if the email exists in the system or not can be enough to disclose this. Besides information disclosure, trying a lot of logins can also be used as a DoS vector.
  • The author found this vulnerability on some websites. The company said it's a known design feature. So, what's wrong? It's a user experience thing. If the user can't remember their username, it becomes hella annoying to use your website. Generally speaking, the less information you give to the attacker, the more secure the system is going to be, but the harder it is for the end sure to work.
  • In practice, things like password reset and logins should have good rate limiting and captchas anyway. This prevents the automation of this exploit but the core issue can be used to try to guess small amounts of usernames by hand. Good read on assessing the design tradeoffs with it.

Solana MEV Report- 1571

Helius    Reference →Posted 1 Year Ago
  • Maximal Extractable Value (MEV) is the value that can be extracted by manipulating the transaction sequencing. By adding, removing and/or reordering transactions within a block, it's possible to profit from it. This article is a perspective on Solana MEV over the last 4 years.
  • The first big change in the Solana MEV space was the introduction of the JITO-Solana client. By allowing block-searchers to choose what transactions go into a block in a democratic way with a bidding process, the validators and searchers are able to profit from it. The JITO-Solana client makes up 92% of clients now. In March of 2024, Jito decided to shut this down because it was hurting average users.
  • Even though JITO is now gone, there are other similar products to it. Much of Solana sandwiching attacks originate from a private mempool called DeezNode. In May of 2024, the scheduler algorithm was made more stable, which prevented leader spamming attacks too.
  • What type of MEV is profitable? The classic one is arbitrage. You can buy something at $1 and then sell it for $3; you make $2. By changing the cost of things with sandwiching, you can arbitrage users to make large profits. Another form of MEV is performing liquidations on lending protocols.
  • An insight they show is the amount of reverted transactions on Solana. Since a single user can only hit a MEV opportunity, all others will fail. This bot spam counted for 75% of all non-vote transactions in the network, leading to major issues in throughput. The new scheduler has majorly improved on this problem, though.
  • Jito attempts to keep track of MEV in the Solana network through their mempool and elsewhere. According to the report, 50% of sandwich attacks come from a program owned by DeezNode. On average, they make 51K transactions in a single day at 2200 SOL per day. Jito shutting down their mempool was nice. However, unless there's a built in way to stop this, some actor will decide to do this.
  • How do we stop MEV then? A scary way is validator whitelists. Jupiter, a retail trading platform, introduced dynamic slippage to optimize settings in real-time. Another one that is common by AMM's is to route transactions to only go through the Jito block engine without sandwiching.
  • RFQ (request for quotation) is an off-chain pricing mechanism where market makers bit for prices, with only the final quote being used on chain. JupiterZ and Kamino swap do similar things but follow this underlying principle. Along the same lines are Sandwich-resistant AMMs. No swaps are executed at a price more favorable than the pool's price at the start of a slow window. Because of the long periods of time that prices stay, sandwiching is impossible.
  • Similar to SR AMMs is Conditional Liquidity, which depends on a new user called "Segmenters" to evaluate the incoming toxicity of the order flow. By adjusting the spreads based on this, we can prevent the profitability of the MEV folks. The spread is paid back as compensation for the Segmenters role. Paladin-Solana aims to be a trusted priority port that can be used but punishes folks who MEV on it.
  • Overall, a good article that explains the wild world of MEV in the Solana ecosystem. Maybe one day we'll get rid of it.

uncontained: Uncovering Container Confusion in the Linux Kernel- 1570

Jakob Koschel - VU Research    Reference →Posted 1 Year Ago
  • Type confusions are a bug class that operates in both memory safe and memory unsafe languages. In C, type confusions typically lead to bad memory corruption bugs.
  • The main part of this paper that I enjoyed was around C class and type hierarchies. C doesn't technically have type hierarchies but it's possible to create a similar effect using structure embedding. For instance, you can have a type and then a child field at the end of that type. To go between the parent and child parts of the object you can just do some pointer math.
  • The Linux kernel uses the container_of macro to do this a lot. According to the author, this technically violates the C language standard and is always an unsafe cast. The goal was to find cases where the casting into the container (child) type is incorrect, leading to a type confusion bug they call container confusion.
  • In LLVM, they created a custom compiler pass to spot uses of container_of in the source code to create a type system. This tracks all casts up and down. From there, they built a custom sanitizer called uncontained in order to detect casts up then back down to the wrong type.
  • An interesting design decision was checking at the time of use vs. the time of the incorrect downcast. They found several scenarios where the downcast was safe through only accessing the parent field on the downcast.
  • In the Linux kernel, they found 37 cases of container confusion. Of these, 16 were false positives, 11 were unique bugs and 10 of them were anti-patterns of checking the container confusion later in the small section of code they looked at. Besides simply downcasting to a static container, they found a few other types of bugs:
    • Empty List Confusion: In cases of list being used but empty, both the next and prev fields will point to the object itself.
    • Mismatch on Data Structure Operators: Different locations in good may treat a pointer as a different type depending on the needs. Of course, offsets must be correct in this case.
    • Past-the-end Iterator: Break-like logic is often used by searching for an element in a data structure until the end. It's possible to use the iterator without checking for its validity.
    • Containers with Contracts: An object may come with additional metadata that program semantics use to control what operations can be done on it, such as the sysfs kernel subsystem. If these invariants are not kept, it leads to a mis-use of the pointer.
  • The sanitizier is not meant to have a 100% positive rate. Instead, it's meant to point out potential locations and types of the bug. To me, this is completely reasonable as long as the false positive rate isn't too high. They added all 5 locations to find a total of 80 bugs, 179 anti-patterns and 107 false positives. Most of the false positives came from the first pattern that had explicit tag type checks within the code. Overall, a real bug 30% of the time is pretty amazing!
  • To me, this is absolutely amazing work. Taking a known bug class in the Linux kernel (and some other code) and writing a fairly accurate static analysis tool is awesome. 80+ in the Linux kernel at a time is unheard of in modern days.

Dependabot Confusion: Gaining Access to Private GitHub Repositories using Dependabot- 1569

Giraffe Security    Reference →Posted 1 Year Ago
  • Dependabot is a Github bot that automatically updates out-of-date dependencies by making PRs. It's a super useful feature for maintaining up-to-date dependencies.
  • In NPM packages, most of these only use a version. However, it's also possible to use a github.com link with a branch name. This is commonly used for private packages as opposed to setting up an internal NPM registry.
  • Dependabot will attempt to update all dependencies that it knows about in the public repo to the most recent version. To the authors surprise, they did not have any special cases for github repos!
  • So, if you registered the name of a package publicly, then dependabot would attempt to replace the private version of it. In order to do this, you would need to guess the name of a private-internal repo. Sometimes, this information can be leaked though.
  • To fix this, dependabot removed the git dependency to NPM public registry mapping that it was trying to do. Clearly, there was an issue with this. According to the author, Bundle and NPM were both vulnerable to this. Obviously, this leads to an RCE if the dependency is added.
  • Overall, a good bug in some important code! Although many of the dependabot PRs must be approved, it's easy to overlook this. Additionally, some repos use the auto-merge workflow for dependabot, making this easier to exploit.

From Arbitrary File Write to RCE in Restricted Rails apps- 1568

Conviso    Reference →Posted 1 Year Ago
  • The premise of the post is having an arbitrary file write in Ruby on Rails. The twist was that the Dockerfile had the application run as a non-root user with only some directories being owned by the executing user. The goal was to get an RCE in this restricted environment.
  • Given the situation, the natural thing to do is to recreate the environment yourself to see what's possible. One of the directories that could be written to was /tmp. Ruby has a framework called Bootsnap that allows for loading Ruby/Rails Apps faster via caching. Much of the configuration and cache for Bootsnap is stored within /tmp/cache/bootsnap.
  • Upon reviewing the contents, they noticed that load-path-cache contained gem file paths in to the MessagePack format. Additionally, comiple-cache-* contained compiled Ruby, JSON and YAML. From there, they decided to review the source code of Bootsnap to get an idea of what made sense to corrupt.
  • The Bootsnap startup went as follows:
    1. Bootsnap is loaded from config/boot.rb.
    2. Load path caching. For every require, Bootsnap checks the cache first.
    3. Compile the cache. Bootsnap caches the compiled Ruby code from the previous steps and stores them in a directory containing a hash of the file.
  • The object of this attack was to overwrite one of the cached compiled Ruby binaries then trigger an application restart. The bulk of the cache file contains information about the version and where it should be loaded this way. Nartually, this can be spoofed and set to an arbitrary value using the originally vulnerable. So, RCE is achieved!
  • How do we restart the server though to load our corrupted cache file? The Puma server will automatically restart if anything is written to /tmp/restart.txt. The arbitrary file write can be used to write to this file a second time to trigger the RCE bug.
  • I really enjoyed this blog post! Taking a library and explaining how to abuse its quirks was an awesome use of time. I bet many people will use this in the future for their endeavors.