Source Code Analysis XSS


Slack Group

Before we get started I have started a slack group dedicated to hacking. We welcome everyone from beginner to advanced to join. I will be on everyday answer questions, doing CTFs, and talking about cool hacks. If you enjoy hacking and are looking for like minded people join below:

NEW Hacking Group Slack Channel

Introduction

Cross site scripting (XSS) is one of the most prevalent bugs in todays web applications. When doing a black box engagement without source code you typically search for this flaw by spraying your payload everywhere and waiting for your alert box to appear. If you have the source code finding XSS can be much faster and easier.

XSS Basics

People seem to think that you need to know the applications programming language to find security vulnerabilities. When searching for XSS the vulnerability looks similar across all programing languages. If an application is out putting user supplied input to the browser without validating or sanitizing that input then they are most likely vulnerable.

<code>
function(username)
    welcome_message = "<h1>Welcome to the site " + username + "</h1>"
    return welcome_message to browser
</code>

As you can see in the above pseudo code the application is taking a persons username and returning it to the browser in the body of a H1 header. An attacker could easily insert malicious javascript code as their username causing the application to execute it.

There are several techniques to prevent this issue such as using a content security policy (CSP) but that is out of scope of a source code review. At the source code level the most common way to prevent XSS is to sanitize user supplied input before returning it to the browser. Most modern day programming languages come with a library that handles this logic for you.

<code>
function(username)
    username = sanitize_input_xss(username)
    welcome_message = "<h1>Welcome to the site " + username + "</h1>"
    return welcome_message to browser
</code>

As shown in the above pseudo code we use a pre defined function to sanitize the users username before returning it to the browser. This should prevent XSS from happening. Note that this isn’t the only technique to mitigate against this attack.

Example

The only way to get good at finding vulnerabilities in source code is to get some hands on experience. Take a look at the following bit of code.

https://github.com/Learn-by-doing/xss/blob/master/public/index.html

<html>
<head>
	<title>Cross-Site Scripting (XSS)</title>
</head>
<body>

	<!-- A simple form that when submitted will navigate back to the same page -->
	<form action="" method="GET">
		<!-- Adds `?q=VALUE` to the URL when the form is submitted -->
		<input type="text" name="q">
		<input type="submit" value="Search">
	</form>

	<!-- The results of the search are inserted here -->
	<div id="results"></div>

	<script>
		document.addEventListener('DOMContentLoaded', function() {

			/*
				Get the search query from the URL. For example:
				http://xss-example-page.nowhere/?q=Searching+for+things
			*/
			var q = getQueryParameter('q');

			if (q) {

				search(q, function(error, results) {
					showQueryAndResults(q, results);
				});
			}
		});

		function search(q, callback) {

			// Fake results. We don't actually searching anything.
			var results = [
				'Result #1',
				'Result #2',
				'Result #3'
			];

			callback(null, results);
		}

		function showQueryAndResults(q, results) {

			var resultsEl = document.querySelector('#results');
			var html = '';

			html += '<p>Your search query:</p>';
			html += '<pre>' + q + '</pre>';
			html += '<ul>';

			for (var index = 0; index < results.length; index++) {
				html += '<li>' + results[index] + '</li>';
			}

			html += '</ul>';

			resultsEl.innerHTML = html;
		}

		function getQueryParameter(name) {

			var pairs = window.location.search.substring(1).split('&');
			var pair;

			for (var index = 0; index < pairs.length; index++) {

				pair = pairs[index].split('=');

				if (decodeURIComponent(pair[0]) === name) {
					return decodeURIComponent(pair[1]);
				}
			}

			return false;
		}
	</script>
</body>
</html>

One of the first things I tend to do is look for any place user supplied input given. We can see that supplying a GET parameter of “q” will cause the application to save its value in a variable as shown below:

var q = getQueryParameter('q');

The application then takes this value and creates some HTML code. Note that user supplied value is never scrubbed of malicious input or validated in any way.

var html = '';

html += '<p>Your search query:</p>';
html += '<pre>' + q + '</pre>';
html += '<ul>';

This code is then rendered by the browser with the following command:

resultsEl.innerHTML = html;

You should always be on the look out for the “innerHTML” javascript function. This function allows you to directly modify HTML code on the fly and is seen in a lot of DOM based XSS instances.

This vulnerability is in a piece of javascript code but it looks very similar when looking at PHP, Python, or any other application. If you can identity it in one language you should be able to find it in another.

Conclusion

Depending on the engagement you are one you may have access to an applications source code. The vast majority of hunters tend to stick to black box testing but if you have an applications source code you should use it. Analyzing an applications source code will allow you find vulnerabilities you may have missed doing a black box testing as you will have a deep understanding of the code and will be able to find hidden functionalities and paths. Source code will allow you to quickly find vulnerabilities and you will have greater insights on how to bypass any filters they may have in place.

19 thoughts on “Source Code Analysis XSS”

  1. Great post. I was checking continuously this blog and I’m impressed! Very useful information specially the last part 🙂 I care for such info much. I was seeking this particular information for a long time. Thank you and best of luck.

Leave a Reply

Your email address will not be published. Required fields are marked *