实战中遇到的sql小姿势

本文作者:Turn it up(信安之路职业渗透小组组长)

笔者有个好习惯就是喜欢做笔记,即使当时没来来得及弄懂,之后也可以慢慢研究。今天就选取出一些之前所做笔记里的个人认为比较有趣的,关于 SQL 注入/ SQL 方面的小东西,以及它们带给我的思考,简单来说就是笔者的一些点滴的成长过程。这些东西也并不怎么高深,比较适合入门的看看。另外就是由于可能比较敏感,所以就尽量不放图了。

逻辑推理注入

访问网站,看到的是一个登录界面,在用户名处随意输入 .'", ,页面就返回 500,显示的是下面这个鬼东西。

之后对用户登录处的用户名进行 payload 测试,最终发现

测试:admin')--

结果:验证失败

测试:asdfsdf')--

结果:无用户信息

之后再测试 admin');waitfor delay '0:0:5'--,页面延迟了,可以判断出数据库类型为 mssql,用星号 * 标记注入点,之后用 Sqlmap 跑跑。

sqlmap.py --random-agent -r req.txt --dbms mssql

结果如下:

 Parameter: #1* ((custom) POST)Type: stacked queriesTitle: Microsoft SQL Server/Sybase stacked queries (comment)PAYLOAD: ...Vector: ;IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]'--Type: AND/OR time-based blindTitle: Microsoft SQL Server/Sybase time-based blind (IF)PAYLOAD:...Vector: IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]'

数据跑出来了,当然,故事到这里并没有结束,这里发现的注入类型只是延迟注入。大表哥表示这里有布尔型注入,之后笔者尝试使用 --technique b,一直没搞出来,后来被告知需要添加 --level 5

当时笔者的内心是这样想的,之前 sqlmap 白学了?不是 level 1 测试当前 HTTP 请求中的参数,level 2 Cookie 字段,level 3User-Agent/Referer 头部字段 .等等.. 这样子的吗?

笔者也曾翻过 Sqlmap 官方手册,但是手册上根本就没讲得很清楚,所以就一直没怎么注意。

Option: --level This option requires an argument which specifies the level of tests to perform. There are five levels. The default value is 1 where limited number of tests (requests) are performed. Vice versa, level 5 will test verbosely for a much larger number of payloads and boundaries (as in pair of SQL payload prefix and suffix). The payloads used by sqlmap are specified in the textual file xml/payloads.xml. Following the instructions on top of the file, if sqlmap misses an injection, you should be able to add your own payload(s) to test for too!

之后笔者使用 -v 3 去看看 Sqlmap 的系统信息与 payload 信息,才知道,level 越高,尝试使用的 payload 越多,level 1 时候就跳过了下面这个 payload。

[DEBUG] skipping test 'Boolean-based blind - Parameter replace (CASE) (original value)' because the level (3) is higher than the provided (2)

最后使用了 --level 3 后 Sqlmap 终于布尔型注入,payload 是这样的,在 sqlmap 的源码 XML 文档中也有说明。

 Parameter: #1* ((custom) POST)Type: boolean-based blindTitle: Microsoft SQL Server/Sybase boolean-based blind - Parameter replacePayload: ...Vector: (SELECT (CASE WHEN ([INFERENCE]) THEN [RANDNUM] ELSE [RANDNUM]*(SELECT [RANDNUM] UNION ALL SELECT [RANDNUM1]) END))

在网上翻了翻文章,乌云上的前辈早就有提及了,奈何就是不知道。

其实呢,学习 sqlmap 看什么源码,傻啊(有完全看懂的大佬忽略)。简单点,只要把 sqlmap 的关键参数弄懂,对着 -v 2 信息慢慢捋一遍,其实就可以了,奈何当初也不知道。

POST 注入

故事这样的,一群菜鸡搞了几天,也没找到几个漏洞,大表哥就只好出手了,“看,这不就是一个 SQL 注入吗”底下的一群菜鸡挠头。

这个网站在测试的时候是没有 WAF 的,然后在 BurpSuit 中有这么一条记录,请求类型为 GET:

controller.do?method=getInfo&page=&calogType=

笔者用过 BurpSuitActiveScan,也用过 Sqlmap 跑过,AWVS 扫过,手工搞过,但是也没发现什么名堂。

但是....表哥的 Payload 是这样的:

 POST /controller.doHost: www.test.comConnection: closeContent-Type: multipart/form-data;boundary=123--123Content-Disposition:form-data;name="method"get--123Content-Disposition:form-data;name="page"1--123Content-Disposition:form-data;name="calogType"*--123--

诶,怎么瞅着好眼熟啊?等等..这不是文件上传的那个吗...这里是在绕 WAF 吗...但不是没 WAF 吗?(其实是有的,只是没表现出来,这 WAF 也很骚啊.)

这里主要有两个要点需要弄清楚:

1)这个 web 应用在这个地方为什么会处理 POST 里面的数据?

2)为什么 POST 的数据可以以文件上传 multipart/form-data 的形式提交?

先回答问题 1。注意这是一个后端语言是用 JAVA 写的网站,笔者后来去学习了一下 JAVA WEB,了解到了程序员使用的 Servlet 中,通常会在 doPost() 里面调用 doGet() 方法,在写代码的时候只需要使用 doGet() 就好。这样一来,就不必区分客户端的请求是 GET 还是 POST 了,省事多了;而 PHP 中也有类似的情况,比如 $_REQUEST;而 .NET 中应该也有类似的操作,后来笔者在 PHP、.NET 中都有遇到过这样的情况。

然后说说问题 2。通常情况下,我们使用表单提交数据,如果没有文件的话,除非向下面这样特意指明,否则浏览器在提交的时候都是给的 Content-Type 类型默认是 application/x-www-form-urlencoded

 <form action="post.php" method="post" enctype="multipart/form-data">    <input type="text" name="username" id="username"><br>    <input type="submit" name="submit" value="submit"></form>

笔者起初以为问题 2 是由于 WEB 容器的强大解析功能导致...对于该种 Content-Type ,笔者首先在 PHP+Apache 中,使用 $_POST、$_REQUEST 进行试验,发现可以直接获取到 username 数据。

随后使用 tomcat-apache+java,发现在 Servlet 中是无法通过 request.getParameter("username") 来直接获取到 multipart/form-data 方式中表单提交的数据,还需要使用其他额外的库,对客户端过来的请求报文进行处理,才能像在 PHP 中一样拿到数据。就此表明,该问题是后台语言本身的一些兼容处理导致的一种表现,与容器无关。(ASP.NET 的就实在懒得弄了)

那还有没有其他 POST 数据的姿势呢?有的。

在实现了 RESTful 接口的网站里,可能会支持application/jsontext/jsonapplication/xmltext/xml ,可参考四种常见的 POST 提交数据方式:

https://imququ.com/post/four-ways-to-post-data-in-http.html

笔者 YY 一下,那可不可以反过来用 application/x-www-form-urlencoded 来上传文件?问题是 RFC 文档中根本没有这样玩法,ServletPHP 本身也就不会支持,当然自己自定规则自己玩也没问题...

在这节中,笔者另外想多 BB 几句。很多人会一本正经地说,HTTP 的 GET 与 POST 的方法不同在于,GET 是向服务器请求资源,POST 是向服务器提交资源。一开始笔者是有点懵逼的,不都可以提交数据吗???

后来笔者发现这只是 RFC 文档上的规定,可能教科书也是这么写的,而实际上我们在使用的使用时有这么严格区分吗,而且说这段话没有意义,甚至还不如不知道...至少对于普通数据(application/x-www-form-urlencoded)的提交,它们表现得差不多。

所以应该这么回答,通常,服务器(后台)会默认 GET 请求为 application/x-www-form-urlencoded 数据类型,并忽略其 Content-Type与请求报文的消息主体;对于 POST 请求,服务器在找不到 Content-Type 时将默认其为 application/x-www-form-urlencoded ,对于 请求行 中的 query_string 则依然会像GET中一样对它进行处理。

放几张图方便懵逼的小伙伴们理解:

本章节最后,笔者从RFC文档摘取一些关于 mulitipart/form-data 的东西给大伙瞧瞧:

它作为用户填写表单的结果,能够被多种多样的应用程序使用,并可通过多种协议进行传输。

这种表示(实现)在众多的 web 浏览器和 web 服务器中得到了广泛的应用。

参考

https://tools.ietf.org/html/rfc7578

MySQL 低权限文件读取

笔者有次在搞事情,然后进到了数据库,发现只是个 test 用户,权限很低,只能“搞自己”。笔者很不甘心,于是就百度一波,意外发现一篇比较老的文章。

Mysql 漏洞利用(越权读取文件,实战怎么从低权限拿到root密码):

http://www.moonsec.com/post-254.html

利用下面的操作,即便是 test 用户,且有 secure_file_priv 限制,也能从读取服务器上的文件。

 create table t(data text);LOAD DATA LOCAL INFILE 'c:\\Windows\\win.ini' into table t fields terminated by '';select txt from t limit 1,30 ;

看了看 MySQL 中关于 LOAD DATA LOCAL INFILE 的相关参考文档,有一些关键的话,如下:

Using LOCAL is a bit slower than letting the server access the files directly, because the contents of the file must be sent over the connection by the client to the server. On the other hand, you do not need the FILE privilege to load local files.

参考

https://dev.mysql.com/doc/refman/5.6/en/load-data.html

In a Web environment where the clients are connecting from a Web server, a user could use LOAD DATA LOCAL to read any files that the Web server process has read access to (assuming that a user could run any statement against the SQL server). In this environment, the client with respect to the MySQL server actually is the Web server, not a remote program being run by users who connect to the Web server.

参考

https://dev.mysql.com/doc/refman/5.6/en/load-data-local.html

文档大意是说,使用添加了 LOCAL 关键字后,数据是由客户端发给 MySQL 数据库服务器的,MySQL 并不会直接读取,所以即便 MySQL 对该文件没有读取权限,只要该客户端本身帐号有读取权限即可。

之后笔者在 WIN7 下,使用 mysql-5.5.60-winx64 进行实验测试。发现确实如此,添加 local 关键字后,读取文件的权限与 MySQL 本身无关,权限来源是运行 MySQL 客户端的系统账号,比如你是通过 mysql -uroot -proot 进行访问的; 或是运行网站 WEB 容器的系统帐号,比如你在 phpmyadmin 访问的 MySQL 数据库。另外重要的一点是,该语句可以绕过 secure_file_priv = 的限制。

前辈们好像也不关心这条语句为啥可以这样玩,所以笔者就随意写写,大伙们喜欢就好...

最后,笔者想说,想要提升还是需要多问问为什么,而非看到一个姿势就觉得自己提升了,那你真的提升了吗?

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2018-06-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

MySQL中的binlog和redo浅析(r12笔记第5天)

有一个小问题可能很多人都想起过,那就是MySQL中既然已经有了binlog,为什么还需要redo,这个问题看起来好像很简单,但是细细品来,还是有不少值得注...

377110
来自专栏AhDung

【SQL】SQL2012离线帮助文档安装不上的处理手记

我SQL实例装的是2008 R2版,由于该版自带的SSMS(Microsoft SQL Server Management Studio 管理工具)存在一些操蛋...

23130
来自专栏张善友的专栏

MongoDB核心贡献者:不是MongoDB不行,而是你不懂!

近期MongoDB在Hack News上是频繁中枪。许多人更是声称恨上了MongoDB,David mytton就在他的博客中揭露了MongoDB许多现存问题。...

257100
来自专栏云计算教程系列

如何在Debian上安装MutliCraft

PS:本文撰写前已查询相关法律,本文内容不违反《互联网文化管理暂行规定》,遵守EULA协议,请勿举报。

21130
来自专栏FreeBuf

Android 5.x漏洞:黑客可以绕过屏幕密码进入系统

很多Android用户会选择使用锁屏密码保护设备,但最新爆出的漏洞却令人震惊:任何人无需复杂的操作即可绕过锁屏直接进入你的系统! 攻击者可以通过漏洞导获取上锁...

264100
来自专栏程序猿DD

自建API网关「架构设计篇」

阅读对象 传统企业正在做微服务架构转型的开发人员或者架构师,希望本文对您能起到一定的引导作用。 API网关介绍 网关一词较早出现在网络设备里面,比如两个相互独立...

1.6K70
来自专栏FreeBuf

打开文件夹就运行?COM劫持利用新姿势

*本文原创作者:菠菜,本文属FreeBuf原创奖励计划,未经许可禁止转载 打开文件夹就能运行指定的程序?这不是天方夜谭,而是在现实世界中确实存在的。利用本文探讨...

27880
来自专栏鸿的学习笔记

闲话聊聊事务处理(中)

上面提到了multi-object事务,但是要完美的处理multi-object事务并不容易。因为我们必须要面对并发问题导致的bug,而隔离性要求数据系统...

11220
来自专栏杨建荣的学习笔记

巧用外部表备份历史数据(r5笔记第62天)

在很多的系统中,随着时间的推移,都会沉淀大量的历史数据。一般数据量达到一定程度都会考虑使用分区表来处理。根据业务规则,可能有些历史数据隔一段时间就需要做清理了,...

381120
来自专栏IT大咖说

TiDB 原理与实战|架构师实践日

摘要 本篇文章出自七牛云和 PingCAP 联合主办的架构师实践日上,来自 PingCAP 的开发工程师李霞分享的《 TiDB 原理与实战》的演讲,介绍了目前分...

49270

扫码关注云+社区

领取腾讯云代金券