Before you start reading this article, please keep in mind that this is a very basic reverse shell, and still needs a lot of work to get the most out of it. A few of the limitations are:
Recently I have found my first blind XSS, and I quickly noticed that it’s hard to figure out what’s possible with your blind XSS and what impact it can have. To figure this out, I tried several payloads, but felt the need to execute payloads in real time. Because of that, I came up with the idea to make a reverse shell, that I can use as soon as I receive an email from XSS Hunter to notify me the XSS has been triggered. The only problem is that the reverse shell would only work if the victim stays on the vulnerable page. Once he goes to another page or closes the page, the connection will be lost.
This reverse shell isn’t the best solution, but it’s helpful for beginners to experiment with it. And it was a fun little project for me to make.
To start the project, I opened up notepad and started writing down how I wanted the shell to function.
I started by creating something that sends the payload to the victim, but does not yet send the response back to the interface. The code is pretty simple, there is a form on the page which on submit, sends a post request to itself (index.php). The PHP on the page will write the payload that’s in the post request to a JavaScript file. The interface code looks like this:
Now it’s time to write the JavaScript that will be ran in the victim’s browser. As you’ve seen in my notes, I’m not sure what interval should be used to make the network request, but I think 1 second is good to start, but feel free to change this if you want it to be faster or slower. The code of the reverse shell looks like this.
The payloadURL
variable should be changed to the location of your own payload script. If you’ve copied my code, payload.js is located in the same folder as where your interface.php is located.
In my code, once the server receives the response, it writes it to a file. 2 seconds after the execute
button is clicked, the response will be read from the file, and reflected on the page. This is probably not the best way to do it, but it works fine if the internet speed of your victim is decent, and if your payload does not take a lot of time to execute. If you experience problems, you could always higher the sleep count in interface.php.
To start, I edited reverse.js so that it would send the response in a POST request to interface.php. Response.js now looks like this:
Again, change the value of interfaceURL
to the URL of your own interface. I also added a check to set the response to “undefined” if it’s not defined, because otherwise the interface would keep displaying the old response when executing payloads without response.
Now the response should be handled in interface.php. As mentioned earlier, the response is written to a file, and reflected 2 seconds after execute
is clicked. The code for interface.php now looks like this:
As a good practice, I used the php function htmlspecialchars()
to prevent reflected XSS on the webpage.
First of all, you need to make sure interface.php and reverse.js are accessible by the internet. To do this, I used a hosting service, but you could also host it by yourself and setup port forwarding.
When that’s done, you need to link the reverse.js to your XSS Hunter so it would be executed in a victim’s browser once the blind XSS is triggered. To do that, login to XSS Hunter and go to settings
and under additional JavaScript payload URI, add the URI to your reverse.js script. Finally, scroll to the bottom and click the Update Settings
button.
Believe it or not, but that’s actually it, everything is done at this point, and you’re ready to test it out.
username.xss.ht
). And open that file.2. Open your interface.php file on your public webserver. and enter alert()
to see it trigger on your html test page. The response will be undefined
.
3. Enter 2+2
and notice the response will be 4
.
Congrats! Thats it, you got yourself a very simple JavaScript reverse shell :).
Feel free to modify your code to make improvements!