SSRF

SSRF是什么

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。

SSRF漏洞原理

可以理解为,服务器可以从其他的服务器获取信息。然而却没有对这个服务器的地址做限制

就比如说,我们可以指定一个有缺陷的url,或者自己的作为外部服务器。

SSRF漏洞挖掘

分享

通过URL分享网页的内容

转码

通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览:由于手机屏幕大小的关系,直接浏览网页内容的时候会造成许多不便,因此有些公司提供了转码功能,把网页内容通过相关手段转为适合手机屏幕浏览的样式。例如百度、腾讯、搜狗等公司都有提供在线转码服务

翻译

通过URL地址翻译对应文本的内容。提供此功能的国内公司有百度、有道

图片、文章收藏功能

图片、文章收藏中的文章收藏就类似于分享功能中获取URL地址中title以及文本的内容作为显示,目的还是为了更好的用户体验,而图片收藏就类似于功能四、图片加载。

http://title.xxx.com/title?title=http://title.xxx.com/as52ps63de

例如title参数是文章的标题地址,代表了一个文章的地址链接,请求后返回文章是否保存,收藏的返回信息。如果保存,收藏功能采用了此种形式保存文章,则在没有限制参数的形式下可能存在SSRF

未公开的api实现以及其他调用URL的功能

图片加载与下载

通过URL地址加载或下载图片,图片加载远程图片地址此功能用到的地方很多,但大多都是比较隐秘,比如在有些公司中的加载自家图片服务器上的图片用于展示

URL关键字中寻找

share
wap
url
link
src
source
target
u
display
sourceURl
imageURL
domain

产生SSRF的相关函数

PHP

  1. file_get_contents

    将整个文件读入到字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    if (isset($_POST['url']))
    {
    $content = file_get_contents($_POST['url']); //获取用户输入的url
    $filename ='./images/'.rand().';img1.jpg'; //蒋文件储存为为一个
    file_put_contents($filename, $content); //将获取的内容写入文件
    echo $_POST['url']; //输出用户输入的url
    $img = "<img src=\"".$filename."\"/>"; //输出图片
    }
    echo $img;
    ?>

  2. sockopen

    以下代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    function GetFile($host, $port, $link)
    {
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30); // 使用fsockopen函数建立与指定主机和端口的连接,设置超时时间为30秒
    if (!$fp) {
    echo "$errstr (错误号 $errno) \n"; // 如果连接失败,输出错误信息
    } else {
    $out = "GET $link HTTP/1.1\r\n"; // 构建HTTP GET请求头,使用HTTP/1.1协议,这对于保持连接很重要
    $out .= "Host: $host\r\n"; // 添加主机信息到请求头
    $out .= "Connection: Close\r\n\r\n"; // 添加连接关闭信息到请求头
    $out .= "\r\n"; // 添加空行,表示请求头结束
    fwrite($fp, $out); // 发送请求头到服务器
    $contents = ''; // 初始化内容变量
    while (!feof($fp)) {
    $contents .= fgets($fp, 1024); // 逐行读取服务器响应内容并添加到内容变量
    }
    fclose($fp); // 关闭连接
    return $contents; // 返回获取的内容
    }
    }

  3. curl_exec

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php 
    if (isset($_POST['url']))
    {
    $link = $_POST['url'];
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_POST, 0);
    curl_setopt($curlobj,CURLOPT_URL,$link);
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($curlobj);
    curl_close($curlobj);

    $filename = './curled/'.rand().'.txt';
    file_put_contents($filename, $result);
    echo $result;
    }
    ?>

  4. curl_exec

    关于curl

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php
    // 检查是否设置了POST请求中的'url'参数
    if (isset($_POST['url'])) {
    $link = $_POST['url']; // 获取POST请求中的'url'参数值

    $curlobj = curl_init(); // 初始化一个cURL会话
    curl_setopt($curlobj, CURLOPT_POST, 0); // 设置cURL请求为GET请求
    curl_setopt($curlobj, CURLOPT_URL, $link); // 设置要访问的URL
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置cURL执行后不直接输出结果,而是返回到变量中
    $result = curl_exec($curlobj); // 执行cURL请求并将结果保存到$result变量
    curl_close($curlobj); // 关闭cURL会话

    $filename = './curled/' . rand() . '.txt'; // 生成一个随机文件名
    file_put_contents($filename, $result); // 将cURL获取的结果保存到文件中
    echo $result; // 输出cURL获取的结果
    }

  5. fsockopen

java

仅支持 HTTP/HTTPS 协议的类:HttpClient 类、HttpURLConnection 类、 OkHttp 类、 Request

支持 sun.net.www.protocol 所有协议的类:URLConnection 类、URL 类、ImageIO 类

SSRF中URL的伪协议

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

SSRF漏洞利用(危害)

读取敏感文件

  1. 使用file协议读取文件内容

    file://

    本地文件传输协议,用于读取本地计算机里面的文件。

    就像是使用win里面的打开或者右键打开

    • 读取/etc/password

      在Linux 中 /etc/passwd文件中每个用户都有一个对应的记录行,它记录了这个用户的一些基本属性。

      系统管理员经常会接触到这个文件的修改以完成对用户的管理工作。

    • 读取/etc/host

      hosts文件主要作用是定义IP地址和主机名的映射关系,是一个映射IP地址和主机名的规定。可以用文

      本文件打开!当用户在浏览器中输入一个网址时,系统会首先自动从hosts文件中寻找对应的IP地址,

      一旦找到,浏览器会立即打开对应网页,如果没有找到,则浏览器会将网址提交DNS服务器进行IP地址解析。简单来说就是负责ip地址与域名快速解析的文件,读取文件可以得到内网所在网段。

      可以理解为这个是本地的DNS解析器

探测内网的服务

  1. 使用dict协议

    dict://

    dict 协议是一个在线网络字典协议,这个协议是用来架设一个字典服务的。不过用的比较

    少,所以网上基本没啥资料(包括谷歌上)。在SSRF漏洞利用中,常常用来探测内网的应用信息

攻击内网应用

  1. 通过dict://协议攻击redis

    可以导致任意用户利用ssrf漏洞攻击内网中的未授权Redis以及读取Redis的数据。

    攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,如果运行 redis 的用户是 root 用户,攻击者可以通过写定时任务的方式进行反弹shell。

    测试是否存在漏洞

    dcit://ip:port/info

    写定时任务

    写定时任务的目录

    centos,在/var/spool/cron/目录下

    ubuntu 的定时任务在 /var/spool/cron/crontabs/ 目录下

    可以根据服务器是否存在以下文件判断服务器的信息

    # Centos

    /etc/redhat-release

    # Ubuntu

    /etc/lsb-release

SSRF中url解码编码

HTTP

现在我们有一个url是:

http://ip:host/xxx

如果现在xxx里含有%xx格式,这个数据先是被接受之后才会被解码

gopher

还是这个url

http://ip:host/xxx

如果xxx里面含有%xx格式的数据,那么会在发送方就处理成接收方接受的数据

漏洞类型

  • 有回显:页面有返回具体内容。

  • 无回显:页面没有返回具体内容

SSRF利用

内网访问

ctfhub 技能树

伪协议读取文件

伪协议:

类型
file:///
dict://
sftp://
ldap://
tftp://
gopher://

这里使用ctfhub技能树的题做演示

file:///var/www/html/flag.php

注意这个是web目录

端口扫描

端口扫描使用的是dict://协议

但是请你注意,我们使用dict扫描出端口之后,需要使用url直接访问,而不是继续使用dict协议

下面是做题逻辑,他说了端口在8000~9000,直接使用bp扫

image-20231130140802475

访问:

image-20231130141033863

http://challenge-a30959492eed8566.sandbox.ctfhub.com:10800/?url=127.0.0.1:8017

POST请求

这次还是使用ctfhub 的技能树作为例子

题目是:

这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年

要求我们发一个POST请求包,但是这个发包需要利用gopher协议

首先我们可以利用index.php的url访问flag.php和index.php

URL Bypass

ctfhub技能树里面的一道题

打开过后发现必须带有

http://notfound.ctfhub.com

这里我们需要知道一个东西

http://www.baidu.com@192.168.0.1/

请求的都是192.168.0.1里面的内容

是所以我们直接构造

challenge-a1e077f43b569033.sandbox.ctfhub.com:10800/?url=http://notfound.ctfhub.com@127.0.0.1/flag.php

IP Bypass

这道题我觉得比较鸡贼,因为他会有到你想ip,ban掉了127/172

但是我们有一个回环地址localhost

所以直接构造poc

?url=localhost/flag.php

302跳转

不知道这个怎么回事,我尝试在http添加Localtion字段发现没有什么用,直接访问这个就没有问题

?url=localhost/flag.php

redis

使用ctfhub 进行演示

image-20240509173630164

可以发现存在ssrf

然后尝试使用redis 对内网进行攻击

image-20240509191455708

制作出webshell

然后尝试使用访问,会发现不行,得再次url 加密一下

image-20240509191615554

然后访问

出现了504 但是不要紧

这个是时候shell.php 是已经写好的

image-20240509191715142

常见的问题记录

为什么ssrf 可以攻击到内网

协议支持与网络边界穿透(技术实现层)

  1. ssrf 利用服务器作为跳板,使用http,https,ftp 等协议实现内网横向移动。
    由于服务器通常具备出站访问权限,能够绕过防火墙和NACL 等边界保护措施,直接访问内部禁止外部访问的服务(redis/mysql)
  2. 示例:AWS元数据服务(169.254.169.254)仅允许本地访问,但通过SSRF可间接获取IAM凭证(通过SSRF获取IAM角色临时凭证,直接接管云账户权限)

信任模型突破(安全假设层)

  1. 内网服务一般都存在“隐私信任”假说,认为请求源自内部可信任的内部节点,因此可以省去很多信任认证
    • 省去身份认证(比如k8s api)
    • 简化权限校验(直接信任来源的ip)
    • 使用弱化的安全协议(http)

网络架构缺陷(系统设计层)

  1. 缺乏防御
    • 没有实现微隔离,微分段
    • 缺少内部服务的双向认证
    • 没有对内部的api 进行双向的认证
  2. 典型的脆弱场景
    • 云上的vpc 内网默认是互通的
    • 传统企业网扁平化架构
    • 容器集群内部Overlay网络

攻击面扩展(漏洞利用层)

  1. 协议处理漏洞的链式利用:

    • 利用gopher协议攻击内网Redis未授权访问

    • 通过file协议读取本地配置文件

      Gopher:一种早期的文档传输协议,支持构造任意TCP请求(包括HTTP/HTTPS/SMTP等)

      攻击优势:可精确控制请求内容,绕过部分协议限制,常用于攻击无认证的TCP服务

      常见的文件特征

      1
      2
      3
      4
      /proc/self/environ	容器环境变量(含API密钥)
      /var/lib/kubelet/kubeconfig Kubernetes集群凭证
      /run/secrets/aws/credentials AWS CLI访问密钥
      /var/run/docker.sock Docker守护进程控制接口
    • 使用dict协议扫描内网端口

  2. 云原生环境下的特殊风险:

    • 访问Kubernetes API Server

    一些常见的风险api

    1
    2
    3
    4
    /apis/rbac.authorization.k8s.io/v1	查看/修改RBAC权限
    /api/v1/secrets 获取数据库密码等敏感信息
    /apis/apps/v1/daemonsets 部署全节点后门
    /api/v1/nodes/proxy 直接访问节点上的kubelet接口
    • 获取容器编排系统的服务账号令牌
  3. 云上VPC内网默认互通 攻击方式
    同一VPC内子网/实例默认允许任意协议端口的双向通信(如AWS/AliCloud默认配置)

    • 可以通过ssrf 获取IAM 角色临时凭证,直接接管云账户

    微服务架构中内部API调用无认证(如Kafka/Consul管理接口)

    • 使用ssrf 直接调用实现数据销毁
  4. 传统企业网扁平化架构
    解释什么是传统企业网扁平化架构

    IP地址连续分配:如使用192.168.0.0/16大网段直接部署所有业务系统
    核心-接入层直连:缺乏安全区域划分,防火墙仅部署在互联网边界

    攻击方式:

    a. ARP欺骗高效化:

    • 在扁平网络中可快速定位核心业务系统(如通过扫描10.0.0.0/8段)
    • 利用SSRF发起内网ARP洪水攻击,扰乱网络通信

    b. 协议漏洞利用

    • windows 系统没有及时的打补丁

      利用SSRF触发内网SMB协议漏洞(如永恒之蓝)

      1
      requests.get("http://vuln-server/ssrf?url=smb://internal-host/exploit")

    c. 工控系统暴露

    • 制造业常见场景:ERP系统与PLC控制器同网段
    • 通过SSRF访问modbus://plc-ip:502直接操控生产设备

    典型案例

    1
    外网OA系统SSRF → 访问内网Jenkins未授权API(http://10.10.10.100:8080/createItem) → 部署恶意构建任务 → 获取服务器权限

防御视角补充(展示全面认知)

  1. 零信任架构的实施可有效缓解:服务间认证、最小权限原则、动态访问控制
  2. 网络层需实现:出口流量过滤、协议白名单、内部服务强制TLS加密
  3. 应用层防御:输入校验标准化库、DNS重绑定防护、响应内容过滤

SSRF
https://tsy244.github.io/2023/11/28/web/SSRF/
Author
August Rosenberg
Posted on
November 28, 2023
Licensed under