[关闭]
@garygchai 2016-05-07T11:57:53.000000Z 字数 4897 阅读 3831

前端安全之XSS

XSS


前言

很早就想写一篇关于跨站脚本攻击的文章(XSS),因为之前看到个别组员毫不犹豫地使用innerHTML这样的方式输出用户输入的内容,我们网站本身也发生过几次xss注入的安全事故,这些事情也暴露了我们整个团队的安全意识不够吧。这几天正好看了一些关于xss的文章,也算做一些笔记吧。

XSS简介

跨站脚本攻击,英文全称是Cross Site Script,按理说缩写应该是CSS吧,据说是为了和CSS(Cascading Style Sheet)有所区别,才叫XSS的!XSS攻击,通常是指黑客通过html注入篡改了网页,插入了恶意的脚本,从而在用户浏览器网页的时候,控制用户浏览器的一种攻击。

XSS分类

XSS通常都分为3类:反射型XSS、存储型XSS、Dom Based XSS,但是不止,还有各种变种,我还听过mXSS,UXSS等等。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>反射型XSS攻击</title>
  5. <meta charset="utf-8"/>
  6. </head>
  7. <body>
  8. <h1>
  9. Hello <span id="value"></span>
  10. </h1>
  11. <script type="text/javascript">
  12. var hash = location.hash.slice(1);
  13. if (hash) {
  14. document.getElementById('value').innerHTML = hash;
  15. }
  16. </script>
  17. </body>
  18. </html>

此时,我们用innerHTML输出链接的内容就让攻击者有了可乘之机,攻击者通过构造的这样的url:http://localhost:3000/index.html#<img src="1" onerror="alert(document.cookie)">,发给用户用户点击链接,就可以做到XSS攻击。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Dom Based型XSS攻击</title>
  5. <meta charset="utf-8"/>
  6. </head>
  7. <body>
  8. <div>
  9. <input type="text" id="input"></input>
  10. <input type="button" id="btn" onclick="test()" value="生成链接">
  11. <div id="link"></div>
  12. </div>
  13. <script type="text/javascript">
  14. function test() {
  15. var link = document.getElementById('input').value;
  16. document.getElementById('link').innerHTML = '<a href="'+link+'">测试链接</a>';
  17. }
  18. </script>
  19. </body>
  20. </html>

Dom Based型XSS

我们本意是想生成一个可点击的链接,通过innerHTML将用户输入的链接写入页面中,这段代码就存在Dom Based XSS。我们在输入框输入:
" onclick=alert(/xss/)//,输入之后点击生成的链接是这样: <a href="" onclick="alert(/xss/)//"">测试链接</a>,第一个双引号是为了闭合href,然后插入一个onclick事件,//是为了注释第二个双引号。点击“测试链接”,脚本就会被执行:
Dom Based型XSS

还可以通过闭合掉<a>标签,然后插入脚本的方式做到XSS攻击:
输入"><img src=1 onerror=alert(/xss/)//,dom就会变为:<a href=""><img src="1" onerror="alert(/xss/)//"">测试链接</a>

这种攻击类型我们网站就曾经发生过,用户发现自己会自动给别人送礼,就是攻击者发现我们socket服务器没有对用户昵称进行校验和转义,攻击者通过闭合我们的nickName属性,构造送礼脚本就做到Dom Based XSS攻击。

XSS的危害

XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,攻击者可以做到任何javascript可以做到的任何事情。攻击一般会做哪些事情呢?

只要攻击者能力足够强大,想象力足够丰富,XSS能做的事情远超过我们的想象。

XSS的构造技巧

构造技巧,说到底就是利用网站漏洞想办法在用户浏览的网页中植入攻击脚本。掌握一些XSS常见的攻击技巧,对我们在开发过程中避免被攻击有重要意义,知道人家怎么攻,才知道自己该怎么防嘛。说说我所知道的一些技巧:

JSunicode:
\u003c\u0069\u006d\u0067\u0020\u0073\u0072\u0063\u003d\u0031\u0020\u006f\u006e\u0065\u0072\u0072\u006f\u0072\u003d\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029\u003e
JSunicode
JS8Hex:
\74\151\155\147\40\163\162\143\75\61\40\157\156\145\162\162\157\162\75\141\154\145\162\164\50\61\51\76
JS8Hex

XSS防御

解决XSS安全问题基本上就下面几条原则:

  • 输入检查 用户输入的内容,过滤其中的特殊字符,如",',<,>,&;
  • 输出检查 输出用户输入的内容时,对其中不含的特殊字段进行转义,如<转为&lt;,> 转为 &gt;;
  • 谨慎使用eval,innerHTML等js方法或属性
  • 设置HttpOnly防止JS读取Cookie
Html characters Html Encode Entities
& &amp;
< &lt;
> &gt;
" &quot;
空格 &nbsp;

实现方式可以引入第三方库,或者类似下面这样处理方法:

  1. function htmlEncode(c) {
  2. switch(c) {
  3. case '&':
  4. return"&amp;";
  5. case '<':
  6. return"&lt;";
  7. case '>':
  8. return"&gt;";
  9. case '"':
  10. return"&quot;";
  11. case ' ':
  12. return"&nbsp;";
  13. default:
  14. return c +"";
  15. }
  16. }

不要在页面中插入任何不可信数据,除非你已经确保这些数据已经进行了安全编码。下面列举一些常见的XSS漏洞场景,看看如何防御。
场景1:
通过 JavaScript 从 Cookie、URL、页面或数据库中获取数据,然后在页面上展示。

  1. <div id="xss">
  2. </div>
  3. <script>
  4. var a = location.hash.slice(1);
  5. document.getElementById("xss").innerHTML = b;
  6. </script>

从 Cookie、URL、页面或数据库中获取的数据,有可能包括恶意攻击的代码;在展示之前,需要使用 JavaScript 编写转义函数,将获取的数据中的 ",',<,>,& 进行HTML转义。

场景2:
直接在页面中输出不可信数据时,要确保对特殊字符有正确的转义。比如:

  1. <script>
  2. var html = '<div>title is "{{$var}}".</div>';
  3. document.write(html);
  4. //或node.innerHTML = html;
  5. </script>
  1. <script>
  2. var html = '<a href="{{$var}}">test</a>';
  3. document.write(html);
  4. //或node.innerHTML = html;
  5. </script>
  1. <script>
  2. var html = '<input type="button" onclick="add(' + {{$var}} + ')">';
  3. document.write(html);
  4. //或node.innerHTML = html;
  5. </script>

以上各类情况,都要确保对特殊字符有正确的转义。

  1. - < 转成 `&lt;`
  2. - > 转成 `&gt;`
  3. - ' 转成 `&#39;`
  4. - " 转成 `&#34;`

我们通过JS是无法读取得到的:
cookie search

结语

在开发过程中,不管是做前端还是后端的编码,安全意识很重要,需要时刻提醒自己,在输出任何来自不可信数据的时候有没有被注入的风险,只有才能让我们远离xss攻击。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注