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
相关推荐
OpenTiny社区3 小时前
操作ArkTS页面跳转及路由相关心得
前端·typescript·web·opentiny
сокол5 小时前
【网安-Web渗透测试-免杀系列】内存免杀(无文件落地)
windows·网络安全
学习溢出7 小时前
【网络安全】追踪PowerShell命令历史
安全·网络安全
还是鼠鼠8 小时前
AI掘金头条新闻系统 (Toutiao News)-获取用户信息
后端·python·mysql·fastapi·web
Sombra_Olivia8 小时前
Vulhub 中的 cmsms CVE-2019-9053 & CVE-2021-26120
安全·web安全·网络安全·渗透测试·vulhub
大方子10 小时前
【PolarCTF】bllbl_ser1
网络安全·polarctf
Chengbei1110 小时前
小程序 AI 渗透新工具MCP!打通调试与安全检测、网络抓包、接口分析、越权检测一站式实现
人工智能·安全·web安全·搜索引擎·网络安全·小程序·系统安全
大数据魔法师11 小时前
Streamlit(十二)- API 参考文档(五)- 输入组件
python·web
humors22111 小时前
Windows运维与安全场景合集(不定期更新)
大数据·运维·服务器·程序人生·网络安全