PHP7CMS 无条件前台GETSHELL

Version:2018-10-09
//最新版中以修复此漏洞
这个漏洞很简单,如果作者在写代码的时候考虑到一点点安全方面,其实都可以避免的。
 
01
02
03
04
05
06
07
08
09
10
11
12
// php7cms/Core/Controllers/Api/Api.php
// 52~61 line
public function save_form_data() {
 
     $rt = \Phpcmf\Service::L( 'cache' )->init( 'file' )->save(
         \Phpcmf\Service::L( 'Input' )->get( 'name' ),
         \Phpcmf\Service::L( 'Input' )->post( 'data' ),
         7200
     );
     var_dump( $rt );
     exit ;
}
调用了Cache类中 init 函数,参数分别为get(‘name’)和post(‘data’)。
 
01
02
03
04
05
06
07
08
09
10
11
12
// php7cms/Fcms/Library/Cache.php
  // 112~121 line
  public function init( $handler = '' , $prefix = 'site-' .SITE_ID. '-' ) {
        $config = new \Config\Cache();
        $config ->handler = 'file' ;
        $config ->prefix = $prefix ;
        ! $config ->prefix && $config ->prefix = 'site-' .SITE_ID. '-' ;
        $config ->path = WRITEPATH. 'caching/' ;
        $cache = \Config\Services::cache( $config , 0);
 
        return $cache ;
    }
初始化缓存类,为prefix参数拼接字符串后直接无任何过滤直接传入CI框架的缓存类中,中间框架的执行流程就不在文章里写了。
直接看最后一步
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
// php7cms/System/Cache/Handlers
// 107~125 line
public function save(string $key , $value , int $ttl = 60)
{
   $key = $this ->prefix . $key ;
 
   $contents = [
     'time'         => time(),
     'ttl'         => $ttl ,
     'data'         => $value ,
   ];
 
   if ( $this ->writeFile( $this ->path . $key , serialize( $contents )))
   {
     chmod ( $this ->path . $key , 0640);
 
     return true;
   }
 
   return false;
}
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//324~345 line       
protected function writeFile( $path , $data , $mode = 'wb' )
   {
     if (( $fp = @ fopen ( $path , $mode )) === false)
     {
       return false;
     }
 
     flock ( $fp , LOCK_EX);
 
     for ( $result = $written = 0, $length = strlen ( $data ); $written < $length ; $written += $result )
     {
       if (( $result = fwrite( $fp , substr ( $data , $written ))) === false)
       {
         break ;
       }
     }
 
     flock ( $fp , LOCK_UN);
     fclose( $fp );
 
     return is_int ( $result );
   }
直接写入到缓存目录中,其中并没有过滤”.”和”/”,可以跨目录写入。所以不需要考虑路由问题。
POC:
1
2
3
4
5
from requests import post
postData = {
   'data' : '<?php phpinfo()?>'
}
新版修复:

首先给dr_safe_replace 参数增加了两个新的过滤条件 ” . “和 ” ‘ “,在原本漏洞出发点接收get值的时候用这个函数过滤。

猜你喜欢

转载自www.cnblogs.com/ichunqiujishu/p/10149439.html