阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

那些年我拿下的demo站之方维O2O

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/rz/2019/1010/116729.html

早前一个被我捂烂的漏洞,其实不是要捂的,当注入交到乌云,审核比较忙测试的时候没复现,就给打回来了。我一直想写个详细的再交,结果没时间就没写,这两天上去一看鸡毛都没了,全补完了,shell也掉光了,后台也进不去……

想想算了不挖了。还好我有记笔记的习惯,拿出来分享一下。

以下是笔记。

今天挖了一阵子方维O2O的本地生活系统。这个系统是不开源的,偶然拿到了一个版本的源码,于是有了这次挖洞之旅。

首先翻到了一个注入,拿下了管理员密码。实际上,demo站已经给了一个低权限的管理员账号demo/demo。

登录后台:

image001.png

0x01 鸡肋文件包含漏洞

大概看了一下功能不多,很多敏感功能(如sql操作)demo管理员没权限。

后台一般安全做的比较差,最容易出现的是文件包含漏洞。我很快在源码里找到一处鸡肋文件包含。/admin/Lib/Action/ApiLoginAction.class.php

codehilite">
<?phppublic function install(){    $class_name = $_REQUEST['class_name'];    $directory = APP_ROOT_PATH."system/api_login/";    $read_modules = true;    $file = $directory.$class_name."_api.php";    if(file_exists($file))    {        $module = require_once($file);        $rs = M("ApiLogin")->where("class_name = '".$class_name."'")->count();        if($rs > 0)        {            $this->error(l("API_INSTALLED"));        }    }    else    {        $this->error(l("INVALID_OPERATION"));    }

之所以叫鸡肋,因为需要截断:$directory.$class_name."_api.php";

但我看demo站的php是5.3.3,记得5.3.4以后才解决截断问题。而且fanwe全局并没有addslashes,不影响截断。

所以简单尝试了一下……结果还真截断不了:

image003.png

可能是其他什么原因,反正不能截断。这个鸡肋漏洞是用不了了。再继续翻源码。

0x02 解压缩造成的鸡肋文件上传漏洞

/admin/Lib/Action/FileAction.class.php,一个文件管理的controller。(审计的时候嗅觉也比较重要,看到这个文件名FileAction我就感觉这里会出问题,因为是文件操作)

实际上也没我想的那么糟糕,这里是上传的控制器,上传的地方过滤的比较严,不能直接上传php文件。

但有个上传压缩包并解压的函数:

codehilite">
<?php/** * 图标上传 */public function do_upload_icon(){    require_once APP_ROOT_PATH."system/utils/zip.php";    $archive  = new PHPZip();    $font_dir = APP_ROOT_PATH."public/iconfont";    $result = $archive->unZip($_FILES['file']['tmp_name'], $font_dir);    if(empty($result)||$result==-1)    {        ajax_return(array("status"=>false,"info"=>"图标库更新失败,请手动解压后上传文件到".$font_dir));    }    if ( $dir = opendir( $font_dir."/" ) )    {        while ( $file = readdir( $dir ) )        {            $check = is_dir( $font_dir."/". $file );            if ( !$check )            {                @unlink( $font_dir ."/". $file );            }        }    }    $result = $archive->unZip($_FILES['file']['tmp_name'], $font_dir);          //清空原文件    foreach($result as $k=>$v)    {        $file = APP_ROOT_PATH."public/iconfont/".$k;        $file_arr = explode("/", $file);        foreach($file_arr as $f)        {            if($f=="iconfont.css"||$f=="iconfont.eot"||$f=="iconfont.svg"||$f=="iconfont.ttf"||$f=="iconfont.woff")            {                //echo APP_ROOT_PATH."public/iconfont/".$f;                @rename($file,APP_ROOT_PATH."public/iconfont/".$f);            }        }    }    foreach($result as $k=>$v)    {        $file = APP_ROOT_PATH."public/iconfont/".$k;        @unlink($file);    }    foreach($result as $k=>$v)    {        $file = APP_ROOT_PATH."public/iconfont/".$k;        @rmdir($file);    }    ajax_return(array("status"=>true,"info"=>""));}

看过我去年写的一篇文章:https://www.leavesongs.com/PENETRATION/after-phpcms-upload-vul.html 的同学应该记忆犹新,解压这种操作有很多方法可以传shell。

这里也一样,虽然解压完成后删除了所有原有文件。但其解压了zip文件后,它判断了是否成功,不成功则直接退出了:

codehilite">
<?phpif(empty($result)||$result==-1){    ajax_return(array("status"=>false,"info"=>"图标库更新失败,请手动解压后上传文件到".$font_dir));}

那么我可以构造一个“能够解压一半”的压缩包,解压出部分php文件,然后出错。这样就执行不到“删除”的代码了。

另外一个方法是,我解压的时候修改文件名为“../xxxx.php”,就能把php文件解压到上层目录中,也能避免被删除的命运。

相对的,第二种方法更简单。

于是我构造压缩包,先写好一个webshell,名字就叫aaaaaaaaaaaaaaaaaaaaaa.php。压缩后用editplus编辑:

image005.png

将前4个a替换成“/../”,这样保证了整个文件的长度不变。

再构造本地上传单页:

codehilite">
<form action="http://o2odemo.fanwe.net/m.php?m=File&a=do_upload_icon" method="post" enctype ="multipart/form-data"> <input name="file" type="file" /><input type="submit" value="upload" /></form>

选择后传上去。结果访问发现403:

image007.png

又重新换文件名试了一下,也403。试了一下不存在的.php文件,也403。基本上就是这个规则:public目录下,所有.php文件都是403。

试了txt文件,是可以上传的,说明public目录有写权限:

image009.png

另外尝试了传到其他目录,比如根目录、admin目录,结果404,应该是没写权限。

所以,现在这个洞也是很悲剧很鸡肋的:只有public目录有写权限,但public目录下不能执行php。

0x03 组合漏洞出奇迹

这是突然想到:之前挖的那个鸡肋文件包含,不就正好排上用场了吗?

之前的文件包含漏洞,鸡肋就鸡肋在只能包含php文件,一般情况下如果我们能写入php文件其实就已经getshell了。

但这里不一样,我解压出来一个xxxx_api.php,虽然在public目录下不能执行,但通过文件包含的方法包含之,即可执行我的webshell了。

于是将文件名改成aaaaaaaaaaaa_api.php

image011.png

上传后直接包含,成功:

image013.png

菜刀连接:

image015.png

0x04 法2:apache解析漏洞的逆袭

平时用apache用的不多,一直觉得apache的那个解析漏洞是很老的版本才会有的。但这次还真被我碰上了。

通过上一个漏洞getshell后,再回来思考还有没有别的方法。

这个时候应该换位思考,如果我是运维,我一般会怎样禁用一个目录中的php文件?

很可能是一个正则:^/public/.*.php$,只要HTTP请求符合这个正则,就返回403。

我曾经写过一篇文章:https://www.leavesongs.com/PENETRATION/nginx-deny-exec-php-file.html,讲的是nginx如何正确禁用执行。

文中被绕过的方法实际上就是这个正则:

image017.png

这样通过后缀去禁止执行的方式是很不可靠的,文中我通过pathinfo的方式(xxx.php/xxx)来绕过了这个正则。

这里我也试了用pathinfo,可惜还是返回403 。那么针对这个正则:“^/public/.*.php$”,真的没有办法了吗?

思路就是:有没有其他后缀可以被解析,如果有就能绕过这个正则了。

试了一下phtml、php3/4/5,都不能解析。这个时候我想到apache的解析漏洞了:当apache不识别最后一个后缀时,会向前寻找直到找到一个能够识别的后缀。

于是将名字改成xxx.php.phi:

image019.png

上传发现已经可以解析了:

image021.png

一个解析漏洞的逆袭。

0x05 拿到shell以后的反思

限制执行这个问题,看了看配置文件。果然和我想的一样,是限制了public目录下几个后缀,不允许执行:

codehilite">
<Directory "/fanwe/www/o2odemo/public">    <FilesMatch ".(php|asp|jsp)$">     Deny from all    </FilesMatch></Directory>

并且查看了整个web目录的权限,web目录所有者是root,只有public是777,其他文件全部是755和644,好家伙和我想的一样。看来我自己的直觉现在也是越来越准拉,哈哈~(完)

相关文章