关于<?php exit;?>"的绕过问题

在Moctf中看到一道题目:

<?php
  show_source(__FILE__);
  $c="<?php exit;?>";
  @$c.=$_POST['c'];
  @$filename=$_POST['file']; 
  if(!isset($filename))                    
  {                                       
    file_put_contents('tmp.php', ''); 
  }                                 
  @file_put_contents($filename, $c);
  include('tmp.php');
?>

这里简单分析下题目,并记录下解题过程。

我们来看第二行的<?php exit;?>,这句话在开头增加了exit过程,导致即使我们成功写入一句话,也执行不了(这个过程在实战中十分常见,通常出现在缓存、配置文件等等地方,不允许用户直接访问的文件,都会被加上if(!defined(xxx))exit;之类的限制)。在往下看,我们要post一个c与file两个变量,而c不用说就是用来绕过exit并执行命令的。而下面的file_put_contents函数的含义为可以将一个字符串写入文件。所以我们简单分析得到,我们应该输入一个c用来绕过exit,并让c中的内容写入filename所代表的变量内容里。

又因为这里文件包含了tmp.php,所以我们很容易想到filename应该与tmp.php相关。

也就是说,这道题目的关键点在于我们如何绕过这句话。

 

这里引入一篇blog

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

这里讲述了可以利用php伪协议进行绕过,简单来说,我们如果使用  file=php://filter/write=convert.base64-decode  来进行对file变量的处理,既以base64的编码来读。而我们为什么要使用base64呢?因为<?php exit;?>中"<、?、;、>"等符号解码时都会被忽略,所以命令就变成了-->    “phpexit”。也就达到了我们绕过了这个函数。之后我们要想执行我们所想的代码,可以在phpexit这七个字符后任意加一个字母(因为base64是4个字符一组进行解码的),所以我们可以写成

file=php://filter/write=convert.base64-decode/resource=tmp.php

也就是说以base64为编码对tmp.php读取。而写入tmp.php的内容是什么呢?

这里我们可以嵌入php命令来写入tmp.php中

将命令用base64编码,得到PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==,然后在原有的(phpexit)基础上添加上述base64代码,(****这里我们为了让其成为八位,所以任意在后面加一个a)得到

phpexitaPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

 

而传过去的值为t=aPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

 

也就得到flag了,,233333

posted @ 2018-03-18 21:15  Ping_ing  阅读(4721)  评论(0编辑  收藏  举报