这个界面绝对是我做过的题里面最好看的了
点击interesting challenge显示源码
<?php highlight_file(__FILE__); 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; } function safe_request_url($url) { if (check_inner_ip($url)) { echo $url.' is inner ip'; } 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 = $_GET['url']; if(!empty($url)){ safe_request_url($url); } ?>
这道题可以动态分析加静态分析一起使用
这段代码相当于main函数
GET方式传入url赋值给$url
检测url是否为空
不为空则执行safe_request_url
函数
safe_request_url
函数在一开始就有个通过check_inner_ip($url)
进行校验的判断
接下来看check_inner_ip($url)
函数
check_inner_ip
函数:
首先preg_match
正则匹配,检查传入的url是否是url格式
如果是url格式,则继续执行safe_request_url
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_setopt用法为
好吧,太乱了,直接看例子
以上的curl部分大致功能就是初始化,然后获取一个网页
这个if的作用就是如果没有获取到信息,就重复获取,重复执行safe_request_url
函数
最后把exec
后的数据dump
出来
var_dump($output);
之后就出函数了
接下来将parse_url
后的url
赋值给$url_parse
如果parse_url
执行失败,则返回false
由此可见,parse_url
会将url
分成6个部分
[scheme] => http [host] => hostname [user] => username [pass] => password [path] => /path [query] => arg=value [fragment] => anchor
接下来,是一个赋值过程
hostname
得到的是前面url_parse
分离出来的host
部分
ip
得到的是将hostname转换为ip地址后的数值(就是把url转成ip地址)
int_ip
得到的是经过计算后的纯数字形式的ip地址?
然后是一个return
我们最终的目的是要curl 127.0.0.1/flag
然后得到dump
出来的数据
那么该怎么绕过这两重检测呢
直接传入http://a:@127.0.0.1:80@baidu.com/flag.php
payload:
http://c83f8e90-2d41-465e-b179-6fdf4b9bfa8f.node3.buuoj.cn/challenge.php/?url=http://a:@127.0.0.1:80@baidu.com/flag.php
其中flag.php是在界面给的提示
这个payload的作用就是
让检测到的url
和curl请求的url
不一致
原理我记得好久之前我看wooyun上好像有过,但是我记不住了