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!

Git Arbitrary Configuration Injection (CVE-2023-29007)- 1687

Andre Baptista    Reference →Posted 8 Months Ago
  • The authors of this post use git submodules internally. They noticed that long submodule URLs led to crashes on a GitHub repository page. They weren't sure why so they started fuzzing it. Eventualy, they noticed that deinitializing submodules sometimes creates new sections in .git/config. But why?
  • When reading configuration files in groups of bytes of 1024, it assumed that the beginning of a read is the beginning of a line. However, with super long lines this isn't the case. So, providing a line with 1024 characters and then a [ for a section header would make the parser believe it was looking at a new section when it really wasn't!
  • By providing a malicious URL that is controllable by an attacker, they could smuggle commands, such as bash commands, into a .git/config using this. They found this was possible via a section was being removed or renamed.
  • The most interesting part to me was how they found the bug. It wasn't a crash in the git client - it was a side effect. Then, after some investigation, they discovered the reason why this was happening. Once you see the bug and the idea, it's straightforward, but it's not an obvious place to look for bugs.

Clone2Leak: Your Git Credentials Belong To Us- 1686

RyotaK - Flatt Security    Reference →Posted 8 Months Ago
  • Git implements a helper protocol called Git Credential Protocol to retrieve credentials from a process. There are several implementations of this depending on the platform, such as Windows and MacOS.
  • The Git Credential Protocol separates parameters using newlines (\n). For instance, sending protocol=https\nhost=github.com\n would return protocol=https\nhost=github.com\nusername=USERNAME\npassword=PASSWORD. Git forbids newline and NULL byte characters in any of these names. But, is this sufficient?
  • GitHub Desktop has a feature where a user can supply credentials to a Git client automatically. The code uses a regular expression in multiline mode to parse a URL passed in. Since \r is a splitter for regex and is allowed by the protocol, this creates a problem. The same attack could be launched on the .NET version of this product as well.
  • A malicious repository with a crafted submodule URL can cause a git credential leak by adding more information to the request than anticipated via including carriage returns - http://%0dprotocol=https%0dhost=github.com%0d@localhost:13337/. This will break into the following:
    protocol=http
    host=localhost
    username=\rprotocol=https\rhost=github.com\r
    
  • git LFS is an extension of git for large files. Although core git rejects newlines, they are not rejected by LFS. Using the configuration file .lfsconfig, newline injection into the protocol is possible - this issue required an alternative path to hit. url = http://%0Ahost=github.com%0Aprotocol=https%0A@localhost:13337/ would turn into the following:
    capability[]=authtype
    capability[]=state
    protocol=http
    host=localhost
    username=
    host=github.com
    protocol=https
    
  • The next two are simple access control bugs IMO. The GitHub CLI will leak the access token to arbitrary hosts that are making requests. The tokenForHost function will always return true for non-GitHub owned instances. There are several cases where this is sent, such as GitHub enterprises, and CodeSpaces environment variables are set.
  • The credential helper on GitHub Codespaces was a very simple bash script that always returns the token to Git. Although the host parameter is set to github.com, this isn't actually validated by git to match the currently requested host. So, Codespaces will send the token to the domain that hosts the repos, even if not GitHub.com.
  • Overall, a good series of vulnerabilities with string parsing complexities. Great research!

CVE-2025-48384: Breaking git with a carriage return and cloning RCE- 1685

dgl    Reference →Posted 8 Months Ago
  • There are two types of "next line" characters in use: carriage return and newline. On original typewriters, carriage return moved the cursor to the left of the margin while the newline (line feed) went down a single line. This made the characters distinct in many ways. Unix tried to just use a newline (\n) while Windows required a CRLF still.
  • .gitmodules is a configuration file in a Git repo that controls submodules. When parsing, it attempts to support both cases described above - Unix \n and \r\n. It should be noted that besides reading these files, git can also write to them directly.
  • When writing a configuration file, git will "quote" the value if it contains a double quote, space, semicolon, or hashtag. Upon writing this information to another file, a final carriage return would effectively be skipped.
  • The actual vulnerability is really a parser difference between the reading and the writing. In other words, it creates a potential time-of-check versus time-of-use security issue. Here's the path:
    1. Create a submodule file that contains the path "foo^M" where ^M is the line feed. The file location is validated at this point.
    2. When this is written to .git/modules/foo/config the content is written as foo^M without the quotes.
    3. When the configuration file is read later, it will parse this as foo without the ^M. This is because the parser will strip out the final CR at the end of a line.
    4. Practically, this means that writing to a file path now has a different meaning than intended. This could lead to symbolic links going to unintended locations on the file system, escaping the cloned directory's sandbox.
    5. The PoC writes to .git/hooks to force it to write arbitrary code and open upon finishing the clone. Pretty neat!
  • The analysis at the end is pretty interesting. Carriage returns led to another bug in the credential helper protocol of git that led to credential leakage. Another one around configuration parsing was found in 2023. These differences in components of git are similar to CRLF injection in HTTP.
  • Overall, a good post that demonstrates a severe vulnerability in Git. I appreciate the clear permission boundaries of git and would like to see more research into it.

Google Logo Ligature Bug- 1684

Jeffrey Yasskin    Reference →Posted 8 Months Ago
  • Fonts can include ligatures - special case specific combinations of letters. For instance, an "f" and an "i" combine into "fi" nicely. The bug reporter noticed that Google Sans, used in the domain of the Chrome browser, includes many long ligatures that could be used for domain spoofing.
  • glogoligatureoogle gets mapped to google for instance. That's pretty terrifying! The bug report triager found lots of other cases where this happens as well besides this one.
  • The triager decided to rate this as a high because of the spoofing effects of the bug. For this, they got 10K and a 5K bonus for the uniqueness of the finding. To fix it, they disabled the usage of hostnames containing ligatures.
  • Super crazy finding! UI vulnerabilities like this are pretty rare so this was fun to see.

Finding Fractures: An Intro to Differential Fuzzing in Rust - 1683

Anthony and Nick Lang - Asymmetric Research     Reference →Posted 8 Months Ago
  • The blog post introduces a concept known as differential fuzzing. The idea is to generate input, process it through multiple pipelines and see if the output is the same. In blockchain protocols that must have the same data, such as consensus client protocols, this is a great way to find bugs. Asymmetric Research uses this for many things, like fuzzing the Solana validator client differences Agave and Firedancer.
  • The target for this demonstration is around JSON parsing. Their chosen fuzzer is AFL. The majority of fuzzing is the same as with a regular AFL fuzzer - input generation and such. The main difference is that we have two JSON parse calls to make. If the results are different, then this results in a "crash"!
  • While running the fuzzer, they ran into several bugs but they were unimportant for security. For instance, 222E2322 was an out of range number that was rejected for one parser but fine by another. Since this doesn't have security consequences, they patched out to accept this case as valid. This happened several times. It should be noted that using a fuzzer is an iterative process - it's not just letting it run once and forgetting about it.
  • Eventually, they get a legitimate parsing difference. serde_json gets a parsing error while json-rust parsers it. After looking at a hexdump, it becomes clear - the vertical control tab (^K) is causing the issue. json-rust has a goal of being less strict than the other JSON parser, since this can cause friction at times.
  • This bug is likely enough to cause a consensus divergence, which is pretty interesting. Many other parsing issues between implementations, like described by the Bishop Fox post, can lead to major security consequences by returning difference values.
  • There are many ways to make this fuzzer better. Using structured input on JSON data, parallelization and checks for equivalence on the data. Overall, a great post discussing automatic bug finding via differential fuzzing.

Novel SSRF Technique Involving HTTP Redirect Loops- 1682

Shubham Shah - Searchlight Cyber    Reference →Posted 8 Months Ago
  • Blind SSRF bugs are difficult to exploit. Just because you have a Server-Side Request Forgery bug, doesn't mean that the data is being returned back to you properly. The article explains a technique that the author used to turn a Invalid JSON exception with no data to get the full response data. Notably, they wanted to get the AWS metadata information.
  • They tested a lot of the handling of responses in the application by sending the request to their website via the SSRF and seeing how it reacted to different things. 300s, 400s, 500s, etc. They noticed that a 500 error returned all of the data. Of course, making a request to the AWS cloud metadata service will respond with a 200 so this wouldn't work for returning the data. Their goal was to trigger a 500 error but get the response from the server.
  • Since this was black box, they had no idea what to do next. The application was following redirects for 3xx status codes so they were curious what would happen if they reached the maximum amount of redirects. This led to a NetworkException and wasn't very useful. So, they decided to do some fuzzing around the types of 3xx status codes and their handling.
  • Their fuzzing was simply using each 3xx status code once and incrementing to the next one. To their surprise, on the application returned the full chain of redirects and the entire response to the metadata request from the final redirect. But, wait, why!?
  • They made some guesses on why this may have worked. The application was happy to follow a few redirects. However, if it followed more than 5 redirects not handled by libcurl then their was another error state. Surprisingly, this technique has worked in several situations for the author of the post.
  • I'm always amazed by how successful people are with this blackbox fuzzing to understand applications. For every instance of a blog post like this, there are likely several hundred cases that were not exploitable though. Interesting read!

Make Self-XSS Great Again- 1681

Slonsor    Reference →Posted 8 Months Ago
  • Self-XSS is when you can trigger cross site scripting (XSS) but only on yourself. This post goes into a few ways to make self-XSS exploitable, with the final one being the most interesting.
  • The main topic of discussion is credentialless iframes. A credentialness iframe is an iframe that is loaded inside of a different context than those on the same origin. Since iframes on the same origin is able to edit other frames on other origins, it's able to edit the logged in iFrame still.
  • If the page contains login CSRF then the usage of credentialless iframes becomes useful.
    1. Create a login CSRF attack on a victim and get the victim to visit the website.
    2. On the same page with the login CSRF to a page that contains two iFrames: one with the credentialless iFrame and another with the regular user login.
    3. Use the XSS on the credentialless iFrame to write into the context of the other iFrame. This leads to many security issues.
  • The second idea is using clickjacking to trick a user to login to an account instead. This works when CSRF login is not possible. Both of the previous techniques require iframes to be allowed on a page though.
  • The coolest example is the final one, by far. In 2025 the function fetchLater function was added. This will send requests after some time, even if the tab is closed. This means it may be possible to do the following:
    1. Trigger self-XSS on an account you control.
    2. Call fetchLater for a fetch requests that uses cookies for a sensitive API.
    3. Logout of the account.
    4. User logs into the account later.
    5. The fetchLater request runs in the context of the users session. This is an easy account takeover from here!
  • On the Critical Thinking podcast, the host Justin claims that the closing at Chrome will shoot off all the requests, making it not good for . To get around this, an attacker can stall the HTTP response on a server that they control with maximum length timeouts in Chrome and redirects. Eventually, the redirect can go to a malicious endpoint on the regular server from the context of the Chrome request. I think that the redirect will lead to a resubmission of the cookies, such as the new cookies of the logged in user. Pretty neat!

Acala Block Production Shutdown Bug Fix Review - 1680

Immunefi    Reference →Posted 8 Months Ago
  • Acala is an L2 blockchain built around the Polkadot ecosystem. Polkadot acts as the relay chain which coordinates with other blockchains in the network. Acala, in this system, is referenced to as a "Parachain". The parachain is able to create lots of custom functionality for their needs.
  • On a Parachain, there are para-validators. These validators are responsible for block creation and block finalization on a specific block.
  • Home module specific to Acala is the Homa module. Homa is a Tokenized Liquid Staking Protocol. The idea is that DOT (Polkadot tokens) could be put into the module and a representation called LDOT returned to the user. Everyone wins - the protocol has more funds to use in staking, the user gets a little bit of that profit and the user is able to use LDOT on the blockchain for other things. If a user wants to withdraw their DOT token, the user submit an unbond request. Every 24 hours all of the unbond requests are processed at once.
  • The vulnerability is something relatively simple but complicated to know if it's exploitable: a missing size limit on the amount of unbond requests. Since this list of unbounded (see what I did there), it can be filled up and force the blockchain to process too many in a single call. There's just a big loop that it iterates over.
  • When I see vulnerabilities like this, I think "PoC or GTFO". Is this actually exploitable? In reality, it is! The blog post says that Acala blocks have a time limit and if this isn't met then the chain halts. By creating 22K withdrawal requests, it slows down the chain enough to prevent the block from being created.
  • The payout was interesting to me. According to Immunefi, a Governance proposal takes 15 days to go through on Acala - meaning that a downtime of 15 days is likely because the proposal is required for the upgrade. Additionally, DefiLlama has a 15 day volume of 712K per day. Given that the payout should be 10% of that, the whitehat got 10% of it.
  • To me, this calculate is strange. If a chain was indeed really down the governance would pass significantly faster. Additionally, a denial of service paying 10% of funds at risk is weird to me; it's an L1 that can fix the chain. The funds were never permanently stuck, like if it was a smart contract that couldn't be changed.
  • A good bug, a good payout and a good writeup!

Deterministic signatures are not your friends- 1679

Paul Miller    Reference →Posted 8 Months Ago
  • The original implementation of Elliptic Curve Digital Signatures Algorithm (ECDSA) worked the same as DSA besides it used EC math. It has a known bad flaw: if you use reuse the nonce, then it's trivial to recover the private key with only two different messages. This has been the root cause for many hacks, such as the Playstation 3s key leak from Geohot.
  • To prevent the duplicate usage of nonces on different data, deterministic signatures were created. The nonce, k, is deterministic based upon the private key and message used. For instance, hash(key||message) would always be the same for every message. Since the attack described above requires two separate messages, this removes the attack vector entirely. Or, so we thought. Since a bug in ellipitic.js was announced, this is being rethought.
  • If two different messages can create the same nonce value then we have the same issue as before. In RFC6979 the JavaScript implementation converted a Uint8Array to a bigint. This had a bug that doesn't properly add leading zeros to a hex value. So, the arrays [1, 1, 30] and [17, 30] led to the same nonces being used. If an attacker could trick the system to sign these two pieces of data, they could recover the key as a result.
  • So, if both are bad then how about we combine them? This is the concept behind hedged signatures. If there is BOTH a deterministic portion and a random portion, then BOTH would need to be done incorrectly for this to fail. There are some downsides, mentioned in the post, but it's interesting none-the-less.

Cosmos SDK Security Discussion/Presentation- 1678

Alpin Yukseloglu & Spearbit    Reference →Posted 8 Months Ago
  • The video explores the Cosmos SDK and highlights some of the key security considerations. The person giving the talk is a protocol engineer at Osmosis, a very prominent blockchain in the web3 space.
  • The Cosmos SDK provides developers with significantly more control over the environment in which they work. Many of the issues surrounding Cosmos SDK chains stem from a central concept: "with great power comes great responsibility."
  • With general-purpose smart contract platforms, many of the issues are taken care of for you. For instance, smart contracts will price you for each instruction that is executed. They also handle panics for you. In the world of the Cosmos SDK, this is not the case; all of this needs to be manually considered for each blockchain.
  • In the BeginBlocker/Endblocker, the code is free of most restrictions. There is no gas; there is no timeouts; there is no panic handlers. So, ensuring that a Golang Panic doesn't occur in this section of code by a malicious adversary is essential. It's common for projects to have generic panic handlers to deal with this.
  • Unbounded operations cannot exist here. Apparently, it's common for a sudo call to CosmWasm to a user-controlled contract to be called. Since there is no gas limit, a user can run an infinite loop, allowing this process to continue indefinitely. Simply adding a gas meter on user-controlled operations is a wise move.
  • Another big one is non-determinism issues. This just means code that may run differently on someone else's machine, leading to a consensus failure. Things like time-based checks, random number generators, floats and Go iteration over maps are not guaranteed to give the same result. The main solution is just to not use functionality that does these things.
  • Most L1 handles fees for you. In Cosmos, you can create your own fee markets. For instance, you can make execution free or free in specific scenarios. However, it's important to recognize the ability to exploit this - if you can infinitely add TXs for nothing then an attacker can halt the chain.
  • Overall, a good video from a knowledge developer/auditor. It's interesting because most of these issues stem from real world issues found on Osmosis.