本文仅用于 CTF、靶场、本机实验和明确授权环境。

面试中常见的问题是:“SUBSTRING() 被过滤怎么办?”真正稳妥的回答不是背另一个函数名,而是先说清楚原函数承担什么能力,再选择同义函数、等价表达式或另一条反馈通道。

1. 截取字符串

1
2
3
4
5
SUBSTRING('abcdef',2,3)  -- bcd
SUBSTR('abcdef',2,3) -- bcd
MID('abcdef',2,3) -- bcd
LEFT('abcdef',2) -- ab
RIGHT('abcdef',2) -- ef

SUBSTR()MID()SUBSTRING() 的同义形式。LEFT()RIGHT() 适合从两端取值。

SUBSTRING 被过滤

1
2
3
4
SUBSTR
MID
LEFT
RIGHT

逗号同时被过滤

MySQL 支持标准语法:

1
2
3
SUBSTRING('abcdef' FROM 2 FOR 3)
SUBSTR('abcdef' FROM 2 FOR 3)
MID('abcdef' FROM 2 FOR 3)

只取某位置到结尾:

1
SUBSTRING('abcdef' FROM 2)

截取函数全部不可用

换成模式或整体比较:

1
2
3
value LIKE 'a%'
value REGEXP '^a'
HEX(value) LIKE '61%'

如果页面能直接回显完整值,就没有必要逐字符截取。

2. 字符串长度

1
2
3
4
5
LENGTH(value)
OCTET_LENGTH(value)
CHAR_LENGTH(value)
CHARACTER_LENGTH(value)
BIT_LENGTH(value)

区别:

1
2
3
LENGTH / OCTET_LENGTH       字节数
CHAR_LENGTH 字符数
BIT_LENGTH 位数

UTF-8 环境中:

1
2
LENGTH('中')       常为 3
CHAR_LENGTH('中') 为 1

只处理 ASCII flag 时常得到相同字符长度,但遇到多字节内容不能混用。

3. 字符与数字转换

1
2
3
4
5
ASCII('A')  -- 65
ORD('A') -- 65
HEX('A') -- 41
CHAR(65) -- A
UNHEX('41') -- A

替代路线:

1
2
3
ASCII 被过滤 → ORD 或 HEX
ORD 被过滤 → ASCII、HEX 或直接字符比较
CHAR 被过滤 → 十六进制字面量、UNHEX

多字节字符、连接字符集和表达式类型都可能改变结果,需要在对应版本验证。

4. 十六进制字面量

1
2
0x61646d696e
UNHEX('61646D696E')

对应字符串是 admin

用途:

1
2
3
避免直接出现字符串引号
观察不可见字符
避免分隔符与数据混淆

十六进制值在不同上下文中可能作为二进制字符串或数字处理,不能脱离表达式判断。

5. 字符串拼接

1
2
3
CONCAT('ab','cd')
CONCAT_WS('-', 'ab', 'cd')
GROUP_CONCAT(username)

注意 NULL

1
2
CONCAT('a',NULL)             -- NULL
CONCAT('a',IFNULL(NULL,'')) -- a

替代路线:

1
2
3
4
CONCAT 被过滤       → CONCAT_WS
多行合并 → GROUP_CONCAT
只需真假判断 → 不一定需要拼接
逗号也被过滤 → 改查询结构或换盲注

6. 条件函数

1
IF(1=1,'yes','no')

等价能力:

1
CASE WHEN 1=1 THEN 'yes' ELSE 'no' END

如果表达式只放在 WHERE 中,往往可以直接使用条件:

1
WHERE LENGTH(value) > 5

没有必要为了使用 IF() 而增加一层结构。

7. 空值处理

1
2
3
4
5
value IS NULL
value IS NOT NULL
IFNULL(value,'fallback')
COALESCE(value,'fallback')
NULLIF(a,b)

不要混淆:

1
2
3
IS NULL      判断是否为空
IFNULL 为空时返回替代值
COALESCE 返回第一个非 NULL 参数

8. 比较与模式匹配

1
2
3
4
5
6
7
8
value = 'admin'
value != 'admin'
value <> 'admin'
value LIKE 'adm%'
value REGEXP '^adm'
value IN ('admin')
value BETWEEN 'admin' AND 'admin'
STRCMP(value,'admin') = 0

等号被过滤

候选:

1
2
3
4
value LIKE 'admin'
value IN ('admin')
value BETWEEN 'admin' AND 'admin'
NOT STRCMP(value,'admin')

大于、小于被过滤

可研究:

1
2
3
4
BETWEEN low AND high
STRCMP(a,b)
GREATEST(a,b)
LEAST(a,b)

这些不是无条件等价。NULL、隐式类型转换和 collation 都可能改变语义。

9. 大小写与 collation

1
2
3
4
5
LOWER(value)
LCASE(value)
UPPER(value)
UCASE(value)
BINARY value

是否区分大小写主要受排序规则影响。调用 LOWER() 和改变比较所用 collation 是不同层次的处理。

10. 信息函数替代

目的 常用 替代
当前库 DATABASE() SCHEMA()
版本 VERSION() @@version
登录用户 USER() SESSION_USER()SYSTEM_USER()
权限用户 CURRENT_USER() 语义独立,不宜直接等同
SQL 模式 @@sql_mode 从语法行为侧面推测

11. 常用替代速查

所需能力 首选 候选替代 注意事项
截取 SUBSTRING SUBSTRMIDLEFTRIGHT 方向和参数不同
无逗号截取 SUBSTRING(x,1,1) SUBSTRING(x FROM 1 FOR 1) MySQL 支持
长度 LENGTH OCTET_LENGTHCHAR_LENGTHBIT_LENGTH 单位不同
字符转数值 ASCII ORDHEX 多字节需验证
数值转字符 CHAR UNHEX、十六进制 字符集与类型
拼接 CONCAT CONCAT_WS NULL 行为不同
条件 IF CASE WHEN、直接逻辑 返回类型可能变化
空值替代 IFNULL COALESCE 参数数量不同
精确比较 = LIKEINBETWEENSTRCMP NULL 与 collation
多行合并 GROUP_CONCAT LIMIT 逐行 长度与回显限制

12. 面试回答模板

遇到“这个函数不能用怎么办”:

1
2
3
4
5
1. 说明原函数承担的能力
2. 判断失效原因:WAF、版本、权限、语法位置还是无反馈
3. 选择同能力函数或等价表达式
4. 同类函数都不可用时,切换查询结构或反馈通道
5. 说明替代方案的限制和验证方法

下一篇进入盲注:怎样把未知数据拆成真假问题,以及如何稳定地使用布尔和时间反馈。

参考资料