3

fastadmin前台漏洞复现

 2 years ago
source link: https://h3art3ars.github.io/2020/09/23/fastadmin%E5%89%8D%E5%8F%B0%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

FastAdmin前台漏洞getshell分析

V1.0.0.20200506_beta

根据官网的修复方法

image-20200921165512720

可以看到产生漏洞的位置 application/index/controller/User.php 看一下 _empty() 方法,将传入的 $name参数未经过滤,直接传输到 fetch方法中。

先调用了 view文件内的 fetch 方法

public function fetch($template = '', $vars = [], $replace = [], $config = [], $renderContent = false)
2
   {
3
       // 模板变量
4
       $vars = array_merge(self::$var, $this->data, $vars);
5
6
       // 页面缓存
7
       ob_start();
8
       ob_implicit_flush(0);
9
       // 渲染输出
       try {
           $method = $renderContent ? 'display' : 'fetch';
           // 允许用户自定义模板的字符串替换
           $replace = array_merge($this->replace, $replace, (array) $this->engine->config('tpl_replace_string'));
           $this->engine->config('tpl_replace_string', $replace);
           $this->engine->$method($template, $vars, $config); //$template为传入参数
       } catch (\Exception $e) {
           ob_end_clean();
           throw $e;
20
       }
21
      ...

之后调用了 think文件内的 fetch方法

public function fetch($template, $data = [], $config = [])
2
    {
3
        if ('' == pathinfo($template, PATHINFO_EXTENSION)) {
4
            // 获取模板文件名
5
            $template = $this->parseTemplate($template);
6
        }
7
        // 模板不存在 抛出异常
8
        if (!is_file($template)) {
9
            throw new TemplateNotFoundException('template not exists:' . $template, $template);
        }
        // 记录视图信息
        App::$debug && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]', 'info');
        $this->template->fetch($template, $data, $config);

在此处经过 is_file 函数判断 ,再次调用template文件内的 fetch方法

public function fetch($template, $vars = [], $config = [])
2
{
3
    if ($vars) {
4
        $this->data = $vars;
5
    }
6
    if ($config) {
7
        $this->config($config);
8
    }
9
    if (!empty($this->config['cache_id']) && $this->config['display_cache']) {
        // 读取渲染缓存
        $cacheContent = Cache::get($this->config['cache_id']);
        if (false !== $cacheContent) {
            echo $cacheContent;
            return;
        }
    }
    $template = $this->parseTemplateFile($template);
    if ($template) {
        $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($this->config['layout_name'] . $template) . '.' . ltrim($this->config['cache_suffix'], '.');
20
        if (!$this->checkCache($cacheFile)) {
21
            // 缓存无效 重新模板编译
22
            $content = file_get_contents($template);
23
            $this->compiler($content, $cacheFile);
24
        }
25
        // 页面缓存
26
        ob_start();
27
        ob_implicit_flush(0);
28
        // 读取编译存储
29
        $this->storage->read($cacheFile, $this->data); //此处为thinkphp<5.0.18 文件包含漏洞发生处
30
        $content = ob_get_clean();
31
        ......

主要意思就是将传入的未经过滤$template文件,经过 $this->storage->read包含执行,最终造成文件包含漏洞。

要访问漏洞的方法,必须是配置文件为:

//是否开启前台会员中心
2
'usercenter'            => true,

[90sec][https://forum.90sec.com/t/topic/1294] 上有人发出windows上面的利用方式。

先注册用户,之后上传带有php代码的头像,查看头像位置,最后访问

http://x.x.x.x/index.php/index/user/_empty?name=../uploads/xxxxxx.jpg

即可包含文件

如果含有其他的文件可控点,也是可以包含的,比如仍然使用低版本thinkphp的fastadmin的日志。包含的文件必须有后缀名,否则默认为 .html

V1.0.0.20200920_beta已修复,官方删除了 application/index/User.php 内的 _empty() 方法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK