小工具知识网

当前位置: 首页 > 行业知识 > ssrf刷题——buu [第二章 web进阶]SSRF Training [网鼎杯 2020 玄武组]SSRFMe

行业知识

ssrf刷题——buu [第二章 web进阶]SSRF Training [网鼎杯 2020 玄武组]SSRFMe

2026-11-15 22:08:48 来源:互联网转载

[第二章 web进阶]SSRF Training

点击即可获得源码

  

源码审计

get方式传参

是否存在url

url不为空就调用safe_request_url()函数

来看一下这个safe_request_url和check_inner_ip两个需要绕过的过滤函数

function check_inner_ip($url) {     $match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url);     if (!$match_result)     {         die('url fomat error');     }     //检查请求的url是否为正确的格式    try     {         $url_parse=parse_url($url);     }     //parse_url 是 PHP 的一个内置函数。    它用于解析 URL,并返回一个关联数组,包含了 URL 的各个部分,    比如协议、主机名、路径等。    parse_url 函数可以帮助开发者在处理 URL 时更方便地提取其中的信息,例如在这段代码中,它被用来解析用户输入的 URL。    catch(Exception $e)     {         die('url fomat error');         return false;     }     $hostname=$url_parse['host'];     $ip=gethostbyname($hostname);     $int_ip=ip2long($ip);    //ip2long 是 PHP 中的一个内置函数,用于将 IPv4 地址转换为对应的长整型数字。IPv4 地址由四个十进制数(每个数范围在 0 到 255 之间)组成,用点分十进制表示(例如:"192.168.1.1")。ip2long 函数将这种点分十进制表示的 IPv4 地址转换为一个长整型数字,方便进行比较和处理。这个长整型数字可以更有效地存储和比较,通常用于 IP 地址的操作和计算。     return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; } //这行代码是在检查给定的 IP 地址是否属于内部 IP 地址范围:    ip2long('127.0.0.0'): 将 IPv4 地址 "127.0.0.0" 转换为长整型数字。    >> 24: 对长整型数字进行右移 24 位,这相当于将 IP 地址的前 3 个字节移出,只留下第一个字节。    == $int_ip >> 24: 比较经过右移操作的 "127.0.0.0" 的结果是否与输入的 IP 地址的前 3 个字节相同。如果相同,则说明该 IP 地址属于 "127.0.0.0/8" 的范围。同样的逻辑被应用于其他内部 IP 地址范围:    "10.0.0.0/8" 被右移 24 位后与输入 IP 地址的前 3 个字节进行比较。    "172.16.0.0/12" 被右移 20 位后与输入 IP 地址的前 3 个字节进行比较。    "192.168.0.0/16" 被右移 16 位后与输入 IP 地址的前 3 个字节进行比较。如果给定的 IP 地址匹配了这些范围中的任何一个,则返回 true,否则返回 false。 //综上所述,这里就是一个IP白名单,不允许我们输入类似127.*.*.*、10.*.*.*、172.16.*.*、192.168.*.*
function safe_request_url($url) {          if (check_inner_ip($url))     {         echo $url.' is inner ip';     }     else     {        $ch = curl_init();  //初始化新的会话,返回 cURL 句柄,供curl_setopt()、 curl_exec() 和 curl_close() 函数使用        curl_setopt($ch, CURLOPT_URL, $url); //访问的域名        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);         curl_setopt($ch, CURLOPT_HEADER, 0);         //curl_setopt函数参数解释:https://www.cnblogs.com/lilyhomexl/p/6278921.html        $output = curl_exec($ch); //执行一个cURL会话并且获取相关回复        $result_info = curl_getinfo($ch);         //php curl请求在curl_exec()函数执行之后,可以使用curl_getinfo()函数获取CURL请求输出的相关信息        if ($result_info['redirect_url'])         {             safe_request_url($result_info['redirect_url']);         }         curl_close($ch);         //if的作用就是如果没有获取到信息,就重复获取,重复执行safe_request_url函数//最后把exec后的数据dump出来//var_dump($output);之后就出函数了//接下来将parse_url后的url赋值给$url_parse//如果parse_url执行失败,则返回false        var_dump($output);     }      } 

绕过

我们最终的目的是要curl 127.0.0.1/flag然后得到dump出来的数据

那么该怎么绕过这两重检测呢

parse_url函数的绕过

PHP: parse_url - Manual

此函数返回一个关联数组,包含现有 URL 的各种组成部分。如果缺少了其中的某一个,则不会为这个组成部分创建数组项。组成部分为:

  • scheme – 如 http
  • host       域名
  • port        端口
  • pass  
  • path   路径
  • query – 在问号 ? 之后
  • fragment – 在散列符号 # 之后

      此函数并 不 意味着给定的 URL 是合法的,它只是将上方列表中的各部分分开。parse_url() 可接受不完整的 URL,并尽量将其解析正确。
      注: 此函数对相对路径的 URL 不起作用。

    demo

      

    这是输出

    但是如果我们输入http://www.baidu.com@2333.com/suning?v=1&k=2#id

    那么结果就会变成

    host就会变成@后面的字符

    这样我们的host就可控了

    回到题目

    如果我们输入'http://127.0.0.1:80@baidu.com/flag.php'

    这样也无法正确绕过

    因为curl_getinfo()函数也无法解析成127.0.0.1

    在前面再加一个@

    这样curl_getinfo()函数解析的是127.0.0.1:80

    而parse_url函数解析的host是www.baidu.com

    这样就成功绕过

    payload:

    http://c47efe80-3429-4c17-afa8-b11ed8e4fa8f.node5.buuoj.cn:81/challenge.php?url=http://@127.0.0.1:80@www.baidu.com/flag.php

    [网鼎杯 2020 玄武组]SSRFMe

     

    代码审计

    和上一题的代码菀菀类卿

    也是get方式传参

    不对

    是一模一样的过滤

    试了一下

    还是有点不一样

    正则匹配不同 这里不仅支持http伪协议还支持https|gopher|dict

    但是后面的匹配是正常的啊

    看不懂

    可能@被ban了?

    不知道

    还可以用0.0.0.0绕过

    也可以用环回地址绕过

    我自己试下来可以用的有

    ?url=http://0x7F000001/hint.php

    ?url=http://[0:0:0:0:0:ffff:127.0.0.1]/hint.php

    ?url=http://0.0.0.0/hint.php

    ——————————————更新——————————————

    上面那个问题  大佬给出答案

    然后我们终于来到第二步

    if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){  highlight_file(__FILE__);}if(isset($_POST['file'])){  file_put_contents($_POST['file'],"

上一篇:建站服务器镜像怎么用啊?

下一篇:揭秘MVC5源码深度解析之旅,框架核心机制探索