[HarekazeCTF2019]Avatar Uploader 1

[HarekazeCTF2019]Avatar Uploader 1

考点

wp

源码是给出的,登录之后,有一个文件上传功能

先看代码,在 config.php 中定义了一些常量,客户端cookie中使用session字段表示PHPSESSID,定义上传目录uploads

define('CLIENT_SESSION_ID', 'session');
define('SECRET_KEY', getenv('SECRET_KEY'));
define('UPLOAD_DIR', __DIR__ . '/uploads');

然后在 upload.php 中判断文件大小,并使用 FILEINFO 判断上传图片类型,上传图片只能是 png 类型

// check file size
if ($_FILES['file']['size'] > 256000) {
  error('Uploaded file is too large.');
}

// check file type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$type = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
if (!in_array($type, ['image/png'])) {
  error('Uploaded file is not PNG format.');
}

后面再用 getimagesize 判断文件像素大小,并且再进行一次类型判断,如果不是 png 类型就给出 flag

// check file width/height
$size = getimagesize($_FILES['file']['tmp_name']);
if ($size[0] > 256 || $size[1] > 256) {
  error('Uploaded image is too large.');
}
if ($size[2] !== IMAGETYPE_PNG) {
  // I hope this never happens...
  error('What happened...? OK, the flag for part 1 is: <code>' . getenv('FLAG1') . '</code>');
}

在这两种判断上传图片类型的函数中,有一个很有趣的现象, FILEINFO 可以识别 png 图片( 十六进制下 )的第一行,而 getimagesize 不可以,代码如下

<?php
$file = finfo_open(FILEINFO_MIME_TYPE);
  
var_dump(finfo_file($file, "test"));
  
$f = getimagesize("test"); 
var_dump($f[2] === IMAGETYPE_PNG);

结果如下

直接上传这个文件就可以获取 flag 了

最后更新于