[点晴永久免费OA]浅淡XSS跨站脚本攻击的防御方法
当前位置:点晴教程→点晴OA办公管理信息系统
→『 经验分享&问题答疑 』
一、HttpOnly属性 为Cookie中的关键值设置httponly属性,众所周知,大部分XSS(跨站脚本攻击)的目的都是通过浏览器的同源策略,来获取用户Cookie,从而冒充用户登陆系统的。 如果为Cookie中用于用户认证的关键值设置httponly属性,浏览器将会禁止js通过同源策略访问cookie中设有httponly属性的信息,因此以劫持用户认证cookie为目的XSS攻击将会失败。 但很明显,只为cookie中的值设置Httponly是不够的,因为XSS攻击并不是只能获取用户COOKIE,它还可以窃取用户浏览器信息,模拟用户身份执行操作等等。(具体内容详见:《白帽子讲Web安全》) 二、对用户输入进行检查——XSS filter XSS filter是在用户提交数据时获取变量,并进行XSS 过滤的。此时的XSS filter只对用户输入数据进行XSS检查,并没有结合渲染页面的HTML代码。 所以针对XSS filter需要强调两点: 1.XSS filter对语境的理解并不完整(比如:无法针对输出点位置进行合适的XSS过滤。所以有时可能会造成遗漏、破坏原有语义等后果) 2.XSS filter是在服务器进行URL解码之前生效的,所以要考虑URL编码绕过的问题。(比如XSS filter过滤了<script>标签,但如果用户输入的是经过URL编码后的<script>标签:%3C%73%63%72%69%70%74%3E,这样就饶过了原本的XSS filter检测) 三、对用户输出进行检查——安全的编码函数 (1)HtmlEncode 一般来说,在进行XSS防御的时候,至少需要将以下字符做转换处理: 转换前 转换后 & & < < > > " " '' ' / / (2)JavascriptEncode javascriptEncode的编码方式和HtmlEncode有所不同,它使用 \ 对特殊字符进行转义。 常用的JavaScript编码函数为:escapeJavascript() 该函数的功能为:将 ‘ ” < > \ & # 这些个危险字符进行转义。 举一个《白帽子讲Web安全》里的例子 var x=1;alert(2); var y="1;alert(2)"; JS环境内,第一行的弹窗代码会被执行,第二行则会是安全的,即使攻击者想要尝试闭合",输入的"也会被JavaScript编码转义为\"。这样攻击者相要绕过"的封锁也会十分苦难。 不过这里需要注意: 1.如果页面使用的是GBK编码,可能会被攻击者利用类似宽字节注入的方式绕过。 2.用户的输出如果是在标签内,则要求JavascriptEncode的变量输出点一定要被引号包裹。 如果用户输出点太多,导致开发人员无法针对性的对用户输出进行编码、转义。则可以使用更严格的Javascriptencode函数,使用函数将除了数字、字母之外的所有字符通通都以"\xHH"的方式进行16进制编码。 接下来需要介绍一个很重要的东西,是我当天总结的重中之重!!!!!! 相信很多初学者会和我一样,非常好奇为什么会有Htmlencode和JavaScriptEncode两种编码方式,从功能上来看都可以抵御XSS攻击,但为什么要将两者分开使用。这是因为浏览器有两套不同的自解码机制。 1、HTML的自解码机制 浏览器在解析HTML标签属性值内的代码前,会先对下列两种编码进行解码,然后再对属性中的代码进行解析。 (1)、进制解码:&#xH;(十六进制格式)、&#D;(十进制格式)。编码中最后的分号(;)可以不要。且16进制中用来表示10~15的a~f对大小写不敏感 例子: <iframe src=''javascript:alert`1`''></iframe> 也可写成 <iframe src=''javascript:alert`1`''></iframe> (2)、HTML 实体编码 例子: <input type="button" value="test" οnclick="document.write(''<img src=@ οnerrοr=alert(123) />'')" /> 也可写成 <input type="button" value="test" οnclick="document.write(''<img src=@ οnerrοr=alert(123) />'')" /> 2、JavaScript 自解码机制 (1)、Unicode 形式:\uH(十六进制)。 (2)、普通十六进制:\xH。 (3)、纯转义:\''、\"、\<、\>这样在特殊字符之前加\进行转义。 注:以上三种规则仅在通过JS更改HTML DOM树时才适用( 例如document.write() document.getelementbyid().innerhtml=""),直接在<script>标签内使用上述编码,自解码规则不生效。 例子: <input type="button" id="exec_btn" value="exec" /> <script> function $(id){return document.getElementById(id);}; $(''exec_btn'').onclick = function(){ document.write(''<img src=@ οnerrοr=alert(123) />'');//改代码可执行、可弹窗 //在JS执行前会先将上面这行代码先解码为:document.write(''<img src=@ οnerrοr=alert(123)/>''); }; </script> 但如果直接在<script>标签内使用该编码,则自解码机制不生效。 例如: <script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029</script> 其中上述\u编码内容为alert(123),但该代码并没有更新DOM树,所以不会弹窗。 四、针对不同的输出点使用合适的编码方式 1.输出点在HTML标签之间 如<div>输出点</div> 攻击者如果想要构造XSS语句并执行,需要构造一个能执行脚本的环境。示例如下: <div><script>alert`1`</script></div> 此处适合使用HtmlEncode,将攻击者输入的<>编码为<> 使得攻击者无法构造JS环境,导致XSS失败。 2.输出点在HTML属性中输出 <div id=''111'' name="输出点"></div> 普通攻击者尝试的方法为将name属性的双引号闭合,然后再构造xss语句。 <div id=''111'' name=" "><script>alert`1`</script><""></div> 此处同样推荐使用HtmlEncode 3.输出点在<script>标签中 在<script>标签中输出时,首先应该确保输出的变量在引号中,例如 <script> var x="输出点"</script> 此处的防御思想是:使攻击者无法闭合标签,导致无论输入什么参数都会被浏览器当作字符串处理。 此处应使用JavascriptEncode。 4.在事件中输出 在事件中输出和在<script>标签中类似 <a href=# οnclick="funcA(''输出点'')">超链接</a> 攻击方法举例: <a href=# οnclick="funcA('''');alert`1`;//'')">超链接</a> 5.在CSS中输出 因为对CSS不太熟悉,所以此部分暂不介绍。 但根据白帽子一书中的介绍,推荐使用 encodeForCSS()函数 6.在地址栏中输出 在地址栏中的输出比较复杂,但总结起来相较于前面有两点需要注意: (1).输出点在路径或者参数中。 <a href="http://www.test.com/test=输出点">test</a> 攻击者可按照如下方式构造payload <a href="http://www.test.com/?test=" οnclick=alert(1) "">test</a> 此处的防御方法为使用URLEncode,是代码变成下面这样 <a href="http://www.test.com/?test=%22%20%6F%6E%63%6C%69%63%6B%3D%61%6C%65%72%74%28%31%29%20%22">test</a> (2).输出点为整个URL。 <a href="输出点">test</a> 此时就不能单纯的使用URLEncode来抵御XSS攻击了,因为协议和域名部分是不能够进行URL编码的,不然会改变原有的语意。 此处攻击者可能会构造伪协议实施攻击 <a href="javascript:alert(1);">test</a> 能被攻击者利用的伪协议有:javascript,vbscript,dataURL dataURL这个伪协议是Mozila所支持的,能够将一段代码写在URL里 <a href="data:text/html;base64,PHNjcmlwdD5hbGVydGAxYDwvc2NyaXB0Pg==">test</a> 这段base64字符串解码后就是<script>alert`1`</script> 所以此处的防御方法应为: <script> <style> <a>等标签的src和href属性必须以白名单的方式强制为 http://或https://开头,并且不能有10进制和16进制编码的字符串。(此处的做法是防止攻击者使用伪协议进行XSS攻击) 7.DOM型XSS的防御 如果用户的输出点在<script>之间时,须先进行一次JavaScriptEncode,在通过document.write等方式输出到HTML页面时,如果输出点为事件或者脚本,须再进行一次JavaScriptEncode,如果输出点为HTML的内容或者属性,则需要做一次Htmlencode。 五、总结 输出到HTML标签内或者之间,需使用HtmlEncode编码进行防御。 输出到JavaScript标签内或者之间,需要进行JavaScriptencode来进行防御。 抵御DOM型XSS,当使用document.write等方法向HTML页面内输入内容时,如过输出点在JS环境内就要再进行一次JavascriptEncode,如果输出点在HTML标签内,则再进行一次HtmlEncode。 以上内容大部分参考《白帽子讲Web安全》一书。 关于XSS进阶教程强烈推荐大家看我的另一篇博客,事我很认真,一点点总结出来的,但访问量很少。。。链接如下:
该文章在 2020/4/8 11:57:26 编辑过 |
关键字查询
相关文章
正在查询... |