首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战中遇到的sql小姿势

实战中遇到的sql小姿势

作者头像
信安之路
发布2018-08-08 16:36:30
8860
发布2018-08-08 16:36:30
举报
文章被收录于专栏:信安之路信安之路

本文作者: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 = 的限制。

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 信安之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 逻辑推理注入
  • POST 注入
  • MySQL 低权限文件读取
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档