其他分享
首页 > 其他分享> > web安全 - DOM based XSS 防御

web安全 - DOM based XSS 防御

作者:互联网

在javascript执行上下文中,可以访问和设置HTML, HTML属性, URL 和CSS,因此这些我们称为子上下文。

1.先进行HTML编码再进行javascript编码,将不受信任的数据插入执行上下文中的HTML子上下文之前。

有几种方法和属性可用于在javascript中直接呈现HTML内容。这些方法构成了执行上下文中的HTML子上下文。
如果这些方法提供了不受信任的输入,则可能会导致XSS漏洞。

xss漏洞

element.innerHTML = "<HTML> Tags and markup";
element.outerHTML = "<HTML> Tags and markup";
document.write("<HTML> Tags and markup");
document.writeln("<HTML> Tags and markup");

HTML 编码和javascript编码

var ESAPI = require('node-esapi');
element.innerHTML = "<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(untrustedData))%>";
element.outerHTML = "<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(untrustedData))%>";
document.write("<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(untrustedData))%>");
document.writeln("<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(untrustedData))%>");

2. 进行javascript编码,在将不受信任的数据插入HTML属性子上下文之前。

当在DOM执行上下文中时,只需要对不执行代码的HTML属性(事件处理程序,CSS和URL属性以为的属性)进行javascript编码。

javascript编码

var ESAPI = require('node-esapi');
var x = document.createElement("input");
x.setAttribute("name", "company_name");
x.setAttribute("value", '<%=ESAPI.encoder().encodeForJavascript(companyName)%>');
var form1 = document.forms[0];
form1.appendChild(x);

3. 将不可信的数据插入事件处理程序和javascript子上下文时

将动态数据插入javascirpt代码中尤其危险,javascript编码对javascript编码数据具有不同的语义。在许多情况下,
javascript编码不会阻止执行上下文中的攻击,因此建议是避免在这种情况下包含不受信任的数据。

无效的javascript编码

var x = document.createElement("a");
x.href="#";
// In the line of code below, the encoded data on the right (the second argument to setAttribute)
// is an example of untrusted data that was properly JavaScript encoded but still executes.
x.setAttribute("onclick", "\u0061\u006c\u0065\u0072\u0074\u0028\u0032\u0032\u0029");
var y = document.createTextNode("Click To Test");
x.appendChild(y);
document.body.appendChild(x);

在上面的例子中,属性名称是一个javascript事件处理程序,因此属性值被隐式地转换为javascript代码。因此在上述情况下
javascript编码并不能缓解基于DOM的XSS。

有效的javascript编码

<!-- Does NOT work  -->
<a id="bb" href="#" onclick="\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029"> Test Me</a>

使用Element.setAttribute(...)设置Dom属性的替代方法是直接设置属性,直接设置事件处理程序属性将允许javascript编码来
缓解基于DOM的XSS,但将不受信任的数据放入命令执行上下文中总是很危险的设计。

//The following does NOT work because the event handler is being set to a string.
//"alert(7)" is JavaScript encoded.
document.getElementById("bb").onclick = "\u0061\u006c\u0065\u0072\u0074\u0028\u0037\u0029";

//The following does NOT work because the event handler is being set to a string.
document.getElementById("bb").onmouseover = "testIt";

//The following does NOT work because of the encoded "(" and ")".
//"alert(77)" is JavaScript encoded.
document.getElementById("bb").onmouseover = \u0061\u006c\u0065\u0072\u0074\u0028\u0037\u0037\u0029;

//The following does NOT work because of the encoded ";".
//"testIt;testIt" is JavaScript encoded.
document.getElementById("bb").onmouseover = \u0074\u0065\u0073\u0074\u0049\u0074\u003b\u0074\u0065\u0073
                                            \u0074\u0049\u0074;

//The following DOES WORK because the encoded value is a valid variable name or function reference.
//"testIt" is JavaScript encoded
document.getElementById("bb").onmouseover = \u0074\u0065\u0073\u0074\u0049\u0074;

function testIt() {
   alert("I was called.");
}

javascript基于国际标准,因此javascript编码除了支持替代字符串表示(字符串编码)外,还支持编程结构和变量中的国际字符。

 for(var \u0062=0; \u0062 < 10; \u0062++){
     \u0064\u006f\u0063\u0075\u006d\u0065\u006e\u0074
     .\u0077\u0072\u0069\u0074\u0065\u006c\u006e
     ("\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064");
 }
 \u0077\u0069\u006e\u0064\u006f\u0077
 .\u0065\u0076\u0061\u006c
 \u0064\u006f\u0063\u0075\u006d\u0065\u006e\u0074
 .\u0077\u0072\u0069\u0074\u0065(111111111);
 var s = "\u0065\u0076\u0061\u006c";
 var t = "\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029";
 window[s](t);

4. javascript编码,在将不可信任的数据插入css属性子上下文时

从CSS上下文执行javascript需要将 javascript:attackCode()传递给CSS url()方法或调用CSS expression() 方法传递
javascipt代码。目前从执行上下文调用expression()函数已被禁用,为了减轻CSS url()方法的影响,请确保对传递给CSS
url()方法的数据进行URL编码。

URL编码与javascript编码

var ESAPI = require('node-esapi');
document.body.style.backgroundImage = "url(<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForURL(companyName))%>)";

5. 先进行URL编码,再进行javascript编码,再将不受信任的数据插入URL属性子上下文时

URL编码和javascript编码

var ESAPI = require('node-esapi');
var x = document.createElement("a");
x.setAttribute("href", '<%=ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForURL(userRelativePath))%>');
var y = document.createTextElement("Click Me To Test");
x.appendChild(y);
document.body.appendChild(x);

6. 使用安全的javascript函数或属性填充DOM

使用不受信任的数据填充DOM最基本的安全方法是使用安全赋值属性textContent。

<script>
element.textContent = untrustedData;  //does not execute code
</script>

7. 修复DOM based XSS漏洞

修复基于DOM的XSS漏洞的最佳方法是使用正确的输出方法(接收器)。

<b>Current URL:</b> <span id="contentholder"></span>
...
<script>
document.getElementById("contentholder").textContent = document.baseURI;
</script>

标签:XSS,based,编码,javascript,u0074,u0065,web,var,document
来源: https://www.cnblogs.com/xiaodi-js/p/16700804.html