Miranda Ross is a member of the Synack Red Team and specializes in cross-site scripting (XSS).
I regularly encounter caches, filters and firewalls while working on XSS attacks during engagements. Navigating the layers between you and the application being tested is vital to a successful test: Sometimes you can attack an application using its security mechanisms.
Firewall Evasion
I never assume a firewall’s rule sets. In one case, an application blocked the popular onerror
attribute — a great vehicle for bypassing firewalls — but still allowed onload
. It prevented using alert
and eval
but only when immediately followed by parenthesis or a period. Concatenating inside square brackets caused syntax errors. Using the initial eval
to assign a variable name gave me the flexibility to craft a proof of concept with a higher impact. Putting these together, I came up with the following payload to successfully trigger XSS on the page.
Another firewall I ran across needed a more obscured payload. The injection point was inside an input
tag. It allowed angle brackets but blocked most tags. I did find the <style
> tag worked, which was all I needed to complete the payload. XSS was possible by assigning an animation style to the input
tag. This one didn’t permit eval
but did allow parent
. I could then call eval
through concatenation. The final <style
> tag triggered the animation executing my script.
Here’s the resulting input form:
Filter Manipulation
Rewriting input during normalization can backfire. I was analyzing a web application to sanitize for quotes, backslashes and anything allowing me to break out of double quotes. However, when I put in an HTML image
tag without quoting the src
value, the server would take it upon itself to enforce best practices—automatically adding quotes! I could insert JavaScript in the image tag’s src
value.
I use a list of special characters to tell how applications handle them individually. I’ll try different combinations of encodings to see what works, saving them to a list for building a working payload. A good reference is OWASP’s Filter Evasion Cheat Sheet.
Cache Breaking & Poisoning
Caching servers make applications faster by storing responses at the edge of content delivery networks (CDN), saving the application server from processing requests individually. These fast static responses can trick scanners and analysts into thinking an application is secure when it is vulnerable. Even worse, a misconfigured CDN may be used to distribute XSS or a client-side DoS.
Caching servers look at specific parts of HTTP requests to make a “key” and serve the matching response. If no response matches or they’re expired, the cache goes to the origin server and saves a new one. Scanners and analysts often use parameters called cache-busters. This technique alone does not work on many CDNs — primarily the very ones vulnerable to cache poisoning — and it almost always fails to break through layered or complex caches.
An application that reflects parameters but doesn’t key them may be vulnerable to cache poisoning. Here’s an example from one I found where the firewall blocked double quotes, but it let me break out of the script tag entirely using a closing script tag and commenting out the rest of the page. It didn’t allow an opening script tag, so I used an `svg` and an `eval.call`.
Going over an entire request, I’ll check basics to the obscure for variances. Finding unique ways to break through layers of caching lets me see where the server is vulnerable. Anywhere not keyed is a potential injection point. The following are only a few of the places I have been able to use to hide injections from the cache key.
Mitigation
OWASP has some general guidelines for preventing XSS attacks. All user input should be sanitized or escaped. Test applications from both sides of the cache/content delivery network (CDN). Configured correctly, CDNs can help mitigate DDoS attacks. Firewalls and filters can decrease the chances of an XSS attack. However, even these tools can have unique paths allowing for exploitation. If an attacker has the time and skills to explore the different ways an XSS can be executed, they will eventually find a way in. Conducting a “friendly” adversarial engagement, such as pentesting with the SRT, is necessary to thwart the malicious creativity of real world adversaries.