从0到1的ctfer--SSRF Training Writeup

从0到1的ctfer--SSRF Training Writeup


题目页面如下:

发现只有intersting_challenge能交互,点进去是源码:


 <?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
    } 
    catch(Exception $e) 
    { 
        die('url fomat error'); 
        return false; 
    } 
    $hostname=$url_parse['host'];   //提取解析后的host(主机名或ip)
    $ip=gethostbyname($hostname); 
    $int_ip=ip2long($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
} 

function safe_request_url($url) 
{ 
     
    if (check_inner_ip($url)) 
    { 
        echo $url.' is inner ip'; 
    } 
    else 
    {
        $ch = curl_init();   //发送curl请求
        curl_setopt($ch, CURLOPT_URL, $url); 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
        curl_setopt($ch, CURLOPT_HEADER, 0); 
        $output = curl_exec($ch); 
        $result_info = curl_getinfo($ch); 
        if ($result_info['redirect_url']) 
        { 
            safe_request_url($result_info['redirect_url']); 
        } 
        curl_close($ch); 
        var_dump($output); 
    } 
     
} 

$url = $_GET['url']; 
if(!empty($url)){ 
    safe_request_url($url); 
} 

?> 

过滤了一些内网ip。



解法1.绕过对hostname的检查

http://a:@127.0.0.1:80@example.com/flag.php

url解析时通常会将最后一个@符号后面的内容作为ip地址解析,这样example.com就被解析为了hostname,但实际ip还是127.0.0.1,从而绕过了gethostname函数。



解法2.直接使用未被过滤的ip地址

既然过滤了部分内网ip,那么使用没被过滤的ip不就行了?比如0.0.0.0就没被过滤。

http://0.0.0.0/flag.php



本题flag:n1book{ug9thaevi2JoobaiLiiLah4zae6fie4r}

posted @ 2025-05-18 20:19  埃克斯X  阅读(15)  评论(0)    收藏  举报