PHP框架学习——thinkphp
字数 2924 2025-10-27 12:13:03
ThinkPHP 8.x 框架入门与代码审计教学文档
第一部分:ThinkPHP 基础与URL访问
ThinkPHP(简称TP)是一个免费开源的、快速、简单的面向对象的轻量级PHP开发框架。
1.1 环境与入口
- 入口文件:通常是项目根目录下的
public/index.php。所有对应用的请求都会经过这个入口文件。 - 基础URL格式:ThinkPHP遵循MVC(模型-视图-控制器)模式,其URL访问模式为:
http://服务器地址/入口文件/控制器/操作/参数名/参数值/...index.php:入口文件。index:模块(或应用)名,默认是index。Index:控制器名,对应 application/index/controller 目录下的Index.php文件。test:操作名,对应Index.php控制器类中的test()公共方法。
1.2 参数传递方式
文档中提到了三种常见的参数传递方式:
方式一:传统GET传参
- 代码示例:
public function test() { $name = $_GET['chuan']; // 直接使用超全局数组获取参数 return 'hello ' . $name; } - 访问URL:
http://127.0.0.1/xiaodi/public/index.php/index/index/test?chuan=111 - 特点:使用标准的
?参数名=值格式,与框架路由无关。
方式二:ThinkPHP Pathinfo传参(推荐)
- 代码示例:
public function test() { $name = input('n'); // 使用TP助手函数 input() 获取参数,更安全 return 'hello, ' . $name; } - 访问URL:
http://127.0.0.1/xiaodi/public/index.php/index/index/test/n/chuan - 特点:参数作为URL路径的一部分,更符合RESTful风格,是TP的默认推荐方式。
方式三:使用Request对象
- 代码示例:
public function test(Request $request) { // 依赖注入Request对象 $name = $request->param('n'); // 通过Request对象的param方法获取 return 'hello, ' . $name; } - 访问URL:与方式二相同。
- 特点:面向对象方式,功能更强大,可以更方便地获取各种请求数据。
1.3 跨控制器访问
-
同模块,不同控制器:
- 控制器文件:
application/index/controller/Test.php - 访问URL:
http://127.0.0.1/xiaodi/public/index.php/index/Test/xd(访问Test控制器下的xd操作)
- 控制器文件:
-
不同模块,不同控制器:
- 控制器文件:
application/test/controller/Xiaodi.php - 访问URL:
http://127.0.0.1/xiaodi/public/index.php/test/Xiaodi/xd(访问test模块下的Xiaodi控制器中的xd操作)
- 控制器文件:
第二部分:数据库操作与安全
数据库配置通常位于 config/database.php 文件中。
2.1 三种数据库查询方式
方式一:原生SQL查询(易产生SQL注入)
- 代码示例:
public function login_check(){ $id = $_GET['id']; // 直接获取用户输入,极度危险 $sql = "select * from cw_admin where id=$id"; // 直接拼接SQL语句 $data = mysqli_query($sql); // 执行查询 echo $data['pass']; } - 风险:直接将用户输入的
$id拼接到SQL语句中,攻击者可以构造恶意参数(如id=1 OR 1=1)进行SQL注入攻击,获取敏感数据。
方式二:ThinkPHP安全查询(使用预编译,推荐)
- 代码示例:
public function login_check1(Request $request){ $id = $request->param('i'); // Db::table 方式,where('字段名', '值') 会自动使用参数绑定 $data = Db::table('cw_admin')->where('id', $id)->find(); echo $data['pass']; } - 访问URL:
http://127.0.0.1/xiaodi/public/index.php/index/Login/login_check1/i/1 - 安全原理:TP框架底层会将这种写法转换为预编译SQL语句,将用户输入的数据当作纯数据处理,而不是可执行的SQL代码,从而有效防止SQL注入。
方式三:ThinkPHP不安全查询(字符串拼接,危险)
- 代码示例:
public function login_check2(Request $request){ $id = $request->param('i'); // where("条件字符串") 方式,如果字符串中包含变量拼接,同样存在注入风险 $data = Db::table('cw_admin')->where("id = $id")->find(); // 危险! echo $data['pass']; } - 风险:虽然使用了TP的数据库类,但由于采用了字符串内直接拼接变量
$id的方式,其安全风险与原生SQL查询相同。这是TP代码审计中需要重点关注的危险写法。
第三部分:ThinkPHP框架代码审计要点
根据原文内容,可以总结出以下审计关键点:
3.1 SQL注入漏洞审计
- 高危模式:在模型或Db类操作中,
where()方法内使用字符串直接拼接用户输入。->where("id = $id")->where("name LIKE '%".$name."%'")
- 安全模式:使用参数绑定的方式。
->where('id', $id)->where('name', 'like', "%$name%")(注意:Like查询需确保变量被正确转义或绑定,高版本TP已做处理,但审计时仍需留意复杂情况)
3.2 其他常见漏洞审计方向
虽然原文未深入提及,但在TP框架审计中还需关注:
- 输入验证与过滤:检查是否使用
input()函数的过滤功能(如input('param.name/s')强制转换为字符串)或Request对象的filter方法对用户输入进行过滤。 - 命令执行:查找
exec(),system(),shell_exec()等函数,其参数是否由用户可控。 - 文件操作:检查文件包含(
include,require)、文件上传、文件读取等操作,用户输入的参数是否被安全地过滤。 - 模板注入:如果项目使用了TP的模板引擎,检查是否允许用户控制模板内容。
第四部分:实战案例——CMS漏洞复现思路
原文提到“cms代码审计框架小迪漏洞复现”,这是一个典型的白盒审计流程:
- 环境搭建:下载目标CMS(如某个基于ThinkPHP开发的系统)并配置好本地测试环境。
- 功能点分析:浏览CMS的前后台功能,寻找与用户交互密切的点,如:登录、搜索、订单查询、文章展示等。
- 代码追踪:
- 以“搜索功能”为例,在前台搜索框输入关键词并抓包,找到对应的参数(如
keywords)。 - 根据URL路由规则(如
/index/search/index)找到对应的控制器文件(application/index/controller/Search.php)和操作方法(index())。 - 在方法中查看
keywords参数是如何被接收和使用的(是直接用$_GET还是input()?)。 - 追踪
keywords变量被传递到哪个数据库查询方法中,检查查询的写法是否安全(即第二部分中的方式二 vs 方式三)。
- 以“搜索功能”为例,在前台搜索框输入关键词并抓包,找到对应的参数(如
- 漏洞验证:如果发现不安全的写法,构造特殊的Payload(如搜索关键词
' AND (SELECT 1 FROM (SELECT SLEEP(5))a)--)进行延时注入测试,验证漏洞是否存在。 - 总结报告:记录漏洞位置、成因、利用方式及修复建议。
总结
本教学文档从ThinkPHP框架的基础URL访问和数据库操作讲起,重点剖析了安全与不安全的编码实践,并系统性地介绍了代码审计的核心要点。关键在于:
- 理解框架机制:掌握TP的MVC路由和参数获取方式。
- 树立安全意识:明确SQL注入等漏洞的产生根源在于“不可信的用户输入”与“代码/指令”的拼接。
- 掌握审计模式:在审计时,像侦探一样追踪用户输入的数据流,最终判断它是否被“安全地”使用。
希望这份详尽的文档能帮助您系统地学习ThinkPHP框架及其安全审计知识。