BUUCTF-[第二章 web进阶]SSRF Training

步骤

打开网站可以看到存在flag.php,所以是要通过SSRF获取flag.php的内容。在intersting chanllenge中查看源代码。

代码分析

php 复制代码
<?php 
highlight_file(__FILE__);        //显示源码
function check_inner_ip($url) 
{ 
    $match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url); //正则匹配是否含有http,https
    if (!$match_result) 
    { 
        die('url fomat error'); 
    } 
    try 
    { 
        $url_parse=parse_url($url); //解析url,返回一个关联数组,包含了url的各个部分,如协议,主机等
    } 
    catch(Exception $e) 
    { 
        die('url fomat error'); 
        return false; 
    } 
    $hostname=$url_parse['host'];  //获取主机名
    $ip=gethostbyname($hostname);     //通过主机名获取ip地址,即dns解析
    $int_ip=ip2long($ip);             //将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是否属于内网
} 

function safe_request_url($url) 
{ 
     
    if (check_inner_ip($url))   //调用检查是否是内网ip的函数
    { 
        echo $url.' is inner ip'; 
    } 
    else 
    {
        $ch = curl_init();     //初始化cURL会话
        curl_setopt($ch, CURLOPT_URL, $url);         //设置要请求的url
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //将结果以字符串返回,而不是直接输出
        curl_setopt($ch, CURLOPT_HEADER, 0);         //不包含头部信息
        $output = curl_exec($ch);                     //执行cURL请求
        $result_info = curl_getinfo($ch);             //获取请求的信息
        if ($result_info['redirect_url'])             //如果是重定向,递归调用safe_request_url
        { 
            safe_request_url($result_info['redirect_url']); 
        } 
        curl_close($ch);     //关闭cURL会话
        var_dump($output); 
    } 
     
} 

$url = $_GET['url'];     //接收get参数url
if(!empty($url)){     //判空
    safe_request_url($url); 
} 

?>

漏洞点1

parse_url

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

组成部分:

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

关键点在于此函数并不意味着给定的url是合法的,它只是将url的各个部分分开。即parse_url可以接受不完整的url,并尽量解析正确。

传入的url如果是:http://@127.0.0.1:80@baidu.com/flag.php

返回的数组为:

这里host变为第二个@符号后面的了,所以host可控了,在配合gethostbyname获取域名的ip。

这里第一个@符的作用是让cur_getinfo()函数正确解析,而解析的内容就是第一个@符后面的内容:127.0.0.1:80,这样就成功绕过了。

漏洞点2

gethostbyname

将域名解析为ip,如果是127.0.0.1则会解析为本地所在的公网ip。

payload:

bash 复制代码
http://127.0.0.1:80/flag.php
相关推荐
yv_302 小时前
CTF-IDA
学习·ctf
爱学习的程序媛12 小时前
【Web前端】JavaScript设计模式全解析
前端·javascript·设计模式·web
独角鲸网络安全实验室14 小时前
惊魂零点击!OpenClaw漏洞(ClawJacked)突袭,开发者AI Agent遭无声劫持
人工智能·网络安全·数据安全·漏洞·openclaw·clawjacked·cve-2026-25253
云祺vinchin14 小时前
解读“十五五”热词,容灾备份正成为国家安全基石
安全·网络安全·数据安全·十五五·容灾备份体系
hzhsec14 小时前
挖矿病毒的排查与分析
网络安全·linux安全·病毒排查
大方子19 小时前
【PolarCTF2026年春季挑战赛】新年贺卡
网络安全·polarctf
CDN36019 小时前
CSDN 交流|360CDN 系列产品使用感受与避坑建议
运维·网络安全
CDN36021 小时前
360CDN 产品实测合集:CDN / 高防 / SDK 游戏盾真实反馈
运维·游戏·网络安全
大方子21 小时前
【PolarCTF2026年春季挑战赛】static
网络安全·polarctf