What is a clear explanation of the difference between server XSS and client XSS?
I read the explanation on the site of OWASP, but it wasn't very clear for me. I know the reflected, stored en DOM types.
First, to set the scene for anyone else finding the question we have the text from the OWASP Types of Cross-Site Scripting page:
Server XSS
Server XSS occurs when untrusted user supplied data is included in an HTML response generated by the server. The source of this data could be from the request, or from a stored location. As such, you can have both Reflected Server XSS and Stored Server XSS.
In this case, the entire vulnerability is in server-side code, and the browser is simply rendering the response and executing any valid script embedded in it.
Client XSS
Client XSS occurs when untrusted user supplied data is used to update the DOM with an unsafe JavaScript call. A JavaScript call is considered unsafe if it can be used to introduce valid JavaScript into the DOM. This source of this data could be from the DOM, or it could have been sent by the server (via an AJAX call, or a page load). The ultimate source of the data could have been from a request, or from a stored location on the client or the server. As such, you can have both Reflected Client XSS and Stored Client XSS.
This redefines XSS into two categories: Server and Client.
Server XSS means that the data comes directly from the server onto the page. For example, the data containing the unsanitized text is from the HTTP response that made up the vulnerable page.
Client XSS means that the data comes from JavaScript which has manipulated the page. So it is JavaScript that has added the unsanitized text to the page, rather than it being in the page at that location when it was first loaded in the browser.
An ASP (or ASP.NET) page outputs a variable to the HTML page when generated, which is taken directly from the database:
<%=firstName %>
As firstName
is not HTML encoded, a malicious user may have entered their first name as <script>alert('foo')</script>
, causing a successful XSS attack.
Another example is the output of variables processed through the server without prior storage:
<%=Request.Form["FirstName"] %>
<script type="text/javascript">
function loadXMLDoc() {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 ) {
if(xmlhttp.status == 200){
document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
}
else if(xmlhttp.status == 400) {
alert('There was an error 400')
}
else {
alert('something else other than 200 was returned')
}
}
}
xmlhttp.open("GET", "get_first_name.aspx", true);
xmlhttp.send();
}
</script>
Note that our get_first_name.aspx
method does no encoding of the returned data, as it is a web service method that is also used by other systems (content-type
is set to text/plain
). Our JavaScript code sets innerHTML
to this value so it is vulnerable to Client XSS. To avoid Client XSS in this instance, innerText
should be used instead of innerHTML
which will not result in interpretation of HTML characters. It is even better to use textContent
as Firefox is not compatible with the non-standard innerText
property.
* code adapted from this answer.