Mysql注入导图-学习篇

2017-09-06 08:07:44 ph0rse 信安之路

接触SQLi(SQL injection)已有大半年,不得不说,这是个庞大的领域。每次以为自己都弄懂了之后都会有新的东西冒出来,需要再次学习,一路走来效率不高,工作量很大。而且随着知识体系的壮大,很多东西会渐渐忘记。因此萌生了写一个思维导图的想法,一来整理自己的思路,防止遗忘。二来,作为一名大二的小学长,希望学弟学妹们在这方面能够学得更快一些。希望自己的工作,能为SQLi这座大厦舔砖加瓦,巩固‘地基’~

SQLi领域很广,从编程语言的角度PHP、JAVA、Python、C#……, 从数据库类型的角度Mysql、Mssql、Oracle、PostgreSQL……,如果再算上响应层Apache或IIS或其它的细微差距怕得是一辈子的工作量~不过好消息是,它们之间在大部分情况(除OOB、提权部分)下只存在细微差距。触类旁通地去学,工作量会小很多。而本文将基于Mysql-PHP,以思维导图为主线,介绍导图中生僻知识点的同时,也会引入一些实战性的CTF练习题,供大家实验。

Mysql+php的环境搭起来非常简单,使用phpstudy

http://www.phpstudy.net/a.php/211.html

即可,这也是我选择mysql+php入手的原因之一。

在熟悉了导图中的知识点中之后,可以借用SQLi-lab、RedTigher:

https://redtiger.labs.overthewire.org/

haking-lab:

http://hackinglab.cn/

的SQLi部分;这三套在线SQLi练习题目,来介绍相关知识点的练习与巩固。

文章涉及的文件可以在这个网盘:

http://pan.baidu.com/s/1gfOSowF

如果对文章内容存有疑问或发现了不严谨的地方,欢迎联系我(点击阅读原文进入我的博客),希望与你共同探讨。

SQLi思维导图的正确打开方式

由于图片大小的问题,请大家移步到下面的地址访问:

SQLi注入思维导图

http://104.194.90.209:2501/tmp_picture/Sum_SQLi.png

导图中的生僻技巧


此部分从上到下,对导图中较为生僻地知识点进行讲解。

SQLi的产生是因为程序没有对输入进行充分的过滤,导致攻击者可以通过操纵输入,达到利用代码进行攻击。

常规UNION查询

其最基础、最根本的利用方式就是获取数据库里的数据,从思维导图的最上方开始,首先是UNION带回显查询常规流程,随着之后知识的扩充,应用手段也会越来越多样。这一部分可以利用SQLi-labs这套题训练一下,源码和答案(Mysql注入天书)已经放到了网盘里,需要的朋友可以自取,这里面的题非常多,也比较全。“Mysql注入天书”中也对基础知识进行讲解,可以多刷几遍,多巩固一下。

6种报错语法与原理

随后是报错函数的原理、语法介绍,知晓原理才能灵活地利用,上面贴了6中我所遇到过的会导致报错的函数,多一种方法,就可能在CTF比赛中多一种预期之外的解法。SQLi-labs有专门的报错关卡,hacking-lab 第六关

http://hackinglab.cn/ShowQues.php?type=sqlinject

同样是报错注入,可以练习一下。

show & descript非常规注入

再往下的SHOW&DESC部分,是一种很巧妙的姿势,在非常规地show或descript语句中利用报错来获取数据。

贴上一个查看官方文档的好地方

http://devdocs.io/

当然google+官网才是硬道理。

盲注中无需函数的字符串比较

随后的SQLi中的'abc'>'abd' 为TRUE部分需要注意一下,就是当字符串截取函数被禁用时(打CTF时常见),可以将字符串直接对比,但字母之间的对比是根据字母表顺序而不是ascii码,这样就会导致盲注脚本最后输出的数据没有区分大小写。而字母与非字母字符之间是按照ascii码进行比较,所以可以通过0x5b-0x60中的一个非字母字符,来判断字母的大小写。

布尔盲注与时间盲注类似,没有特别需要补充的。

再往下的字符串操作部分则纯粹为了绕过一些黑名单,CTF比较有用,实战环境常用的几个一般就够用了。

数字型运算利用

测试注入部分,贴上了一些测试语句。其中需要注意Number中的‘3-2’测试向量,如果传参时输入3-2,然后回显了id=1的页面,就说明该处存在漏洞,且至少可以通过盲注的方式获取数据。

比如输入 1-(IF(user()='root@localhost'),1,0)--+如果返回的页面是id=1的,则说明后面的语句判断为假,若页面是id=0的页面,则说明判断为真,这就存在了盲注漏洞。可以继续测试,根据测试结果,用工具或者写脚本进行注入。

注释符绕过

继续往下,是Mysql注释符部分,其中有两点需要注意。第一,' /*!50000or*/1='1' /*!or*/1='1这种形式是为了绕过WAF。第二,对注释符--空格的过滤。因为有些黑名单(CTF题中尤其常见)在过滤--空格这种注释符时使用的是正则,但正则很容易不严谨,比如过滤了--空格 和 --%20(PS:空格的url编码),但--%a0(PS:换行符)依然能够绕过过滤,充当注释符使用。所以在测试--空格注释符的时候,只要--没有被过滤,就很可能有绕过的方法。

信息搜集向量

继续向下,在“版本&主机名&用户&库名&数据库路径&MAC地址”部分,搜集了一些Mysql中的全局变量名,可以获取一些渗透测试需要的敏感信息,其中获取Mysql版本号部分需要注意 /!mysql版本号/ 这种形式。当注入语句为SELECT * FROM Users limit 1,{INJECTION POINT};这种形式时,可以在注入点插入比如/!50717/,如果版本号小于5.7.17则返回真,从而可以判断版本号。

OCEDUER ANALYSE语法爆列、表名

继续向下,在查列名、表名部分,除了较为常规的UNION、报错、盲注方法,还可以使用PROCEDUER ANALYSE 语法。


limit用法可以自己测试。hacking-lab第四关

http://hackinglab.cn/ShowQues.php?type=sqlinject

一次性爆出所有的库、表、列名

除此之外,我还找到了一个非常NB的注入向量:

(SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x)

可以一次性爆出所有的库、表、列名

查看源码可以看到【库名】>表名>列名,整齐地显示了出来~

文件操作需知

继续向下,从文件操作开始,就要涉及SQLi的高级用法了。首先查询本用户是否具有文件操作的权限,三种查询方式。如果secure_file_priv变量为空那么直接可以使用函数,如果为null是不能使用。但在mysql的5.5.53之前的版本是默认为空,之后的版本默认为null。如果注入点使用的用户拥有文件操作权限,将十分危险。

首先,用户可以用loadfile()函数来获取任意文件信息,利用HEX()和UNHEX()函数甚至可以获取,服务器上应用程序(二进制文件)的全部数据。“select …… into outfile 'path'”语句可以将一句话木马写到服务器中,“select …… into dumpfile 'path'”可以直接写入二进制文件,从而向服务器中写入不安全的插件,从而进行提权和其它非法操作。

基本上获得了拥有文件操作权限的注入点,就离拿下整个服务器群不远了~

OOB带外通道渗漏注入

继续向下是OOB(带外通道攻击),就是通过非常规的方式将数据传输出去。同样需要secure_file_priv权限,对于Mysql有DNS(域名渗漏)和SMB两种主要带外传输方式。这种技术在概念上比较难理解,但掌握之后是非常强大的技术,除了能绕过WAF向外带出数据之外,还可以结合XSS漏洞进行危害性更大的攻击。在安全客上有一篇文章

http://bobao.360.cn/learning/detail/3458.html

介绍的比较详细,同时也有复现教程,可以学习一波~

爆出当前SQL语句

继续向下,有一个很厉害,但从未被提及的知识点,可以将当前查询语句爆出来:SELECT group_concat(info) FROM information_schema.processlist将注入语句爆出来之后,才可以更好地想办法去构造查询语句,甚至在column_name等列名关键字被过滤时,直接顺带查出来敏感列名。

继续向下是堆叠注入,如果注入点可以进行堆叠注入,就可以使用分号结束之前的语句,开启一个新的语句,类似这样:SELECT * FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username, password, priv) VALUES ('BobbyTables', 'kl20da$$','admin');如果可以堆叠注入,那么利用漏洞的方式就会更多,比如上一条语句中的添加admin用户。或者摆脱原语句的语法限制,注入一条新的语句进行文件操作。有很多旧文章,包括《SQL注入攻击与防御》这本书里都说php-mysql不可以,但经过测试之后,还是有办法进行堆叠注入的。对于php-mysql来说,通过PDO_MYSQL和MYSQLi方式与数据库交互地可以使用堆叠注入,但通过mysql_query进行交互的不可以。

提权

UDF提权

https://hack0nair.me/2013-05-01-udf-privilege-escalating-on-mysql/

是Mysql的常规提权方式,当hacker通过其它方式能够上传文件并执行时,可以通过提权来修改已知用户的权限,从而“脱裤”。

绕过

继续向下是一些绕过姿势,用来绕过一些WAF。

宽字节注入

宽字节注入可以在web应用转义单引号的情况下,利用宽字节的特性,吃掉转义反斜杠。此特性和下面的字符编码绕过技巧一样,都已经有较为详细地介绍文章,在这里就不再赘述了。宽字节注入详解传送门

http://drops.blbana.cc/2016/12/05/Mysql%E5%AE%BD%E5%AD%97%E8%8A%82%E6%B3%A8%E5%85%A5/

字符编码绕过技巧

字符编码绕过技巧详解传送门

https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html

绕过空格过滤

绕过空格部分,在导图中特殊字符用|分隔开了,用法类似%09,百分号加上ascii码的十六进制。而AND操作符之后的空格,可以用一些特殊字符的组合进行绕过,比如导图中提到的


-++-
!~~!
-+-+-+-+~~

可以进行组合的字符有+,-,~,!,@。是否能充当空格与选用字符以及字符数的奇偶都有关系,有兴趣的朋友可自行测试。

编码绕过

继续向下,编码绕过,并非所有情况都适用,根据代码情况会有所不同。其中非法十六进制的意思是,web应用检测到%后尝试对后面的字符进行url解码,正常情况,后面的两位字符应该是(0-f),如果出现大于f的字符,则非法,则停止解析,去除了百分号,还原了敏感关键字。

绕过逗号

继续向下,绕过逗号是一个在CTF中常见的知识点,可以在有回显情况下,不引用逗号,进行注入。mid('abc' from 1 for 1) 则在禁止逗号的盲注中非常有用。limit 1 offset 0 可以用来绕过 limit 0,1中的逗号

下面的溢出区绕过指的是有些web应用会截取用户输入,分段执行。这时可以利用截取的位数,来绕过关键字检测。

md5第二参数带来地安全问题

后面的[md5第二个参数

http://cvk.posthaven.com/sql-injection-with-raw-md5-hashes

约束性SQLi

http://bobao.360.cn/learning/detail/3357.html

类型转换

http://bobao.360.cn/learning/detail/3804.html)

都已经有比较详细的文章。

至此,思维导图中一些直观上不易理解的点就介绍结束了,其它的点同样重要,只是直接看图应该就能知道什么意思,就不再废话了。