文章目录
SSRF(Server Side Request Forgery,服务端请求伪造)是一种攻击者通过构造数据进而伪造服务器端发起请求的漏洞。因为请求是由内部发起的,所以一般情况下,SSRF漏洞攻击的目标往往是从外网无法访问的内部系统。
SSRF漏洞形成的原因多是服务端提供了从外部服务获取数据的功能,但没有对目标地址、协议等重要参数进行过滤和限制,从而导致攻击者可以*构造参数,而发起预期外的请求。
2.1.1 SSRF的原理解析
URL结构如下URI = scheme:[//authority]path[?query][#fragment]
authority组件又分为以下3部分:[userinfo@]host[:port]
- scheme:由一串大小写不敏感的字符组成,表示获取资源所需要的协议
-
authority:
-
userinfo@:是一个可选项,一般http使用匿名形式来获取数据。如果需要进行身份验证,格式为
username:password
,以@结尾。 - host:表示在那个服务器上获取资源,一般所见的是以域名形式呈现的,也有以IPv4、IPv6地址呈现的。
- port:服务器端口。各协议都有默认端口,如HTTP——80,FTP——21。使用默认端口时可以将端口省略。
-
userinfo@:是一个可选项,一般http使用匿名形式来获取数据。如果需要进行身份验证,格式为
-
path:指向资源的路径,一般使用
/
进行分层。 -
query:查询字符串,用户将用户输入数据传递给服务端,以
?
作为表示。 - fragment:为片段ID,其内容不会被传递`<服务端,一般用于表示页面的锚点。
2.1.2 SSRF漏洞的寻找和测试
SSRF漏洞一般出现在有调用外部资源的场景中,如社交服务分享功能、图片识别服务、网站采集服务、远程资源请求(如wordpress xmlrpc.php)、文件处理服务(如XML解析)等。在对存在SSRF漏洞的应用进行测试的时候,可以尝试是否能控制、支持常见的协议,包括但不限于以下协议:
-
file://
:从文件系统中获取文件内容 -
dict://
:字典服务器协议,让客户端能够访问更多字典源。在SSRF中可以获取目标服务器上运行的服务版本等信息 -
gopher://
:分布式的文档传递服务。使用Gopher协议时,童安格控制访问的URL可实现向指定的服务器发送任意内容,如HTTP请求、MySQL请求等,所以其攻击面非常广。
2.1.3 SSRF漏洞攻击方式
2.1.3.1 内部服务资产探测
SSRF漏洞可以直接探测网站所在服务器端口的开放情况甚至内网资产情况,如确定该处存在SSRF漏洞,则可以通过确定请求成功与失败的返回信息进行判断服务开放情况。
例:
# encoding: utf-8
import requests as req
import time
ports = ['80', '3306', '6379', '8080', '8000']
session = req.Session()
for i in xrange(255):
ip = '192.168.80.%d' % i
for port in ports:
url = 'http://example.com/?url=http://%s:%s' % (ip, port)
try:
res = session.get(url, timeout = 3)
if len(res.content) > 0:
print ip, port, 'is open'
except:
continue
print 'DONE'
2.1.3.2 使用Gopher协议扩展攻击面
1. 攻击Redis
Redis一般运行在内网,使用者大多将其绑定于127.0.0.1:6379,且一般是空口令。攻击者通过SSRF漏洞未授权访问内网Redis,可能导致任意增、查、删、改其中的内容,甚至利用导出功能写入Crontab、Webshell和SSH公钥(使用导出功能写入的文件所有者为redis的启动用户,一般启动用户为root,如果启动用户权限较低,将无法完成攻击)。
Redis是一条指令执行一个行为,如果其中一条指令是错误的,那么会继续读取下一条,所以如果发送的报文中可以控制其中一行,就可以将其修改为Redis指令,分批执行指令,完成攻击。如果可以控制多行报文,那么可以在一次连接中完成攻击。
2. 攻击MySQL
MySQL分为客户端和服务端,由客户端连接服务端有4种方式:
- UNIX套接字
- 内存共享
- 命名管道
- TCP/IP套接字
我们进行攻击依靠第4种方式,MySQL客户端连接时会出现两种情况,即是否需要密码认证。
- 当需要密码认证时,服务器先发送salt,然后客户端使用salt加密密码再验证
- 不需要密码认证时,将直接使用第四种方法发送数据包
所以在非交互模式下登录MySQL数据库只能在空密码未授权的情况下进行
3. PHP-FPM攻击
利用条件如下:Libcurl,版本高于7.45.0;PHP-FPM,监听端口,版本高于5.3.3;知道服务器上任意一个PHP文件的绝对路径。
首先,FastCGI本质上是一个协议,在CGI的基础上进行了优化。PHP-FPM是实现和管理FastCGI的进程。在PHP-FPM下如果通过FastCGI模式,通信还可分为两种:TCP和UNIX套接字(socket)。
TCP模式是在本机上监听一个端口,默认端口号为9000,Nginx会把客户端数据通过FastCGI协议传给9000端口,PHP-FPM拿到数据后会调用CGI进程解析。
既然通过FastCGI与PHP-FPM通信,那么我们可以伪造FastCGI协议包实现PHP任意代码执行。FastCGI协议中只可以传输配置信息、需要被执行的文件名及客户端传进来的GET、POST、Cookie等数据,然后通过更改配置信息来执行任意代码。
在php.ini中有两个非常有用的配置项。❖
-
auto_prepend_file:在执行目标文件前,先包含auto_prepend_file中指定的文件,并且可以使用伪协议如
php://input
。 - auto_append_file:在执行目标文件后,包含auto_append_file指向的文件。
php://input
是客户端HTTP请求中POST的原始数据,如果将auto_prepend_file设定为php://input
,那么每个文件执行前会包含POST的数据,但php://input
需要开启allow_url_include,官方手册虽然规定这个配置规定只能在php.ini中修改,但是FastCGI协议中的PHP_ADMIN_VALUE选项可修改几乎所有配置(disable_functions不可修改),通过设置PHP_ADMIN_VALUE把allow_url_include
修改为True
,这样就可以通过FastCGI协议实现任意代码执行。