前言
前不久參加了一個CTF比賽,有一道題是PHP代碼審計,採用框架進行開發,因爲從沒有接觸過框架學習,故找到了漏洞代碼也不知道怎麼構造利用,悲慘之極,現在惡補下。
PHP框架
在PHP中,目前主流的框架有:
Zend Framework:重量級框架,由PHP官方出品,因爲功能較全面,導致啓動慢比較臃腫。
YII:重量級框架,由美國華人薛強開發
Symfony:重量級框架,一款國外框架。
Laravel:輕量級框架,一款國外框架。
Codelgniter:輕量級框架,簡稱CI框架,一款國外框架。
ThinkPHP:由國人開發,有中文官網和社區,在國內使用比較普遍。
MVC
說到框架,那麼不得不說MVC設計模式了,它是強制將用戶的輸入、邏輯、輸出相分離,將整個項目分爲三個部分:控制器、模型、視圖。
編程階段:
第一階段:混合編程-將PHP代碼和前端代碼寫在一個文件中。
第二階段:模板引擎-典型的如smarty。將後端代碼和前端代碼分離開。
第三階段:框架-將用戶的輸入、邏輯、輸出相分離,維護性提高很多。
ThinkPHP框架
目前最新的是V5版,但目前使用最多的是3.2.3版本。
軟件版本的修飾詞:
- Alpha版本:內測版本,內部測試
- Beta版本:公測版本,面向用戶,由用戶找BUG
- RC版本:候選版本,軟件在這個階段就已經不會有太多的功能性調整,主要是排錯。
- R版本:release版本,發行版本,穩定的版本
目錄解釋
- Application:應用目錄
- Public:資源文件,存放圖片、CSS、JS等靜態文件
- ThinkPHP:框架核心目錄
- .htaccess:分佈式配置文件
- composer.json:給composer管理軟件使用的說明文
- index.php:項目的入口文件
- README.md:說明文件
核心框架目錄:
- Common:系統函數庫目錄,存放了functions.php
- Conf:系統配置文件目錄
- Lang:語言包目錄
- Library:thinkphp核心目錄
- Mode:模式,一般用不着
- Tpl:系統模板目錄,裏面包含了系統所用的模板
- ThinkPHP.php:項目接口文件,在後期開發的時候被項目入口文件所引入
自動生成
在首次運行index.php入口文件時會自動生成相應的目錄結構:
開始只需要這兩個文件即可:
訪問入口文件會自動生成Application目錄
應用目錄名字取決於在index.php中定義的常量APP_PATH:
目錄安全文件:
在自動生成的目錄中都有一個空白的html文件,這是爲了防止開發者忘記在Apache配置文件中配置了options+indexes,防止目錄遍歷攻擊。防止列出站點文件結構。
默認訪問:
默認訪問可看到一個笑臉,這是爲啥呢?
默認配置在系統配置convention.php文件中:
默認分組/平臺:Home
默認控制器:Index
默認方法:index
ThinkPHP中控制器
命名規範:控制名(英文首字母大寫)+Controller關鍵詞+.class.php
如:GoodController.class.php
控制器代碼結構:
1、聲明當前控制器(類)的命名空間:namespace Home\Controller
2、引入父類控制器:Think\Controller
3、聲明控制器(類)並且繼承父類:class IndexController extends Controller
自己寫一個控制器:
#自己建立一個控制器:UserController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class UserController extends Controller{
public function test(){
echo "hello world";
}
}
那麼怎麼構造訪問呢?http://127.0.0.1/thinkphp/index.php?m=Home&c=User&a=test
m爲平臺/分組,默認爲Home,C爲控制器,a爲方法
路由形式
路由:是指訪問項目具體某個方法的URL地址,在ThinkPHP中系統提供了4種路由形式:
- 普通形式路由(GET形式路由)
- Pathinfo形式路由
- Rewrite形式路由
- 兼容形式路由
普通形式路由:
路由形式:http://網址/入庫文件?m=分組名&c=控制器名&a=方法名&參數名=參數值
例如:訪問Home分組下的User控制器中的test方法,並且傳遞一個參數,id=1
http://127.0.0.1/index.php?m=Home&c=User&a=test&id=1
問題:既不安全也不好看
Pathinfo形式路由:thinkphp默認路由
路由形式:http://網址/入口文件/分組名/控制器/方法/參數名1/參數值1/參數名/2參數值2
例如:訪問Home分組下的User控制器中的test方法,並且傳遞一個參數,id=1
http://127.0.0.1/thinkphp/index.php/Home/User/test/id/1
Rewrite形式路由:
路由形式:http://網址/分組名/控制器/方法/參數名1/參數值1/參數名/2參數值2
http://127.0.0.1/thinkphp/Home/User/test/id/1
注意:該路由需要配置才能使用。此路由形式很少使用。
兼容形式路由:
路由形式:http://網址/入口文件?s=/分組名/控制器/方法/參數名1/參數值1/參數名/2參數值2
http://127.0.0.1/thinkphp/index.php?s=/Home/User/test/id/1
thinkphp路由的配置:在thinkphp系統配置文件convention.php中,默認爲Pathinfo形式路由,這裏配置不影響我們在地址欄輸入的形式,而是影響的是thinkphp系統封裝的URL組裝函數。
分組
一般的項目都會根據某個功能來區分代碼,這時候放到一起就形成了分組文件夾,分組就是指的是平臺(前臺、後臺)。
默認thinkphp創建了一個Home分組,後期需要更多的分組,需要自己創建。
如何創建分組:參考Home分組的文件結構
自己創建一個分組:
在Home分組同級目錄中創建一個Admin分組,裏面的結構參考Home分組結構
在Admin分組中創建一個控制器:TestController.class.php,並創建一個測試方法Test
<?php
namespace Admin\Controller;
use Think\Controller;
class TestController extends Controller {
public function test(){
phpinfo();
}
}
訪問創建的分組:http://127.0.0.1/thinkphp/index.php/Admin/test/Test
控制器中的跳轉
URL組裝:
URL組裝就是根據某個規則,來組成一個URL地址,這個功能就叫做url組裝。
在Thinkphp中,系統提供了一個封裝函數來處理URL的組裝,這個方法叫做U方法。
U方法是系統提供的快速方法,除了U方法還有其它的快速方法:A、B、C等這些方法都定義在系統函數庫中functions.php。
測試U方法組裝:
<?php
namespace Admin\Controller;
use Think\Controller;
class TestController extends Controller {
public function test(){
echo U('admin');
}
}
這裏admin後面是.html,這是僞靜態,爲了優化。
用法:U('[分組名/控制器名]方法名',array('參數名1'=>參數值1,'參數名2'=>參數值2))
示例:echo U('Admin/Test/Test',array('id'=>1));
系統跳轉方法:
在Thinkphp中系統有2個跳轉方法:成功跳轉和失敗跳轉。
成功:
$this->success(跳轉提示,跳轉地址,等待時間);
失敗:
$this->error(跳轉提示,跳轉地址,等待時間);
跳轉參數必須要有,後面的地址和時間可以沒有,若沒有地址則跳轉到上一頁。
測試跳轉:
<?php
namespace Admin\Controller;
use Think\Controller;
class TestController extends Controller {
public function test(){
echo "hello world";
}
public function test1(){
echo "good id";
}
public function jmp1(){
$this->success("跳轉成功",U("test"),10);
}
public function jmp2(){
$this->error("跳轉失敗",U("test1"),10);
}
}
視圖
什麼是視圖:是MVC三大組成部分之一,主要負責信息的輸出和展示。
視圖的創建:
創建的位置需要在分組目錄下的View目錄中,一般來說,一個控制器對應着一個視圖目錄 (同名),控制器中的方法對應着視圖目錄裏的一個html文件。
示例:Test控制器中的login方法,需要有一個模板,則該模板文件login.html需要放在View/Test/login.html。
視圖的展示:
在Thinkphp中展示視圖是通過:$this->display();展示當前控制器下與當前請求方法名稱一致的模板文件。
測試模板:
Test控制下有一個test1方法:
public function test1(){
$this->display();
}
在View\Test\創建一個test1.html模板文件,訪問即可展示test1.html。
變量的分配:
在Thinkphp中系統已封裝好了一個變量的分配方法:$this->assign('模板中變量名','php中變量名');
而在模板中通過{$模板變量名}來展示變量數據。
測試:
public function test1(){
$date=date('Y-m-d H:i:s',time());
$this->assign('date',$date);
$this->display();
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
現在時間是:{$date}
</body>
</html>