
By: bestiaNXN
October 28, 2015
Tutorial: A3 Cross-Site Scripting (XSS)

By: bestiaNXN
October 28, 2015
Info Sec Institute runs a great site to learn how to hack websites. It's called Practical Website Hacking (http://ctf.infosecinstitute.com/ctf2/exercises/ex1.php) and best of all, it's free. Spoiler alert: This is the solution to the Level 1 challenge.
The vulnerability identified at the bottom of the page is A3 Cross-Site Scripting (XSS).
The A3 Cross-Site Scripting (XSS) is referencing OWASP's 2013 Top 10 most critical web application security flaws. You can go to OWASP's website and find some great resources about XSS and other vulnerabilities.When you navigate to the page, you're presented with a form asking for a Site Name and Site URL. Now, the goal is to run <script>alert('Ex1');</script>. You have two options or places to try to run the malicious script: from the Site Name input field or the Site URL input field. I'm going to run it from the Site URL.When I try to run the script, I get a "Please Enter a URL" message. I'm getting this because the input type is URL by default. The form will validate that it's a URL by default if I'm using a browser that supports this feature. Step 1: Disable the HTML5 Form Input Type ValidationTo disable the HTML5 Form Input Type Validation you cannot use a browser that supports this feature like IE9 and lower, modify the HTML in the developer tools of your favorite browser, or run some code in the Console of your favorite browser. I'm using Chrome. To get to the developer tools, press F12.Change: <form action="" class="ex1">
To: <form action="" class="ex1" novalidate="">
or run the below code in the console to do the same thing:
$('form').attr('novalidate', true);
If you wanted to run the malicious script in the other input field (Site Name), you'd need need to disable the maxsize and pattern attributes used for the input field or disable the HTML5 Form Input Validation as described above.
Change: <input type="text" name="name" required="" pattern="[A-Za-z]+" class="form-control" maxsize="10" placeholder="Name of site">
To: <input type="text" name="name" required="" class="form-control" placeholder="Name of site">
or run the below code in the console to do the same thing:
$('input').removeAttr('maxsize').removeAttr('pattern');
If you try to submit the malicious script, it will submit but not run the code. That's because they're encoding the input when it adds the input to the "My Sites:" section of the page. The encoding is being done on the client side; we can just override the function to not do the encoding.
Step 2: Remove the Replace Method from Either the siteName or siteURL Variable in the ex1.js File
Change: var siteName = $(".ex1 input[type='text']").val().trim().replace(/</g, "<").replace(/>/g, ">");
var siteURL = $(".ex1 input[type='url']").val().trim().replace(/</g, "<").replace(/>/g, ">");
To: var siteName = $(".ex1 input[type='text']").val().trim();
var siteURL = $(".ex1 input[type='url']").val().trim();
Note: For the page to still be functional, we'll have to override the entire object that the above code is found in. To do that, we can just copy the following code from the ex1.js file that gets loaded at page load. To perform this in Chrome, open the developer tools and, under the sources tab, you'll be able to see all the files that the page loads. Below is the code you'll need to copy into the Console. After you paste the code into the Console, make the necessary code changes as described above. Then, run the code.
$(function() {
var Exercises = {
ex1: {
initialize: function() {
$("#messages").text("People want you to store your favorite links here. However, you are not into that, you just want to do some XSS magic to the page. Add an alert with the message 'Ex1' to the page (My Sites:)");
var nativeAlert = window.alert;
var lastAlert = null;
window.alert = function(msg) {
nativeAlert(msg);
lastAlert = msg;
}
$("form.ex1").submit(function(evt) {
evt.preventDefault();
var siteName = $(".ex1 input[type='text']").val().trim();
var siteURL = $(".ex1 input[type='url']").val().trim();
$("<p class='lead'><span class='label label-success'>" + siteName + "</span>" + siteURL + "</p>").appendTo(".ex1.links-place");
if (testForScript("Ex1", [siteName, siteURL], lastAlert)) {
$("#messages").removeClass("alert-info").addClass("alert-success");
$("#messages").text("You made it to exercise 2. You will be redirected to it in 10 seconds.");
levelCompleted(1);
}
})
}
}
}
Exercises.ex1.initialize();
});
We're finally ready to run the malicious code.
Step 3: Enter Script as Input and Click Add Link
Input: <script>alert('Ex1');</script>
AnalysisHere' why this is an example of a Reflected XSS / DOM XSS / Client XSS:
- Reflected XSS type because the malicious script is reflected back onto the page as opposed to being stored in the web application (like in a database or browser cookie).
- DOM XSS type because the malicious script is able to run as a result of modifying the DOM environment in the browser.
- Client XSS type because the code never gets submitted back to the server and the vulnerability is on the client side or browser.
In order to get my malicious script "<script>alert('Ex1');</script>" to execute, I had to run additional JavaScript code manually in the Console of my browser.
Here's the real question: Is this web page really susceptible to XSS?
To answer that question I'm going to ask another question. Can an attacker inject their malicious script into another user's session and have it successfully run?
Lets look at some of the ways a hacker can inject their malicious script into another user's session:
- By loading the malicious script in the response to the client browser from a datasource the web server is using. Without being able to see the source code, I can't say for sure, but this page doesn't appear to be loading any content on server side code.
- By loading the malicious script through the query string in the URL or from a form post. Again, this page doesn’t seem to be loading any content on the page.
Since this page doesn’t appear to load any content then I would deem the page not susceptible to XSS. If the page stored in the web application on the server, then this page would allow attackers to input their malicious scripts to be stored in, for example, a database and, if whatever page doesn’t encode the entry when it goes to displays it, then the malicious script would run in another user’s session.
I hope this was educational and worth your time. I am always trying to learn more and get different perspectives on things. If you have anything to add to or even contradict what I've wrote, I'd love to discuss it. Thanks.