Home Blog Second-Order Attacks, Exploitations and Security Best Practices

Second-Order Attacks, Exploitations and Security Best Practices

19.08

What is a Second-Order Attack?

Second-Order Attacks, Exploitations and Security Best Practices

Second-order vulnerabilities are not a distinct type of vulnerability in their own right, as a command injection might be. Rather, they refer to a specific way of exploiting existing vulnerabilities.

They arise when user input is stored by an application and then reused later in a different context without being properly validated or processed.

A classic example is stored XSS, which in many cases constitutes a second-order exploit. User input is first stored in the application without being properly sanitised. It is then reused or displayed in another part of the application, or even in another application—such as a back-office system—without being properly escaped on output. It is at this point that the vulnerability manifests itself.

Many types of vulnerabilities can thus be exploited in a second-order manner, including XSS, SQL injection, LFI/RFI and RCE. Below, we will detail two specific scenarios, relating to SSRF and SQL injection respectively. The principle, however, remains applicable to these other types of vulnerabilities.

What are the differences compared with ‘traditional’ attacks?

The main difference between a conventional attack and a second-order attack lies in when and where the exploit is triggered.

In the case of a traditional attack, the injection immediately causes unexpected behaviour, either directly on the server side or in the application’s response. The presence of the vulnerability can therefore be observed and measured at the moment the malicious payload is injected.

Conversely, in a second-order attack, the injection and execution occur at two distinct moments. The payload is first stored or transmitted without necessarily causing any visible behaviour, and is then executed at a later stage when it is reused in a different context.

This is particularly the case with a Blind XSS attack.

How to detect second-order attacks?

Second-order attacks are particularly difficult to identify, and the detection approach varies significantly depending on whether one is working in a black-box, grey-box or white-box context.

In black-box or grey-box scenarios, automated tools are often ineffective, as they rely primarily on the immediate response to a request. However, in the case of a second-order attack, this response generally shows no visible signs of the vulnerability.

One method therefore involves injecting unique markers into each of the fields whose data is recorded by the application, then exploring the various functionalities to identify where these markers reappear. This helps to pinpoint the contexts in which user-controlled data is reused.

When the vulnerability is triggered blindly, it is necessary to rely on an external server to detect any interaction. Tools such as Burp Collaborator, for example, can identify this type of trigger.

In white-box testing, code review remains the most reliable approach. However, it requires a holistic view of the data flows within the application, rather than analysing each function in isolation. The first step is to identify the various sources from which user input can be entered into the application, then to trace the path of this data to the locations where it is stored and reused. The aim is, in particular, to identify instances where user-controlled data subsequently reaches a sensitive context, such as an SQL query.

Second-Order Vulnerability Exploitation Examples

Exploiting an SSRF via a second-order attack

Let’s take the BookVault app as an example, where any user can create an account.

BookVault sign-in page with a centered login card containing username and password fields and a Sign in button.
Login page

Once an account has been created, the user can add a book to their library using a URL. This type of functionality is frequently encountered during our audits and is often a source of vulnerabilities.

By analysing the application’s source code, we can identify a configuration issue here.

Python fetch_url(url) validates URL scheme and raises ValueError for unsupported schemes (file/http/https).
File protocol is allowed

In addition to the HTTP and HTTPS protocols, the developer has also enabled the file protocol. This makes it possible to access files on the server directly, which constitutes a vulnerability.

To verify this, we can use the entry file:///etc/passwd. This file is present on UNIX systems and can generally be read by all users.

Dark BookVault library page showing a form to add a book by URL and an empty 'My books' panel.
Access to /etc/passwd

However, the application returns an error stating that no <title> tag was found in the file. To understand why this is happening, we need to examine the extract_title() function.

Code snippet: Python function extract_title(content) that extracts the last HTML title tag content using regex and returns it, or None if no match.
extract_title function

A regular expression (regex) is applied to the retrieved content in order to extract everything contained between the <title></title> tags.

Although it is possible to read files on the server, few of them are likely to contain such tags. It is even less likely that the data contained between them would be of particular interest to an attacker.

However, a more in-depth analysis of the source code reveals two interesting behaviours:

  1. The application logs the administrator’s session cookie at regular intervals. These logs are stored in the file /app/app.log.
  2. In the event of a failed authentication attempt, the username provided is logged as is in this same log file.

Based on these two elements, it is possible to envisage a scenario whereby the administrator’s session could be compromised:

  1. We attempt to log in using <title> as the username. This value is then recorded in the log file and corresponds to the start of the regular expression used by the application.
  2. We wait for the application to add an entry containing the administrator’s session cookie in the meantime.
  3. We make another login attempt, this time using <title> as the username. This value corresponds to the end of the regular expression. All the data recorded between our two attempts is therefore enclosed within the tags <title> and <title>.
  4. We then use the payload file:///app/app.log. The extract_title() function then extracts all the content located between the two tags we injected, including the administrator’s session cookie. This can then be used to access their account.
Dark BookVault dashboard showing a 'My library' panel with a URL input and 'Fetch title' button, and a 'My books' list.
Get admin session token

This scenario clearly illustrates the principle of a second-order attack. The various actions carried out separately do not, on their own, allow the vulnerability to be exploited directly. It is the sequence of these actions, together with the subsequent reuse of the injected data, that makes exploitation possible.

This scenario is based on a real vulnerability that we identified during an audit. It had enabled the retrieval of several megabytes of logs generated by the application over a given period.

    Exploiting an SQL injection via a second-order attack

    In this second scenario, we will exploit an SQL injection via the username.

    The SupportDesk application allows users to create an account, edit their profile details and contact support. They can also view their ticket history from the /support page.

    Support dashboard showing user alice's tickets and an open VPN access ticket in a dark theme UI
    Dashboard

    From the profile section, users can change their username, email address and password. These are therefore standard features found in many web applications.

    An analysis of the source code reveals that both account creation and profile editing rely on parameterised queries, thereby preventing direct SQL injection at this stage.

    Flask route /profile handling GET and POST to update and fetch a user's profile (username, email, full_name).
    Profile update source code

    The code shown above is therefore not vulnerable as it stands. It should be noted, however, that the three fields are stored in the database as they are, without any specific sanitisation.

    On further analysis of the source code, however, it can be seen that, on line 208, the username is concatenated directly into an SQL query.

    Code editor screenshot showing a backend /support route: validates session, fetches username, queries tickets by user, then renders support.html with data.
    Vulnerable query

    An important point is that this value is not retrieved directly from user input when the query is executed: it is read from the database.

    However, as we have just seen, the user can previously modify their username and store arbitrary characters within it. It is therefore possible to inject an SQL payload, which will be stored in the database without immediately triggering any specific behaviour.

    The vulnerability arises when this value is reused by the /support route. For example, if a quotation mark is stored in the username, and a GET or POST request is then made to this route, the stored value is concatenated into the SQL query. This then becomes invalid and causes an error to be returned to the client.

    Support desk page with user 'alice' signed in and a red error bar under 'My tickets'.
    Query error returned to client

    The injection is therefore indirect and less obvious to identify, but it is certainly present. The payload is injected when the profile is modified, whilst its execution only takes place later, when the username is retrieved from the database and then reused in the SQL query.

    A basic automated scanner may fail to detect this vulnerability, as it generally relies on the immediate response to the query containing the payload. However, Sqlmap allows you to handle this type of scenario by using options such as --second-url or --second-req.

    From there, it becomes possible to modify the username with a suitable payload in order, for example, to retrieve information about other users. By injecting a UNION-based SQL injection into the username and then revisiting the /support page, the payload is executed and the query returns the list of users.

    SupportDesk page with a dark blue UI showing a 'My tickets' table (Subject, Message, Status) and a form to open a new ticket below; a highlighted row area is outlined in red.
    Exploitation of the Second-Order SQL injection

    What are the Impacts of Second-Order Attacks?

    By its very nature, the impact of a second-order attack is no different from that of the underlying vulnerability: an SQL injection remains an SQL injection, an XSS remains an XSS, and so on. What does change, however, is the context in which the malicious payload is ultimately executed.

    This is precisely what makes these attacks particularly interesting. Execution may take place in a context with higher privileges than that of the initial injection point. For example, data may be saved by a standard user and then reused later in a back-office system accessible to an administrator.

    This is particularly the case with Blind XSS, but also with the BookVault scenario described earlier: the attack starts from a simple user account but ultimately allows the administrator’s session cookie to be retrieved.

    Another important feature is that the malicious payload is not usually present in the request that triggers its execution. The request itself may be entirely legitimate and contain no suspicious elements. A WAF therefore finds it difficult to identify the attack at the time it is triggered, as the malicious data was introduced earlier in the application.

    This behaviour also complicates incident response. A malicious payload may remain stored for several hours or days before being reused and executed, making it more difficult to correlate the initial point of injection with the event that triggered the incident.

    The ultimate impact therefore depends mainly on the context in which the data is reused. In our previous examples, the exploit enables, respectively, the theft of an administrator session and the exfiltration of user information. Depending on the underlying vulnerability and the execution context, however, a secondary attack could lead to other consequences, such as code execution or privilege escalation.

    How to Protect Yourself Against Second-Order Attacks?

    There is no single remedy for second-order attacks. As we have seen, these do not constitute a specific category of vulnerability: the remedy therefore depends primarily on the underlying vulnerability.

    The fact that an attack is second-order does not necessarily imply any specific protective measures. It is, above all, the vulnerability present at the point where the data is reused that must be addressed: parameterised queries to prevent SQL injections, context-sensitive output encoding for XSS, validation of the protocol and destination for SSRF, and so on.

    The key principle to bear in mind is that data considered safe in one context is not necessarily safe in another. In our SupportDesk example, the username is harmless as long as it is used on its own, but becomes dangerous as soon as it is concatenated into an SQL query.

    Data should therefore never be regarded as secure simply because it comes from a source deemed trustworthy, such as the application’s database. The database may simply contain data entered by a user and recorded at an earlier time.

    Finally, as these vulnerabilities are particularly difficult to identify, code review remains one of the most effective approaches. The analysis must be carried out by thinking in terms of data flow: this involves identifying the points at which user input is entered and stored, then tracking the various points at which this data is subsequently reused in order to verify that context-appropriate safeguards are indeed in place.

    Author: Théo ARCHIMBAUD – Pentester @Vaadata

    Partager l'article
    Language

    Stay connected!

    Receive offensive security updates (selection of articles, events, training…)

    Search

    Tell us about your offensive security challenges and needs
    Contact us to discuss your offensive security needs and get information about our services and processes. Our team will get back to you as soon as possible.