[HackerNotes Ep. 60] Our Take on PortSwigger's Top 10 Web Hacking Techniques of 2023

This episode is all about the Portswigger top 10 research of 2023. We’ve done our own spin on this, the HackerNotes top 5.

Hacker TLDR;

  • Portswiggers Top 10: It’s been a seriously good year for research and Portswigger dropped the top 10 for the year. We’ve done our own spin, HackerNotes top 5, below:

  • Smashing the state machine: the true potential of web race conditions: James Kettle combined Nagle's algorithm with HTTP/2 methods to create a single packet attack, resolving historical race condition issues caused by network jitter. This functionality has been nicely bundled into Burp Suite repeater via the grouping functionality for all of us to use.

  • From Akamai to F5 to NTLM... with love: A HTTP request smuggling on Akamai Edge, used to identify a cache poisoning in F5s BIGIP, to then poison unsuspecting victim users to exfiltrate their session material. Pretty crazy writeup!

  • SMTP Smuggling - Spoofing E-Mails Worldwide: This research took inspiration from James Kettle's HTTP request smuggling to apply the same principles of request smuggling to the SMTP protocol. Discrepancies in how messages endings are intrepreted allowed for the researchers to smuggle and spoof additional SMTP messages and piggy back off of trusted infrastructure.

  • PHP filter chains: file read from error-based oracle: Using an error based oracle and some PHP quirks, the researchers managed to create a working proof of concept to arbitrarily exfiltrate a file via PHP filter chains.

  • Exploiting HTTP Parsers Inconsistencies: This research focuses on parser discrepancies between Nginx and different backend technologies. Different backend languages treat characters differently than Nginx, resulting in inconsistencies when interpreting a given path. Hint: Make sure to include hex characters in some of your wordlists!

Once again, it's that time of the year, folks! PortSwigger sifts through and determines the top 10 web application hacking research pieces from the plethora of notable research released throughout the year.

The 10 that came out on top are:

  1. Smashing the state machine: the true potential of web race conditions:

  2. Exploiting Hardened .NET Deserialization

  3. SMTP Smuggling - Spoofing E-Mails Worldwide

  4. PHP filter chains: file read from error-based oracle

  5. Exploiting HTTP Parsers Inconsistencies

  6. HTTP Request Splitting vulnerabilities exploitation

  7. How I Hacked Microsoft Teams and got $150,000 in Pwn2Own

  8. From Akamai to F5 to NTLM... with love.

  9. Cookie Crumbles: Breaking and Fixing Web Session Integrity

  10. can I speak to your manager? hacking root EPP servers to take control of zones

If you’re interested in the original post detailing all of the research, it can be found here.

In true HackerNotes fashion, we’ve TL;DR’d our top 5. Let’s jump in.

James Kettle made his return for last year dropping an absolute gem of a technique to exploit previously difficult, if not near unexploitable races.

If you’re unfamiliar with race conditions, a race condition is, in its simplest form, where two processes or threads attempt to access the same resource at the same time. The fun part is if you can win the race, then you can do a whole bunch of unexpected stuff.

With race conditions in the context of HTTP, each HTTP request usually goes through an application entering many different states, or sub-states. Take for example an object being instantiated, it could be instantiated with a default set of properties, which then get overwritten by input from our HTTP request. This small window would be a substate.

Trying to abuse one of these substates was historically quite difficult, with numerous things to account for such as network jitter, latency issues, server load, and so on. This made the window (or the race) to abuse these types of conditions difficult due to factors largely out of our control or unknown to us.

James’s research combined Nagle’s algorithm, which essentially abuses behavior to combine numerous small outgoing messages and sends them all at once, with HTTP/2 methods of combining multiple HTTP requests in the same packet to form the single packet attack, which eliminated all of the historic problems of race conditions with network jitter.

The implementation of this is pretty sleek - first, pre-send the bulk of each request. If the request has no body, send all the headers, but don't set the END_STREAM flag. Withhold an empty data frame with END_STREAM set. If the request has a body, send the headers and all the body data except the final byte. Withhold a data frame containing the final byte. Then, use a last-byte sync to complete all packets at the same time.

This research has been easily packaged for us to use in Burp Suite via repeater. You can use the repeater tab grouping functionality to group several taps together, and then send that group via the single-packet attack.

I previously remember going as far as spinning up an AWS instance in the same region as something I was attacking to try and reduce network jitter to see if something was exploitable in a race condition - this completely removes the need for that added work.

Off of the back of this research, Portswigger created a set of labs. Check them out here.

If you were looking for a reason to brush up on request smuggling like myself, this article could be the push you were looking for.

At the end of an engagement, researcher d3d launched a smuggle probe which came back with a bunch of findings. It looked like the trace method was being processed by a backend server somewhere in the flow of the probe.

During this process, they managed to identify that the smuggling gadget could also be used to poison the cache in the process. Initially, it wasn’t clear exactly what cache and to what extent it was being served to but artifacts hinting Akamai could be the culprit were evident.

After testing this gadget against all Akami customers with a bug bounty program, it was determined that a specific smuggling variation could be crafted to hit the Akamai Edge servers. So we have HTTP smuggling into the Akamai edge servers, which could then be abused to poison the cache of Akamai.

Further analysis of the response headers from each successful smuggle revealed that 85% of the response headers indicated F5 BIGIP. So Akamai edge customers using BIGIP were vulnerable to a global cache poisoning bug.

Taking this one step further, all Akamai customers using BIGIP that were part of a bug bounty program or VDP were enumerated with this gadget.

To prove impact, login portals were identified and poisoned using these gadgets to redirect to a Burp Collab instance. Authorization tokens from the login portals started flooding the Collab instance which was enough to earn some pretty tasty bounties:

Now this research didn’t stop here. During the process of identifying bounty targets and reading through traffic, some unexpected POST requests were making their way through with NTLM-related headers set.

Using this traffic combined with a Responder instance spun up in the cloud, they changed the collab callback in the payload to the new Responder instance hostname, which allowed for NTLM credentials to be exfiltrated:

So an HTTP request smuggling on Akamai Edge, used to identify a cache poisoning in F5s BIGIP, to then poison unsuspecting victim users to exfiltrate their session material. Pretty crazy writeup!

Although this isn’t directly a web bug, it still made its way into the top 10 web hacking techniques of the year. I think despite it being based on a different protocol, it still has some great fundamentals we can all take away as researchers which can be applied universally.

This research took inspiration from James Kettle's HTTP request smuggling to apply the same principles of request smuggling to the SMTP protocol.

By default, new lines in SMTP are delimited by \\r\\n . The end of data sequences is marked by characters \\r\\n. \\r\\n as shown below:

Due to some discrepancies across various SMTP implementations, not all servers use the same characters to end a data sequence. Some servers instead use \\n . \\n or \\r \\r. Can you see where this is going?

This mismatch can be abused to create a discrepancy between the relaying SMTP server and the SMTP server that receives the message. By modifying the end of the data sequence, malformed SMTP messages can be sent which can be used to smuggle and send spoofed emails.

As the auth process SMTP relies on happens outside of the messaging process shown above, we are taking advantage of the relay server’s authority as a trusted entity to essentially smuggle additional messaging contents under its context.

Conceptually, the takeaways for this are the same as HTTP request smuggling - identifying what boundaries the server uses to differentiate between requests, and abusing discrepancies across SMTP variations to smuggle additional info across.

There are delimiter(s) that some parsers, regardless of the protocol, recognize as the termination or ending of a context. Can we inject the same or something similar into an input to achieve some form of context break?

This methodology could probably be applied to other protocols to find similar yet undiscovered bugs.

This research was bred from a CTF, and once we get stuck in, you will probably be able to tell straight away. This is very much a TL;DR format of a very long writeup, but we highly recommend checking out the research for yourself.

The CTF essentially asked players to leak a flag via the following index.php content:

<?php file($_POST[0]);

The file function in PHP reads a file but doesn’t return anything - it doesn’t print or echo the content back, so no response will be displayed when you call it. So now what?

Using an error-based oracle and some PHP quirks, the team (after the CTF) managed to create a working proof of concept to arbitrarily exfiltrate a file.

An error-based oracle is when you can trigger some sort of error and can use that error almost as a true or false condition to identify if something is or is not happening.

There’s also a concept in PHP where there you can call the php protocol php:// to access various I/O streams. This also supports a huge amount of attributes to be passed in, and one of them is a filter.

These PHP attributes can also be chained together, some examples of attributes being encodings such as UTF-8, ROT13, and so on.

The exploit used relies on various encodings, one of them being UCS-4 encoding. This encoding pads out each byte into multiple bytes and by doing so over and over again, you can grow the input into such a large output you can create a memory overflow and to cause an error. This is used as the error Oracle.

You can use the filter dechunk to parse chunked transfer encoded data. The first character is intended to be the length of the chunk. It will parse the first character as a hex character, so if the first character is hex, it is used to determine the length and then looks for a CRLF after it. If it doesn’t find a CRLF character after it, it knows to bail out so it doesn’t throw an error. Now we know it's a hex character, but not which character.

Now, there's another encoding, IBM930 (CP930) encoding. Every time this encoding is used, it shifts the alphabet over by one. For example, an a would translate to hex \61, but after the encoding, it will translate to \62.

You can do this over and over again until it crashes. For example, 5 shifts cause a crash. Now the shift is known, you can use it to go backward and know what each character is. From here, various encodings can be used such as ROT13 to rotate to get into a known range and so many more.

This is only scratching the surface of this research. Off of the back of this, a script was created which translates all of these methods into large filter chains which can then be used to leak one byte at a time of a given file.

This research focuses on parser discrepancies between Nginx and different backend technologies. Different backend languages treat characters differently than Nginx, resulting in inconsistencies when interpreting a given path.

When ACLs and controls are usually applied per endpoint, this makes for some pretty interesting impact scenarios when you have the webserver and the backend parsing a route differently to each other.

Nginx supports the capabilities to rewrite, block or trigger rules based on strings or regex based off input from the HTTP pathname. This is done by specifying location rules which look like the below:

location = /admin {
    deny all;
}

location = /admin/ {
    deny all;
}

Nginx performs normalization on paths before checking them - so transforming and standardizing URLs to a consistent format by performing things like decoding and so on.

Equally, each backend does the same. Each language has its own spin on how the trim or strip the function is implemented, essentially meaning each language has differences in which input it removes from paths passed to these functions.

Two examples of this are given in the research:

Now the research highights some nice examples of how this might look when it cmpes to impact. Using the same block rules specified above, the below HTTP request would be permitted by Nginx as it’s not recognized as /admin, get passed to the Nodejs backend which trims the character passing it to the associated /admin route:

It is worth adding that some backends parse the path piece differently, allowing you to start the path with an @ character, ; and so on depending on the flavour. You can even put full HTTP URLs here too depending on the implementation for compatibility between HTTP versions and proxy configurations.

The research also specifies discrepancies across other backends, so definitely check it out here: https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies

I think a takeaway for this one is to add hex characters to our wordlists!

PortSwigger always does a great job of getting together some of the best research around. If you have the time, we recommend deep diving into all 10 of them as there will be no doubt something you can take away as a hunter.

Till next time - GL hunting!