【42】WEB安全學習----PHP-ThinkPHP框架1
前言
前不久參加了一個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>