buuctf [第二章 web进阶]SSRF Training

[第二章 web进阶]SSRF Training

    • 源码审计
    • 分析:
    • gethostbyname函数私有地址绕过
    • var_dump(flag.php)

buuctf [第二章 web进阶]SSRF Training_第1张图片

题目已给出源码

源码审计

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

GET方式传入url赋值给$url
检测url是否为空
不为空则执行safe_request_url函数

function check_inner_ip($url) 
{ 
    $match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url); 
    if (!$match_result) 
    { 
        die('url fomat error'); 
    } 
    try 
    { 
        $url_parse=parse_url($url); 
    } 
    catch(Exception $e) 
    { 
        die('url fomat error'); 
        return false; 
    } 
    $hostname=$url_parse['host']; 
    $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; 
} 

safe_request_url函数有个通过check_inner_ip($url)进行校验的判断
正则匹配然后解析url
过滤了一些私有ip,应该是可以通过这些ip访问本机文件

if (check_inner_ip($url)) 
    { 
        echo $url.' is inner ip'; 
    } 

check_inner_ip函数:
首先preg_match正则匹配,检查传入的url是否是url格式

    else 
    {
        $ch = curl_init(); 
        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格式,则继续执行else
curl_xxxx

1. curl_close — 关闭一个cURL会话
2. curl_copy_handle — 复制一个cURL句柄和它的所有选项
3. curl_errno — 返回最后一次的错误号
4. curl_error — 返回一个保护当前会话最近一次错误的字符串
5. curl_escape — 使用 URL 编码给定的字符串
6. curl_exec — 执行一个cURL会话
7. curl_file_create — 创建一个 CURLFile 对象
8. curl_getinfo — 获取一个cURL连接资源句柄的信息
9. curl_init — 初始化一个cURL会话
10. curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄
11. curl_multi_close — 关闭一组cURL句柄
12. curl_multi_exec — 运行当前 cURL 句柄的子连接
13. curl_multi_getcontent — 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流
14. curl_multi_info_read — 获取当前解析的cURL的相关传输信息
15. curl_multi_init — 返回一个新cURL批处理句柄
16. curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
17. curl_multi_select — 等待所有cURL批处理中的活动连接
18. curl_multi_setopt — 为 cURL 并行处理设置一个选项
19. curl_multi_strerror — Return string describing error code
20. curl_pause — Pause and unpause a connection
21. curl_reset — Reset all options of a libcurl session handle
22. curl_setopt_array — 为cURL传输会话批量设置选项
23. curl_setopt — 设置一个cURL传输选项
24. curl_share_close — Close a cURL share handle
25. curl_share_init — Initialize a cURL share handle
26. curl_share_setopt — Set an option for a cURL share handle.
27. curl_strerror — Return string describing the given error code
28. curl_unescape — 解码给定的 URL 编码的字符串
29. curl_version — 获取cURL版本信息

题目中主要用到

curl_init — 初始化一个cURL会话
curl_setopt — 设置一个cURL传输选项
curl_exec — 执行一个cURL会话
curl_getinfo — 获取一个cURL连接资源句柄的信息
curl_close — 关闭一个cURL会话

以上的curl部分大致功能就是初始化,然后获取一个网页

if ($result_info['redirect_url']) 
        { 
            safe_request_url($result_info['redirect_url']); 
        } 
        curl_close($ch); 
        var_dump($output);

if的作用就是如果没有获取到信息,就重复获取,重复执行safe_request_url函数
最后把exec后的数据dump出来
var_dump($output);之后就出函数了
接下来将parse_url后的url赋值给$url_parse
如果parse_url执行失败,则返回false

分析:

我们最终的目的是要curl 127.0.0.1/flag然后得到dump出来的数据
hostname得到的是前面url_parse分离出来的host部分
ip得到的是将hostname转换为ip地址后的数值(就是把url转成ip地址)

gethostbyname函数私有地址绕过

绕过这个函数只需要把它的host字段改成不是以127,10,172.16,192.168,开头的私有ip

payload:http://a:@127.0.0.1:[email protected]

这里它取到的host为baidu.com
可以绕过gethostbyname函数

var_dump(flag.php)

payload:http://a:@127.0.0.1:[email protected]/flag.php 

buuctf [第二章 web进阶]SSRF Training_第2张图片
buuctf [第二章 web进阶]SSRF Training_第3张图片

你可能感兴趣的:(web,web安全,php)