跨站脚本攻击
简介:
XSS (Cross Site Scripting),即跨站脚本攻击,是一种常见于 Web 应用中的计算机安全漏洞。恶意攻击者往 Web 页面里嵌入恶意的客户端脚本,当用户浏览此网页时,脚本就会在用户的浏览器上执行,进而达到攻击者的目的。比如获取用户的 Cookie、导航到恶意网站、携带木马等。借助安全圈里面非常有名的一句话:*所有的输入都是有害的。*这句话把 XSS 漏洞的本质体现的淋漓尽致。大部分的 XSS 漏洞都是由于没有处理好用户的输入,导致恶意脚本在浏览器中执行。任何输入提交数据的地方都有可能存在 XSS。
分类:
按漏洞成因:
- 反射型
- 存储型
- DOM型
按输出位置:
- 输出在HTML属性中
- 输出在 CSS代码中
- 输出在JavaScript 中
反射型
反射型XSS也被称为非持久性XSS,是现在最容易出现的一种XSS漏洞。当用户访问一个带有XSS代码的URL请求时,服务器端接收数据后处理,然后把带有XSS代码的数据发送到浏览器,浏览器解析这段带有XSS代码的数据后,最终造成XSS漏洞。这个过程就像一次反射,故称为反射型XSS。
非持久型XSS漏洞实际上大多数攻击数据是包含在URL中的,类似这样的:
http://www.xxxxx.com/test.asp?hi=[code]
。需要用户的浏览器访问到这个URL恶意代码才执行,攻击者一般会把URL发给用户让用户通过浏览器去访问。不过URL里面带有稀奇古怪的代码确实有点奇怪,为了掩人耳目,攻击者可以发一个看起来没问题的URL,再通过那个页面跳转到恶意的URL,甚至也可以让一个域名转向到恶意URL,把那个域名发给用户。
原型代码:
<?php
echo 'your input:' - $_GET[ 'input ' ];
?>
客户端输入的 input值未经任何过滤便直接输出,所以攻击者可以提交:http:/ /example.com/xss.php?input=<script>alert ( /xss/)</script>
来进行攻击。
存储型
存储型XSS又被称为持久性XSS,存储型XSS是最危险的一种跨站脚本。允许用户存储数据的Web应用程序都可能会出现存储型XSS漏洞,当攻击者提交一段XSS代码后,被服务器端接收并存储,当攻击者再次访问某个页面时,这段XSS代码被程序读出来响应给浏览器,造成XSS跨站攻击,比如我在某个论坛发帖的时候,论坛没有对传入的HTML作处理,那么我就可以发一个帖子内容包含<script>[code]</script>
的帖子,然后就守株待兔地等着来看帖子的人执行恶意脚本了。持久型XSS漏洞是把恶意脚本存储到了数据库,访问页面的时候完全没有预兆,这就是存储型XSS。
存储型XSS与反射型XSS、DOM型XSS相比,具有更高的隐蔽性,危害性也更大。它们之间最大的区别在于反射型XSS与DOM型XSS执行都必须依靠用户手动去触发,而存储型XSS却不需要用户手动去触发。
DOM型
DOM的全称为Document Object Model,即文档对象模型,DOM通常用于代表HTML、XHTML和XML中的对象。使用DOM可以允许程序和脚本动态地访问和更新文档的内容、结构和样式。
通过JavaScript可以重构整个HTML页面,而要重构页面或者页面中的某个对象,JavaScript就需要知道HTML文档中所有元素的“位置”。而DOM为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。根据DOM规定,HTML文档中的每个成分都是一个节点。基于DOM型的XSS是不需要与服务器端交互的,它只发生在客户端处理数据阶段。
输出在HTML中
原型如下:
<input name="user" value="ii your input }}”/>
XSS 攻击Payload输出在HTML属性中时,攻击者需要在闭合相应的HTML属性后注人新属性,或者在闭合标签后直接注入新标签,如输入:
" onclick="alert ( /xxs/)
就闭合了value属性,并且加入新的属性onclick。
或者输入:
"><script>alert(/xss/ )</script>
这样就直接闭合了input标签而且注入了新的标签。
输出在CSS代码中
原型如下:
<style type="text/css">
body {
color: your input ;
}
</style>
XSS攻击Payload输出在 CSS代码中时,攻击者需要闭合相应的CSS代码,如输入:
#000 ; background-image: ur1( 'javascript:alert ( /xss/) ')
闭合前面的color属性,注入 background-image属性
输出在JavaScript中
原型如下:
<script>
var name='{{ your input }}';
</ script>
XSS攻击Payload输出在Javascript代码中时,攻击者需要闭合相应的Javascript代码,如输入:
'+alert(/xss/)+'
闭合前面的单引号,注入攻击代码,就变成了
<script>
var name=' '+alert ( / xss/)+'';
</ script>
XSS的特性
XSS的核心:获取别人的cookie来登陆别人的账号。
要展开XSS攻击,需要在目标网站上触发指定的JS语句。攻击者主要通过以下三种触发方式展开攻击:
1、标签法(又叫XML法) ,比如:
<script>alert(1)</script>
2、伪协议法,比如:
<a href=Javascript:alert(1)>123</a>
3、事件法,比如:
</img src=# onerror=alert(1) />
常用的on事件有:
onerror
onload
onfocus
oninput
防护和绕过
1.特定标签过滤
部分开发者认为过滤掉危险标签(如script、iframe等)就会导致无法执行脚本,但其实任何一种标签,无论是否合法,都可以构造出XSS代码,比如如下代码:
<not_real_tag onclick="alert(/xss/) ">click me</not_real_tag>
如果输出点在HTML标签的属性中或在Javascript代码中,那么攻击者可以简单地闭合、拼接属性或Javascript 代码而不需要引入任何新标签就可以执行XSS代码。
同时,HTML5也带来了部分新标签,容易被开发者忽略,如video标签。总而言之很多标签都可以构造出攻击代码。
2.事件过滤
很多时候,开发者会过滤掉许多HTML标签的事件属性,这时需要对所有可利用的事件属性进行遍历,测试一下开发者是否有所遗漏。常用的事件属性如下,测试时可使用Burp或自行编写脚本进行Fuzz:
3.敏感关键字(字符)过滤
(1)字符串拼接混淆
关键字过滤大部分是针对敏感变量或函数而进行的,如cookie、eval等,这部分的过滤可通过字符串拼接、编码解码等方法进行绕过。
例如:windowp['alert'](/xss/)
就可以变成windowp['al'+'ert'](/xss/)
因为里面是个字符串的形式。
我们还可以利用base64编码,btoa函数可以将字符串编码为Base64字符串,atob函数可以将Base64字符串还原,比如:
window[ atob ( "Ywxl"+"cnQ=" )](/xss/)
就相当于windowp['alert'](/xss/)
(2)编码解码
基于字符串的代码混淆不仅可以通过字符串拼接的方式来实现,还可以通过各种编码、解码来实现。XSS漏洞中常用的编码方式包括:
- HTML进制编码:十进制(a)、十六进制(a)
- CSS进制编码:兼容HTML 中的进制表现形式,十进制、十六进制
- Javascript进制编码:八进制(\141)、十六进制(\x61 )、Unicode编码(\u61 ),ASCII (String.
- fromCharCode(97))
- URL编码:%61
- JSFuck编码
这里值得一提的是JSFuck编码,它可以只使用“[O!+”6个字符来编写Javascript程序,在某些场景下具有奇效。
(3)location.*、window.name
既然开发者会对输入的敏感关键字进行过滤,那么可以将XSS代码放置于其他不被浏览器提交至服务端的部分,如 location.*、window.name等处,location.*的构造如下:
http://example.com/xss.php?input=<input onfocus=outerHTML=decodeURI(location.hash)>#<img src=x onerror=alert( /xss/)>
window.name的构造页面如下:
<iframe src="http://example . com/xss.php?input=83Cinput%20onfocus=location=windowname%3E"name="javascript:alert (/xss/) "></iframe>
利用location对象结合字符串编码可以绕过很多基于关键字的过滤。也有一部分关键字过滤是针对敏感符号的过滤,如括号、空格、小数点等。
(4)过滤“.”
在JavaScript中,可以使用with 关键字设置变量的作用域,利用此特性可以绕过对“.”的过滤,如:
with(document )alert ( cookie ) ;
(5)过滤“(”
在JavaScript中,可以通过绑定错误处理函数,使用throw关键字传递参数绕过对“()”的过滤,如:
window.onerror=alert; throw 1;
(6)过滤空格
在标签属性间可使用换行符0x09、0x10、0x12、0x13、OxOa等字符代替空格绕过过滤,如:
http://example.com/xss.php?input=<img%0asrc=x80aonerror=alert ( /xss/)>
在标签名称和第一个属性间也可以使用“/”代替空格,如:
<input/onfocus=alert(/xss/)>
( 7 )svg 标签
svg内部的标签和语句遵循的规则是直接继承自xml而不是html,区别在于svg内部的script标签中可以允许存在一部分进制或编码后的字符(比如实体编码)
http://example.com/xss . php?input=1"><svg><script>alert%26823x28;1号26%23x29</script></svg>
4.字符集编码导致的绕过
pikachu靶场练习
反射型xss(get)
界面展示:
这里我们看到界面是一个输入框,并且输入的内容会在url上显示,说明是GET请求的传参。我们可以直接在url上攻击。我们尝试简单的让它弹出框框试试,输入<script>alert("123")</script>
。
但是这我们注意到,这个输入框有长度限制,不能直接输入上面那一大串,于是我们对长度进行绕过。
这里提供以下几种方式:
- 直接在url中传参数,
?message=<script>alert("123")</script>&submit=submit&submit=submit
- F12调出控制台,使用左上角的选择器,找到框框那里,可以看到maxlength=20的代码,双击选中把这个20改了再试以下就行。这里的修改只能生效一回合,刷新后就需要重新修改了。
- 使用burpsuite抓包,再进行传参。在我们使用这种方式传参后,可以在返回包里直接找到我们传入的语句,原模原样,由此也可以判断出有xss漏洞。
反射型xss(post)
这一关先要用admin账号登录再进行操作。也就是给咱体验体验
如果要获得cookie,那么就输入payload:<script>alert(document.cookie)</script>
这样就得到了admin的cookie
存储型xss
本关页面有一个留言板,输payload:<script>alert(document.cookie)</script>
就能弹出cookie。并且可以看到留言表中有一条数据了(虽然该数据不显示,但是有删除按钮)。
并且我们也能在抓包的返回包中找到我们输入的代码。
并且存储型xss还会导致一个额外的结果,就是当我们使用其他浏览器中来到本关页面,也出现了同样的弹框。说明存储型XSS能危害所有访问受影响页面的用户。
DOM型xss
这一关就考验到了简单的绕过技巧,这题你只要F12 打开查看源码就能发现它把源码都给你了
也告诉你绕过方法了,事实上一般的ctf题如何绕过要靠你自己去试。
DOM型xss-x
这俩题差不多,只不过设定了要想触发你输入的东西,必须点击下面的超链接。也就是说代码藏在了a标签里面
xss盲打
这题要告诉我们的是,当我们在前端没有发现自己注入的代码执行时,有可能在后台执行了。本关我们登录后台,在前端注入payload再刷新后台就会发现,我们的后端页面弹出了框框。查看代码发现我们输入的内容确确实实传输到了后台页面里面。
xss之过滤
这题考验简单的过滤,因为我们发现注入<script>alert("123")</script>
后直接被过滤掉了,那我们换做事件触发方式使用<img src="#" οnerrοr=alert(document.cookie)>
就可以正常注入了
xss之htmlspecialchars
这一关会发现注入的内容完全输出到了页面里面,并且变成一个超链接,因此考虑到这里有一个a标签。因此本关我们只需要闭合a标签的属性再使用onclick触发就行了。
但是这关尝试了闭合a标签发现不行,原因是过滤了尖括号,但是由于没过滤掉单引号所以我们可以闭合标签属性。
xss之href输出
这一题发现左右尖括号和单引号都被html编码了,因此我们选择伪协议触发法,使用payload:
javascript:alert(document.cookie)
xss之js输出
这题将我们输入的内容放到了<script>
标签内了,并且没有被编码。于是我们闭合该字段,再直接写入script代码就行了。输入payload:';alert(123);//