Files
reverse-skill/skills/field-journal/2026-08-01_pentest-encryption-oracle-public-template-sql-admin-takeover.md
T
yhc 5906d74b2d chore: remove stale evolution counters, unify capability/tool counts to source of truth
- Remove hand-maintained <!-- [进化统计] --> comments from 12 journal/seed
  files (counters were contradictory: 21/7/8/11/12/94/18; template keeps the
  placeholder for future guidance)
- Capability lists in RULES.md / RULES_zh.md / skills/SKILL.md now match
  bootstrap-manifest.json (24 capabilities: add jeb-pro, reqable-mcp, bkcrack)
- Burp tool count in RULES_zh.md: 63 -> 78 (verified against getToolList()
  in burp-mcp-full/McpHttpServer.java; RULES.md already said 78)
2026-08-10 19:11:06 +08:00

8.1 KiB
Raw Blame History

2026-08-01 通用加密 oracle 与公开模板解析器组合成 SQL 管理员接管

场景分类

Web / API / 渗透测试 / .NET CMS / 权限组合 / SQL 注入 / 管理员接管

目标概述

对一个开源 .NET CMS 做高危优先源码审计时,闭合“受限管理员通用加密功能 + 无认证密文模板消费者 + 危险模板标签”组合链。单独看似低影响的字符串加密权限,可为任意恶意模板生成系统有效密文;公开搜索动作把“可解密”误当“可信”,最终以 CMS 数据库账号执行原始 SQL 并重置合成管理员口令。

完整执行链路

  1. 先把既有数据泄露归档设为 baseline,根因指纹不再计入“挖新的”停止门。
  2. 从所有 Encrypt/Decrypt/Sign/Verify 入口建立生产者—消费者矩阵,记录权限、用途绑定、调用者可控字段和密文格式。
  3. 定位一个只要求普通后台角色与独立“字符串加密”应用权限的动作;动作允许任意明文输入。
  4. 反向搜索同一解密函数的消费者,发现公开搜索动作解密调用者模板,且控制器/动作没有授权元数据。
  5. 沿公开动作跟踪到完整模板解析器,而非搜索专用允许列表;确认数据库标签可读取嵌套查询文本并沿用默认 CMS 数据库连接。
  6. 跟到数据库抽象的最终 sink,确认原始字符串直接进入 ExecuteReaderAsync(queryString),不限制为 SELECT。
  7. 第一层夹具直接引用官方发布程序集,反射精确路由、角色与权限;无权限返回 401,有单一权限时加密成功,公开消费者解密后把固定 SELECT 送到数据库管理器替身。
  8. 单独用官方数据库管理器、ORM 与 PostgreSQL provider 在隔离数据库执行 UPDATE ... RETURNING;独立查询确认状态持久化。
  9. 最终在同一 Linux 进程串联官方加密动作、公开搜索动作、完整模板解析器和真实 PostgreSQL,修改合成管理员表。
  10. 使用官方管理员仓储的口令验证方法做业务层正负对照:指定新口令成功、旧口令失败;到此立即停止进一步 SQL/RCE 扩展。
  11. 数据库容器使用无宿主端口、独立网络、tmpfs 与自动删除;测试后确认容器不存在。
  12. 按本地标准把“任意 SQL + 管理员密码接管”定为高危,生成正式报告、攻击路径图、结构化总账和不可变证据哈希。

踩坑记录

问题 原因 解决方案 耗时
先尝试从 CBC 密文直接伪造模板 块翻转虽可控,但会破坏前一明文块;非标准 padding 对最后一字节产生 33 个成功候选,不是经典单候选 oracle 将密码学分支作为独立闭合项,不用它支撑主结论;回到应用层通用加密 oracle 中
SQL 写入夹具在 macOS 打开 SQLite 前失败 官方 SQLite provider 依赖缺失的 native SQLite.Interop 保留“SQL 前失败”的环境证据,切换正式支持的 PostgreSQL provider 与 Linux 容器 低
模板属性中的 HTML &quot; 未转成 SQL 双引号 模板属性解析没有按预期完成实体解码,数据库在 & 处拒绝语句 改用嵌套查询文本元素;先前失败保留为语法负控,不重复同法 低
Linux 证明项目缺 ICU 最小 Debian 镜像未安装 globalization native 依赖 证明仅使用 ASCII canary,以 DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 运行,不扩展镜像或下载额外包 低
“能执行 UPDATE”仍可能被认为影响抽象 只证明数据库原语,不一定闭合实际业务接管 修改官方管理员表后调用官方口令验证器,建立新口令成功/旧口令失败的独立业务对照 低

工具链发现

  • 对采用“不透明密文参数”的应用,必须同时审计密文生产者和消费者;加密不提供来源认证,通用加密接口会摧毁消费者隐含的信任边界。
  • 控制器级角色限制不能替代细粒度权限影响分析。一个看似低风险的独立应用权限若能生成其他公开 sink 接受的 capability,就属于权限提升原语。
  • 模板语言的公开解析面必须采用标签允许列表;只过滤搜索输入/XSS,不会约束数据库、文件、插件或代码类标签。
  • ExecuteReaderAsync 并不等于只读。支持 UPDATE/INSERT/DELETE ... RETURNING 的数据库可通过同一 reader API 完成写入并返回行。
  • 跨 OS native provider 失败后,用产品已携带的另一数据库 provider 和相同数据库抽象做隔离动态证明,证据强度高于重新实现 sink。
  • 管理员接管要由业务验证器闭合;数据库列改变、HTTP 200 或响应回显单独都不足以证明新凭据可用。

关键代码/命令

生产者—消费者检查模板:

producer: role + exact permission + arbitrary plaintext -> ciphertext
consumer: unauthenticated ciphertext -> decrypt -> full parser
parser: dangerous database tag -> raw query string
sink: configured CMS connection -> ExecuteReaderAsync(raw SQL)
impact: synthetic administrator UPDATE -> official validator new=true / old=false

隔离数据库执行模式:

docker run -d --rm --name {pg_canary} \
  --network none --tmpfs /var/lib/postgresql/data \
  -e POSTGRES_PASSWORD={synthetic_password} \
  -e POSTGRES_DB={synthetic_database} {existing_postgres_image}

docker run --rm --network container:{pg_canary} \
  -e DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
  -v "{task_root}:/proof:ro" -w /proof {existing_linux_image} \
  /proof/{verified_dotnet_runtime}/dotnet /proof/{proof_dll}

docker stop {pg_canary}

高价值断言:

DENIED_WITHOUT_PERMISSION=True
PERMISSION_CHECK={single_encrypt_permission}
PUBLIC_CONSUMER_AUTHORIZE_METADATA_COUNT=0
RAW_SQL_RETURNED_CANARY=True
PERSISTED_ADMIN_ROW_CHANGED=True
CHOSEN_PASSWORD_ACCEPTED=True
OLD_PASSWORD_REJECTED=True
PROOF=PASS

对本包的改进建议

  • 在 API Security 与 SRC Hunter 中增加固定检查:“通用 Encrypt/Sign/JWT 生成器是否能为另一个公开 Verify/Decrypt/Parse 消费者生成 capability”。
  • 模板引擎审计清单增加“按解析上下文列危险标签允许列表”,优先检查 SQL、文件、插件、include、代码执行与任意连接字符串覆盖。
  • 数据库 sink 证明模板应优先使用 UPDATE ... RETURNING 加独立读回;若可触达账号表,再加官方认证方法正负对照。
  • 把“宿主 native provider 失败 → 产品另一正式 provider + 隔离 Linux/DB 容器”加入 .NET 动态证据降级路径。

可复用的模式/脚本片段

低权限加密/签名生产者
  → 同格式公开解密/验签消费者
  → 消费者把密码学有效性误作授权
  → 完整解释器/模板引擎
  → SQL/文件/插件高危标签
  → 实际业务状态改变

评级闭环:

原始 SQL 可达
  + 无权限负控
  + 独立持久化读回
  + 官方管理员验证器新旧口令差分
  = 管理员接管 confirmed

进化动作

  • 更新了路由矩阵(新增通用加密/签名 oracle 与公开危险消费者组合路由)
  • 更新了 tool-index(未安装新项目工具)
  • 更新了 bootstrap-manifest(无缺失能力)
  • 更新了子 skill 文档
  • 新增了 pitfalls 记录
  • 更新了 field-journal 三类索引

环境信息

  • OS:macOS ARM64 宿主 + 隔离 Linux ARM64 容器
  • 工具版本:.NET SDK 10.x;官方发布程序集目标 .NET 8;证明 runtime .NET 10.x;PostgreSQL 16
  • 目标平台/版本:{target_product} 7.x 开源发行物

脱敏检查

  • 无真实产品名、域名、公网 IP、客户部署、commit 或发行物哈希
  • 无真实 token、Cookie、账号、口令、数据库连接串或业务记录
  • 所有命令使用 {placeholder};状态改变仅描述合成 canary
  • 未保留管理员原值、密文、SecurityKey 或可直接回放的载荷

索引同步

本文件已加入 Web/API 场景、高频 Web/API 授权模式和 .NET CMS 模板解析实体倒排;统计日期同步为 2026-08-01。