Skip to content
Kurisu
Go back

六环链调试笔记:同一个 SQL 注入点,从盲注读到 RCE 写入

之前写过 ThinkPHP 的 POP 链调试,这次换 WordPress——一个让我调了最久的链。这篇是自己的调试笔记,源码逐行核实过(WordPress 6.9.4,本地授权靶机)。一句话总结:RCE 不是新漏洞,是同一个 batch 错位 + 同一个注入点,从”读”升级成”写”。上一篇(盲注 check)是把注入当”眼睛”偷看数据;这一篇是把它当”手”伪造一行数据,再借 WordPress 自己的机制把这行假数据”洗”成真权限。

0x01 承接:同一个错位,换三样东西

错位机制在 check 篇已经讲过:batch 路由按 matches[] 匹配 handler,探针让 matches[] 短一格 → 载体请求偷到下一个路由的 handlerauthor_exclude 参数原样进 SQL。这次从读变写,只改三处:

check(只读)RCE(写)
注入语句SELECT IF(...SLEEP...)1) AND 1=0 UNION ALL SELECT 伪造行... -- -
内层载体/wp/v2/users?.../wp/v2/widgets?author_exclude=...&per_page=-1&orderby=none&context=view
额外请求追加 2 次 POST /wp/v2/users(创建管理员)

两个关键开关:

外层还有一次同样的错位:[PRIMER, postsCarrier, /batch/v1]/batch/v1 只是”献出 handler 的牺牲品”,真正执行内层批的是它前面的载体——机制是同一个,套了两层。

0x02 六环总览

环1  SQL 注入 → 内存对象投毒      UNION 伪造行被 get_results() 取回,
                                  update_post_caches() 写进内存缓存(可信!)
环2  oEmbed 缓存 → 持久化写入      oEmbed 渲染时把伪造字段经 wp_update_post
                                  "稀疏合并"写进数据库 ← 假数据落地成真
环3  层级循环检测 → 状态转换        伪造的父子关系触发修环,post 状态 future → publish
环4  Customizer 发布 → 权限提升     发布流程把当前用户切成管理员
环5  parse_request 动态钩子 → REST 重入   第二次修环触发钩子,重入 REST API
环6  创建管理员 → webshell → RCE    管理员身份 POST /wp/v2/users 建号,登录传马

设计上最巧的是环 2 的 7 条毒化记录一次注入(1 条 seed + 一组 changeset,含两条父子环):后续每一环需要的”数据形态”都在这一次注入里预置好了,后面全靠 WordPress 自己的机制接力——攻击者只写一次,平台替他洗白六次

调试上我的经验两条:

0x03 check vs RCE 对照(收尾)

维度check 盲注RCE 六环
注入的角色眼睛(读)手(写)
关键语句SELECT IF(...SLEEP...)UNION ALL SELECT 伪造行
剩余攻击面数据库内容内存缓存 → 数据库 → 权限系统
调试重心响应时间差25 个断点的状态传递

这条链给我的最大启发:注入点的价值上限不取决于注入本身,取决于取回数据的代码怎么用——update_post_caches 无条件信任查询结果的那一刻,数据库的边界就成了权限系统的边界。

相关旧文


Share this post:

Previous Post
AI Agent 渗透测试:MCP、工具调用与一次黑客松的启示
Next Post
应急响应实战与项目复盘:从阿里云入侵排查到 AKSK 接管云上 341 台服务器