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!

Vuln Research is NOT Cooked but is Continuously Reborn Raw- 1948

tensecorrection    Reference →Posted 16 Hours Ago
  • There have been many posts claiming that vulnerability research is over because of LLMs. The main post they reference is true if you use an economically interesting but technically uninteresting definition of VR. VR is exploring an infinitely large space of weird machines and is the perfect example of a 0 or 1 task.
  • For soft targets, it's all about spreadsheets and vulnerability tracking. Taking bug class X and chaining it with other bugs to produce an impactful vulnerability. The authors claim: this isn't the meat of VR. On hard targets, this looks much, much different.
  • A vulnerability will be discovered. What's actually hard is everything that comes after it. Cheap to maintain, the exploit works on all versions, doesn't crash or fail in debuggable ways, and contains a remote attack surface... this is what makes it hard.
  • The article is a little hard to parse, with references to things that I don't know much about. Regardless, the perspective that VR is dead is not true to them. There's still lots of bugs to be found. Some will be by humans and others by AI.

Vulnerability Research Is Cooked- 1947

SockPuppet    Reference →Posted 16 Hours Ago
  • The author has been around the vulnerability research scene since the beginning. In the beginning, it was fun and motivating; they trafficked hidden knowledge, trying to understand obscure things. Within a decade, the mood shifted. Exploitation techniques like C++ vtables were common discussion points. The in-memory layouts of fonts became widely discussed because they are exploited in memory corruption attacks.
  • They make two claims. First, vulnerabilities hide in non-obvious areas that don't have anything to do with security. The entry point for hackers is where they have control of the data and where the code is bad. Second, the cost of being an elite security researcher is high, making it very difficult for many people to be good at it. It requires attention from elite people
  • Because of these two claims, they say that LLMs are perfect for exploitation research. Vulnerabilities are found by pattern-matching bug classes, which the LLM was a complete library of. It has great constraint-solving capabilities, like reachability and exploitability concerns. LLMs can write code and test exploitation as well, creating a great feedback loop.
  • Nick Carlini works on Anthropic's Frontier Red Team. They claimed to have generated 500 high-severity vulnerabilities with a super-simple set of operations. For each source file in the repo, Claude was asked to find an exploitable vulnerability in that project. With a lot of vulnerabilities, they would give Claude the reports and tell Claude to triage them. Accordingly, it had almost a 100% success rate. This process is simple, very focused on a specific file, and gets deep coverage.
  • The simple approach is weird to me. I would think that human intuition and guidance would be good for the LLM. The reality is much different: just let the LLM cook. Richard Sutton's bitter lesson realized that the important thing is data and computation. Everything else doesn't matter.
  • So, what's the future hold then? The claim is that vulnerabilities will come in large waves. The cost is apparently going down to do this. The author is worried that legislators will try to fix the issue by preventing LLMs from conducting security research.
  • They finally claim that there's room for human vulnerability research but only at the highest end. Not everything is documented, and humans come up with new tricks all the time. LLMs are great at pattern-matching and pulling concepts together across the realm, but NOT creating new ones. Still, this is a small subset of people. The post is very dystopian but potentially true. I think LLMs tend to find the same bugs, but I'm doubtful it's finding ALL of the bugs.

TheIdols NFT, `_beforeTokenTransfer` and 340k gone- 1946

Quill Audits    Reference →Posted 17 Hours Ago
  • Idol was a staking-to-rewards protocol that used NFTs for this. There would be some amount in stETH. As a reward, it would be given to the NFT holders. This uses standard math to calculate the user's balance since the last claim and determine how much value they are owed.
  • In transfer() the to and from on the call need to have their rewards updated. When doing this, if the user had a value of 0, it would reset the rewards index to 0, as if they had never claimed anything. So, what happens if you transfer to yourself? Infinite money...
  • The reset performed on the to of the transfer causes issues with the math checkpointing system for the last claim. By resetting it to 0 and then triggering it again, the rewards are calculated over a longer period than they should be. This only works for a self-transfer because a regular transfer sets the reward timestamp to the current time.
  • There's actually a second bug in this! There is a check to ensure that only specific white-listed contracts can make the call. Since both the to and from addresses were the same, this was a valid transfer.
  • The attack is simple... get an NFT and transfer it to the same contract address over and over again. The attacker did this 14 times from 14 different contracts for a total of 87 calls. All in all, they stole about $340K worth of ETH.
  • Overall, a pretty classic bug. The article from Pyro asks a simple question: what happens when you do a transfer to yourself?

How to Find vulnerabilitys So Creative It Feels Illegal - 1945

Patrickbatman    Reference →Posted 17 Hours Ago
  • The point behind this article is focused: start thinking and stop performing a ritual. If you have a methodology that you got from someone else, it's probably not going to work for you. It was built for their brain, their targets, their pattern recognition, their experience and their interests. Real good bugs come from understanding an application and not some checklist.
  • The next big claim is about focus. Sitting in deep focus is super hard. It's uncomfortable and boring. But, these are where good bugs are found at! Sit in the uncomfortably instead of scrolling Twitter, or reading some new article. You have to slow your brain down and stop seeking the next dopamine hit.
  • They give some tips to fix both of these issues. Days 1-2 are the reset. Cap your hunting at 4 hours, pick your biggest distraction to kill it, and go on a walk without your phone. All of these rest the brain to want to focus on the harder challenges in the bug bounty realm.
  • For days 3-4, the goal is more focus. Pick a single writeup and read it in detail; really understanding the whats and the whys of it. Go on walks with no music or anything. Just notice what's around you and think. For days 5-6, pick a single target and ask yourself a lot of comprehension questions about how the application works. Rebuild the curiosity for yourself. Finally, test a single feature in the application and go crazy on it.
  • A good reminder that our brain is the tool and the goal is to find bugs.

Breaking Blockchain Consensus with a JSONPath Wildcard- 1944

gjaldon    Reference →Posted 17 Hours Ago
  • SEDA is a decentralized oracle network built with the Cosmos SDK. First, A user submits a data request, and then do a commit/reveal scheme. The SEDA chain tally modules process the reveals and apply any configured consensus filter.
  • A Data Request can include a consensus filter that uses the JSONPATH extension. If you have a JSON object like {"a" : "b"} the filter would be $.a. This allows for complex filter expressions with comparison operators and wildcards, and helps define what data is actually returned.
  • JSONPath was standardized in RFC 9535. When using wildcards, it states the following: "The order in which the children of an object appear in the resultant nodelist is not stipulated, since JSON objects are unordered." There IS no deterministic ordering. In blockchain land, this means consensus failures because the serialized values from different nodes appear different to each other.
  • Wait, shouldn't the algorithm be deterministic if it's all in the same language? I looked into this once for Golang. In many cases, such as dictionary iteration, Golang intentionally introduces randomness to operations so that users don't rely on undefined ordering semantics. I imagine this is the case here as well.
  • I imagine the JSONPath library has wildcard functionality built in, and this wasn't written from scratch. So, this feature of the filtering engine was never intentionally put in, but was a side effect of the underlying library. At least, these are my assumptions. Overall, a great blog post on the discovery and exploitation of a consensus failure.

CVE-2021-45467: CWP CentOS Web Panel - preauth RCE- 1943

pwn.ai    Reference →Posted 2 Days Ago
  • While reviewing CentOS Web Panel (CWP), they noticed an interesting protection for local file inclusion.
    PHP
    function GETSecurity($variable)
    {
      if (stristr($variable, ".." ) {
         exit("hacking attempt");
      }
    }
    
  • Why was this interesting to them? stristr() is a substring function that isn't case sensitive. They had a few ideas for circumventing this check... First, have it treat other characters as dots but this yielded nothing.
  • Second, was finding characters that the C PHP processor would treat as dots when lower-cased. They reviewed the underlying C code to see that any inputs was converted to lowercase, and then the comparison was performed. The main idea was that the check and the use were slightly different but this didn't yield any results.
  • The final idea was tricking CWP into thinking that dots were NOT being used at all. After some fuzzing, they came to the payload /.%00./. The string comparison saw one thing but the routing saw another. stristr effectively ignores null bytes but they were not sure why this happened.
  • This vulnerability gave them a local file inclusion vulnerability. They reported this to ZDI and patched. Overall, a good bug! I appreciated the thought process of why they targeted this specific section of code, including the failures.

ImageMagick: From Arbitrary File Read to File Write In Every Policy (ZeroDay)- 1942

pwn.ai    Reference →Posted 2 Days Ago
  • The author of this post is the creator of an autopwn bot. While on a customer engagement with a small scope that was perfectly patched, it decided to tackle a dependency that is used by millions of websites: imagemagick. After five days of searching, it had a zero-day RCE bug in the default configuration of this library. This is the story of the vulnerabilities and the disclosure process.
  • On the first day, it learned that extension-based filtering doesn't work because it mostly cares about magic bytes. From this, it was determined that it could process SVGs at will, and the SVG parser was reviewed. Fairly quickly, it identified a file-read vulnerability when PostScript was enabled, but exploiting it required a very generous policy. The default policy blocks PS but not EPSI, allowing for an arbitrary file read. There are two issues here: the ability to read files at all and a bad deny-list.
  • After another day, it learned that by shifting the magic bytes, adding a \n could be used to defeat the PostScript detection. So, using GhostScript, you could write arbitrary files to the server just by reading a file. After finding a clear RCE vulnerability via a file-write, the development team pushed back, saying that real users should have better policies in place, where the default configuration still had the issue.
  • After this point, they moved their client to a very restrictive set of image policies. Upon doing this, the AI bot realized that the PS module was blocked but NOT the PDF module. By using the PDF path, which is fine in production according to the maintainers, it achieves RCE again. Even after this, they found that using the magic bytes C5 D0 D3 C6 overrode the extension-based format selection, allowing for even jpgs to be processed.
  • The most secure policy blocked all usage of delegates. This should theoretically catch all external process invocations and reject them. Unfortunately, this protection was busted in the case of GhostScript. When GhostScript is compiled into ImageMagick as a library, it runs in-process via gsapi_init_with_args(). So, the policy check never fires.
  • WordPress has no ImageMagick policy to begin with, making it vulnerable in many situations. It all depends on the website and the user's capabilities. In the end, the module was silently fixed without a CVE being assigned, and the fix wasn't backported to older versions. Practically, this means that a server with defaults of the library is vulnerable to some pretty nasty things. Only the core file read and file write issues were fixed; the PDF bypass and gslib delegate execution issue were never fixed.
  • The maintainers' fixation on secure policies appears to be a security boundary that is different between real-world usage and maintainer expectations. As usual, if there are no good defaults, then the protection is effectively null. Overall, a great post on ImageMagick's security and the use of LLMs to find bugs.

Tricking the Polygon bridge into withdrawals by forging transaction proofs- 1941

Hexens    Reference →Posted 2 Days Ago
  • Polygon is an EVM-L2 solution. It has multiple bridges to go to and from Polygon/Ethereum. One of these is the Plasma bridge, which uses transaction receipts to prove incoming/outgoing transaction information for token transfers. The user just needs to provide a proof of a withdraw event of the token on Polygon to obtain it. This event contains the amount and receiver of the transfer inside of it.
  • The proving process is done on a Merkle Patricia State Trie. This is a state trie that encodes data into it, making it searchable, that is used all over the EVM ecosystem. With a valid root hash and the existence proof within the state trie, it's possible to prove that the event happened. This requires that a checkpoint hash of the given block is proven.
  • The first vulnerability is an issue within the MerklePatriciaProof verification library. When providing data against an MPT root hash, it requires the trie's nodes and path. The recipient is an RLP-encoded transaction index. These tries have prefixes that define length extension information. The library enabled early stopping at an extension node by simply providing a shorter proof path. This creates a parsing differential between reality and what the proof sees. By doing this, the 7th parameter in the exit payload is completely controllable!
  • The RLPReader library had a memory corruption issue during parsing. The code has a simple memory pointer and loops over each element. For each element, it adds the length value and copies the data to get the entry. The library blindly trusts the length of a value to be valid, not considering it could go into other memory of the program. As a result, the parser can read beyond the expected bounds into memory.
  • Now we have two issues: an out of bounds read and a parser differential. Without the OOB read, the parser differential is unexploitable because the hash data requires as the value is random and likely cannot be parsed into a valid transaction. To get this to work, the extension node hash must be parsable as a valid receipt, which has a lot of requirements. They wrote a script to search the whole chain history for extension node hashes that would work in this case and did find a few.
  • The parser differential is completely separate from the exploitability of this; we just need a single valid tx for this exploit to work. Once we have the differential, we can use the out of bounds read to perform the exploit. To exploit this, we need Solidity to read from dirty memory (data that hasn't been cleaned up yet) with data that we control. Because of the order of operations, only the ERC20PredicateBurnOnly code was affected; it has a CALL opcode before the parsing that writes data to memory that is controllable. By having the parser read this data, we can control the logs that are processed.
  • This exploit is super clever! It required a small parsing discrepancy to begin with. After this issue occurred, it exploited a bug in the RLPReader library. The developers likely made the reasonable assumption that all data processed by the library would already have been validated. Although this is true, it doesn't account for a bug in the validation. Once you get past the initial validation, the code typically becomes much softer.

Advanced Client Side Hacking- 1940

XSS Doctor & Jason Haddix    Reference →Posted 2 Days Ago
  • Client side security is a little bit opaque to me. This is a course that focuses on practical exploitation of client-side vulnerabilities, and how to chain these types of bugs together for greater impact.

Impossible XXE in PHP- 1939

Aleksandr Zhurnakov - Swarm PT    Reference →Posted 3 Days Ago
  • The code snippet the author shows should prevent XXE in PHP. The usage of external entities is disabled when XML on the first call, but NOT on the second. There are four obstacles:
    1. Entities are set to an empty string during initial XML loading.
    2. Disallows external entities from being loaded into another.
    3. No networking URIs are allowed, such http://.
    4. With XML_DOCUMENT_TYPE_NODE this prevents normal entities from being used.
  • Condition three can be bypassed by using parameter entities. The network issue doesn't actually matter in PHP. This is because it's only used on the initial URI and not in a nested fashion. So, php://filter/resource=http://example.com can be used to bypass this.
  • Condition one prevents the usage of external entity loading out of the gate. The code will remove all external entity references that it sees. It turns out that the SYSTEM attribute is parsed for the DOCTYPE tag. If the code is within the brackets, it is NOT removed on the first parse. This means the second parse will include XXE. This happens because the DOCTYPE is considered part of the structural definition and shouldn't be touched.
  • The final bypass is the impact. How do we extract files? Parameter Entities are defined on the same page and used on that page. Parameter entities are expanded in libxml2 in PHP with a different set of rules when LIBXML_DTDLOAD is enabled. Additionally, the loading time is interesting. The parameters are expanded before the usage of anything else.
  • So, the final payload is as follows:
    1. Create a parameter entity that loads a file.
    2. Create a new entity that references the file in step 1.
    3. The entity is called with a URL that has the entity of step 1 as part of the URL. Because the parameter expansion loads first, this sends the file contents to the server.
  • They found an exploitable path in SimpleSAMLphp and in another undisclosed product. Overall, this is a great post on vulnerability research and skipping past what looks like a "reasonable" defense.