GXYCTF2019-禁止套娃php
进去一句话,啥都没有。扫个目录,/.git返回429
直接访问返回403,说明存在
直接访问:git
在没有其余明显目录,且无hint的状况下。
考虑存在git泄漏。
常见的源码泄漏有.git与.svn,对于git泄漏咱们可使用Githack来拿下。
https://github.com/lijiejie/G...github
果真存在,index.php源码到手shell
<?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']); } else{ die("还差一点哦!"); } } else{ die("再好好想一想!"); } } else{ die("还想读flag,臭弟弟!"); } } // highlight_file(__FILE__); ?>
原来所谓禁止套娃就是指饶掉这三个正则。下面逐步分析。数组
直接访问flag.php,无404但不回显。
那么咱们的目的是,要求eval函数执行,而且执行读取flag.php的命令。
那么一个个if来分析svn
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp']))
要求必须用data://,filter://,php://,phar://等伪协议。
这样不能够用file://读取了。函数
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))
第二个正则关键在于\((?R)?\)
,(?R)
表示引用当前表达式。
其中?
引用是可选项,匹配成功后用NULL替换。
那么一个合法的表达式能够是a(b();)工具
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp']))
过滤一些函数。spa
下面列出一些函数,
1.scandir()
若是咱们要看当前目录,须要给这个函数一个变量能够表示当前声明。
但这么作须要提早声明一个变量,显然不可行。
那么php中有没有相似常量来指当前目录呢?
2.一个常量
从上面能够看到,localeconv是一个数组,因此咱们须要current取出数组中的单元,从而可让scandir读取。这就是所谓无参数执行命令。
但因为正则的限制,current须要换成其同名函数pos
构造一个payload的指针
/?exp=print\_r(scandir(pos(localeconv())));
成功读取到目录位置。如今问题是:如何读取数组的元素(输出)?
这就涉及到了php的数组指向函数:
那么能够看到flag.php在倒数第二个位置,目前指针在0处。正常状况下是指不到第二个的。如何呢?
又是另外一个函数:
那么,就能够用array_reverse()先反转,而后用next读取第二个,以后用highlight_file()读取便可
highlight_file(next(array_reverse(scandir(pos(localeconv())))));
成功拿下:
一题一个知识点,累觉不爱。
http://www.pdsdt.lovepdsdt.com/index.php/2019/11/06/php_shell_no_code/#comment-15 http://xxlegend.com/2015/04/01/SVN和GIT信息泄漏利用原理及现状/