首先,要为其他任何人发现问题设置场景,我们将从OWASP跨站点脚本类型页面中获取文本:
服务器XSS
当不受信任的用户提供的数据包含在服务器生成的HTML响应中时,就会发生服务器XSS.此数据的来源可以来自请求,也可以来自存储的位置.因此,您可以同时拥有Reflected Server XSS和Stored Server XSS.
在这种情况下,整个漏洞都在服务器端代码中,浏览器只是呈现响应并执行嵌入其中的任何有效脚本.
客户端XSS
当不受信任的用户提供的数据用于使用不安全的JavaScript调用更新DOM时,会发生客户端XSS.如果JavaScript调用可用于将有效的JavaScript引入DOM,则认为它是不安全的.此数据的来源可以来自DOM,也可以由服务器发送(通过AJAX调用或页面加载).数据的最终来源可能来自请求,也来自客户端或服务器上的存储位置.因此,您可以同时拥有Reflected Client XSS和Stored Client XSS.
这将XSS重新定义为两类:服务器和客户端.
服务器XSS意味着数据直接从服务器进入页面.例如,包含未清理文本的数据来自构成易受攻击页面的HTTP响应.
客户端XSS意味着数据来自操纵页面的JavaScript.因此,JavaScript将未经过处理的文本添加到页面中,而不是在首次加载到浏览器中时位于该位置的页面中.
ASP(或ASP.NET)页面在生成时向HTML页面输出一个变量,该变量直接从数据库中获取:
<%=firstName %>
Run Code Online (Sandbox Code Playgroud)
由于firstName不是HTML编码,恶意用户可能已输入其名字<script>alert('foo')</script>,导致成功的XSS攻击.
另一个例子是在没有事先存储的情况下通过服务器处理的变量输出:
<%=Request.Form["FirstName"] %>
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
请注意,我们的get_first_name.aspx方法不对返回的数据进行编码,因为它是一种Web服务方法,也被其他系统使用(content-type设置为text/plain).我们的JavaScript代码设置innerHTML为此值,因此容易受到客户端XSS的攻击.为了避免在这种情况下innerText使用Client XSS,应该使用innerHTML它而不是导致HTML字符的解释.使用它甚至更好,textContent因为Firefox与非标准innerText属性不兼容.
*代码改编自这个答案.