自己看书看视频学个七七八八,整理个笔记,有不妥的地方请大佬们指出来。
SQL注入漏洞的产生需要满足一下两个条件:
参数用户可控:前段传给后端的参数内容是由用户可以控制的。
参数带入数据库查询:传入的参数拼接到SQL语句,并且带入数据库查询。
例如:select * from users where id = 1 ‘ 这不符合语法规范所以会报错。
当传入ID的参数为 and 1=1时
语句为 select * from users where id =1 and 1=1 因为1=1为真 而且id=1也为真,所以返回的结果与 id=1一样,当换成1=2时因为1=2不成立,所以返回假,页面如果与id=1返回不同结果 说明存在sql注入漏洞。
MySQL5.0版本之后,MySQL默认在数据库中存放一个“information_schema”的数据库,在该库中,有三个表名:SCHEMATA、TABLES、COLUMNS。
SCHEMATA表存储该用户创建的所有数据库的库名,需要记住该表中记录数据库库名的字段名 SCHEMA_NAME。
TABLES表存储该用户创建的所有数据库的库名和表名,数据库名为TABLE_SCHEMA,表名为TABLE_NAME。
COLUMNS表存储该用户创建的所有数据库的库名、表名、字段名,数据库名为CHEMA_NAME,表名为TABLE_NAME,字段名为COLUMN_NAME。
MySQL查询语句:
Limit的使用格式为limit m,n ,其中m是指记录开始的位置,从0开始,表示第一条记录;n是指取n条记录。例如limit 0,1 表示从第一条记录开始,取一条记录。
需要记住的几个函数:database():当前网站使用的数据库版本。
version():当前MySQL的版本。
user():当前MySQL的用户。
常见注释符:# --空格或者/**/
一、Union注入
先测试是否存在注入,然后使用order by (数字) 查询数据表字段的数量,报错说明大了,然后利用union select 1,2,3…看返回结果哪里有数字,在返回的数字上输入想查询的 例如datebase等,假如数据库名为sql接下来
输入命令查询表名:select table_name from infomation_schema.tabless where table_schema=’sql’ limit0,1; //这是查询第一个表名 根据修改limit后面的数字 便可以得到想要的表
二、布尔注入
1’ and length(database())>=1–+ //判断数据库的长度
1’ and substr(database(),1,1)=‘t’ --+ //判断数据库第一个字母的值(substr的意思是截取,其意思为截取database()里的值)
1’ and substr(database(),2,1)=‘q’ --+ //判断数据库的第二个字母的值
1’ and ord(substr(database(),1,1))=115–+ //利用ord和ASCII判断数据库库名
1’ and substr(database(),2,1)=’q’–+ //利用substr判断数据库的库名
1’ and substr(select table_name from information_schema.table wheretable_schema=‘sql’ limit 0,1),1,1)=‘e’ --+ //利用substr判断数据库的表名
还可以使用ASCII码查询, s的ASCII码是115,在MYSQL中,ASCII转换的函数为ord:’ and ord(substr (database(),1,1)=115–+
三、报错注入
例如在.php?username=1’ 因为参数是1在后面加一个’在数据库执行SQL的时候会报错,在返回页面结果可以看到程序直接将错误信息输出到了页面之上,所以可以构造语句利用报错返回我们想要知道的信息。比如:1’ and updatexml(1,concat(0x7e,(select user()),0x7e),1)–+ //利用updatexml获取user() , 其中 0x7e是ASCII编码等同于~
解释:UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
由于updatexml的第二个参数需要Xpath格式的字符串,以~开头的内容不是xml格式的语法,concat()函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。
四:时间注入
if (length(database())>1,sleep(5),1) //语句的意思是,如果数据库库名长度大于,则MYSQL查询休眠5秒,否则查询1。
根据burp抓包响应的时间就可以判断是否正确,根据这个原理,
使用substr函数:if (substr(database(),1,1)=’s’,sleep(5),1) //如果第一个字母是s则休眠5秒,以此类推。
修复屏蔽sleep等字符。
五:堆叠查询注入
(不太懂和直接用布尔和时间注入的区别)
堆叠查询可以执行多条语句,语句直接以;分隔。堆叠注入就是在第二个sql语句中构造自己要执行的语句,例如访问 id=1’ ,页面返回错误,再访问 id=1’%23 返回正常,这里可使用Boolean注入和时间注入或者堆叠注入
堆叠注入:id=1’;select if(substr(user(),1,1)=’r’,sleep(5),1)%23
//这个第二句sql就是时间注入的语句
六:二次注入
存在两个页面1.php 和2.php ,其中1.php功能是注册用户名;2.php是通过参数ID读取用户名和用户信息。
访问1.php?username=test’ 在burp抓包得到对应的ID 为21,然后访问2.php?id=21 返回错误(因为有一个单引号引起语法错误)
回到第一步1.php?username=test’ order by 1%23,获取一个新的id=23,再次访问2.php?id=23,页面返回空白;再次回到1.php?username=test’ order by 10%23,获取新的id=33,再访问2.php?id=33返回错误(unknow column’10’ in ’oder clause’)说明返回空白页面为正确,通过测试可以知道有几个字段,然后联合union查询结果
七:宽字节注入攻击
输入Id=1’时返回结果发现没有报错并且’后方出现一个\转义反斜杠,一般情况是不存在注入漏洞的,有一个特殊情况,数据库的编码是GBK编时,可以使用宽字节注入,宽字节的格式是在地址后加一个%df在家单引号,因为单斜杠的编码为%5c,而在GBK编码中%df%5c是繁体字連,单引号就可以成功逃逸,报出数据库错误。然后进行进一步注入。
八:cookie注入
发现URL中没有GET参数,但是页面返回正常,使用burp抓包发现cookie中存在id=1的参数,修改为id=1’然后再次访问发现报错,在输入几个1=1 1=2判断是否存在sql注入,接着 order by ,union
九、base64注入
在URL中发现id的参数是经过base64编码的,就将所有语句也进行base64编码即可
十:XFF注入
通过burp抓包看HTTP请求头,有头部参数为X-Forwarded-for(简写xff)他代表客户端的真是ip,通过修改xff的值可以伪造客户端ip,然后在ip地址后测试sql语句进行判断并进行注入。
SQL注入绕过:
1、大小写 And aNd 等
2、双写绕过 例如输入 id=1 and 1=1 报错 输入的 and1=1 变成 1=1,可知 and被过滤了,可以写 id=1 anandd 过滤and 还剩下一个and可以成功绕过,接下来输入 order by 3 返回错误信息 der by 知道过滤了or,写作oorr
3、编码绕过 由于服务器会对URL进行一次解码,所以将被拦截的进行两次编码
4、内联注释:/!and/
SQL注入修复建议:
1、过滤危险字符
2、使用预编译语句
SQLMAP:参数
–level 5:探测等级 一共有五个等级 等级越高payload越多也越慢
–is–dba:当前用户是否为管理权限
–roles:列出数据库管理员角色
–referer:HTTP Referer头
–sql–shell:运行自定义的sql语句
–os–cmd,–os–shee:运行任意操作系统命令
–file-read:从数据库服务器中读取文件
–file-write–file-dest:上传文件到服务器中