hex编码绕过仅对mysql、postgresql等支持十六进制字面量的数据库生效,sqlite需启用hex模式,sql server须配合convert;检测需兼顾0x变体(如0x、注释嵌入、unhex等)及语义校验(偶数长度、合法字符、无控制字符)。

HEX编码绕过只对特定数据库生效
MySQL 和 PostgreSQL 原生支持 0x61646D696E 这类十六进制字面量,直接解析为字符串;SQLite 需显式启用 hex 模式(如 PRAGMA hex),否则不识别;SQL Server 的 0x 前缀仅表示二进制字节流,不能直接用于字符串比较,必须配合 CONVERT(VARCHAR, 0x61646D696E) 或 CAST(0x61646D696E AS VARCHAR) 才能生效。误判数据库类型会导致 payload 完全失效。
单纯匹配 0x[0-9a-fA-F]+ 会漏掉大量变体
真实攻击流量中,0x 常被刻意变形来逃逸正则检测:
-
0X61646D696E(X 大写)——MySQL 允许 -
0x61%0a646D696E(URL 编码换行符插入) -
0x61/**/646D696E(注释分隔) -
UNHEX('61646D696E')、CONV('61646D696E',16,10)、CONCAT(0x6164,0x6D696E)
这些形式在语法上合法、语义上等价,但若检测逻辑只盯 0x 开头的连续十六进制串,就会全部放过。
必须校验 HEX 串是否真能被当作字符串解释
检测不能停留在“看起来像 HEX”,而要验证它是否具备可执行语义:
- 长度必须为偶数,否则 MySQL 报错
Incorrect hexadecimal value - 字符只能是
0-9a-fA-F,含其他字符(如g、G、_)即非法 - 尝试解码:用
bytes.fromhex("61646D696E")不抛异常,且解出内容不含控制字符(如0x27单引号、0x3B分号、0x00空字节) - 特别警惕
0x27、0x22、0x3D、0x20等 ASCII 控制字符出现在 HEX 串中——大概率是构造恶意字符串的信号
整型注入点用 HEX 绕过时最容易忽略边界
当注入点是数字型(如 id=1),攻击者常写 id=-1 UNION SELECT 1,2,(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database())--;一旦引号被过滤,就换成 ...WHERE table_schema=0x6461746162617365...。这里容易踩坑:
-
database()返回的是当前库名,但0x6461746162617365是硬编码值,若库名动态变更(如多租户场景),解码后不匹配导致查询为空 - 某些 WAF 对
information_schema表名做过滤,但放行0x696E666F726D6174696F6E5F736368656D61——这串 HEX 解码后仍是information_schema,却绕过了关键词检测 - MySQL 5.7+ 默认禁用
SELECT从information_schema中读取敏感字段(如COLUMN_NAME),需确认目标版本权限配置
真正难防的不是 0x 本身,而是它嵌套在函数调用、拼接表达式、跨库引用里的组合形态——单点规则很难覆盖所有语义等价路径。











