ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

web安全 - DOM based XSS 防御

2022-09-16 18:01:58  阅读:379  来源: 互联网

标签:XSS based 编码 javascript u0074 u0065 web var document


在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编码不会阻止执行上下文中的攻击,因此建议是避免在这种情况下包含不受信任的数据。

  • setAttribute(name_string, value_string)方法很危险,因为它隐式地将value_string强制转化为name_string的DOM属性数据类型。
    其他将代码作为字符串类型的方法也有类似的问题(setTimeout, setInterval, new Function, eval 等)。

无效的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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有