本文主要和大家探討一下`ThinkPHP`的安全注意事項,可以作為`ThinkPHP`建議的安全規范實踐。(如果有新的內容我也會及時補充)
>[danger]### 首先,沒有絕對的安全,只要你有足夠的安全意識才能盡可能的杜絕安全隱患。規范的使用框架,能讓你盡量避免一些看起來比較幼稚的安全問題。本文描述的安全注意事項主要是指生產環境下面的安全策略,本地開發的情況下有時候為了調試的需要安全并不是第一考慮。
ThinkPHP在考慮開發體驗的同時,仍然十分重視框架的底層安全,雖然屢有安全漏洞被播報,但官方都是第一時間進行修復處理,而且大部分漏洞只要開發者有一定的安全意識都是可以避免的,今年也和國內的幾個安全團隊建立了合作關系,有助于提前發現和及時修正框架可能被利用的漏洞或者隱患。
## 規范部署
這一點很多開發者不是特別重視,安全是一個整體性的問題,任何一個環節出問題,帶來的后果都是一樣的嚴重,部署的安全策略是一個基礎安全問題。
很多開發者往往不按照官方的部署規范進行部署,請務必把你的`WEB`根目錄指向`public`目錄而不是應用根目錄,并且不要隨意更改入口文件的位置。`public`目錄下面不要放除了入口文件和資源文件以外的其它應用文件。
## 關閉調試模式
在部署到生產環境的時候,確保你已經關閉了調試模式,可以通過修改環境變量的方式關閉調試模式。
```
APP_DEBUG=false
```
>[danger] 無論是本地開發還是生產環境部署,都不建議直接通過修改配置文件的方式開啟/關閉調試模式,而應該使用環境變量(本地開發可以通過定義`.env`文件)。
關閉調試模式后,系統的健康狀態和運行監控主要依靠日志或者你使用的監控服務。所以,要養成定時檢查日志和運行狀態的習慣。
## 請求變量過濾
永遠不要相信用戶的輸入,這是一句至理名言。盡可能的過濾請求變量能有效防范大部分的漏洞和隱患。
框架建議的獲取請求變量的方法是`Request`類的`param`方法(如非必要不要再使用`get`或者`post`方法獲取,更不要使用原生的`$_GET`/`$_POST`等方法獲取)。
```
public function index(Request $request)
{
$name = $request->param('name');
// 在這里可以根據你的業務需求進行更嚴謹的過濾
// 例如 $name = $request->param('name','','htmlentities,strtolower');
// 或者使用驗證器進行專門的驗證
}
```
對于有明確類型的請求變量,可以在使用`param`方法的時候使用**類型強制轉換**,例如:
```
public function index(Request $request)
{
// 強制轉換字符串數據
$name = $request->param('name/s');
// 強制轉換整型數據
$name = $request->param('id/d');
// 強制轉換浮點型數據
$name = $request->param('score/f');
}
```
或者直接使用方法參數獲取請求變量
```
public function index(string $name)
{
// 在這里可以根據你的業務需求進行更嚴謹的過濾
// 或者使用驗證器進行專門的驗證
}
```
>[info] 如果你需要對所有數據進行處理,可以設置全局的過濾方法。對不同的應用需求設置`default_filter`過濾規則(默認沒有任何過濾規則),常見的安全過濾函數包括`stripslashes`、`htmlentities`、`htmlspecialchars`和`strip_tags`等,請根據業務場景選擇最合適的過濾方法。
如果需要獲取多個數據,建議使用`only`方法指定需要獲取的變量名稱,避免有些不懷好意的數據提交導致權限問題。
```
public function index(Request $request)
{
// 指定表單數據名稱
$data = $request->only(['name','title']);
}
```
當你使用數據庫或者模型操作寫入數據的時候,也可以指定字段,避免非法和不希望的字段寫入數據庫。
```
// 模型
User::allowField(['name','title'])
->save($data);
// 數據庫
Db::name('user')
->field(['name','title'])
->insert($data);
```
模型還有一個[只讀字段](http://www.hmoore.net/manual/thinkphp5_1/354049)的功能能避免你的數據受到外部的修改。
## 上傳檢測
網站的上傳功能也是一個非常容易被攻擊的入口,所以對上傳功能的安全檢查是尤其必要的。
系統的`think\File`類提供了文件上傳的安全支持,包括對文件后綴、文件類型、文件大小以及上傳圖片文件的合法性檢查,確保你已經在上傳操作中啟用了這些合法性檢查,可以參考手冊的[上傳章節](http://www.hmoore.net/manual/thinkphp5_1/354121)。
## SQL注入
ThinkPHP的查詢統一使用了`PDO`的`prepare`預查詢和參數綁定機制,能有效的避免SQL注入的發生。但不代表絕對安全,如果你缺乏良好的代碼規范,仍然有可能被利用。
>[danger] 一個最簡單的原則就是不要讓用戶決定你的查詢條件(或者字段排序)和控制你的查詢數據。
對于一些字符串的查詢條件(包括原生查詢)或者特殊的查詢(包括`ORDER`部分),需要手動進行參數綁定。
```
// 錯誤的
Db::query("select * from think_user where id=$id AND status=$statis");
// 正確的
Db::query("select * from think_user where id=? AND status=?", [ $id, $status]);
// 正確的
Db::execute("update think_user set name=:name where status=:status", [
'name' => 'thinkphp',
'status' => 1
]);
```
對于使用了`whereExp`和`whereRaw`方式的查詢,你也需要使用參數綁定。
```
Db::name('user')
->whereRaw('id > ? AND status = ?',[10, 1])
->select();
```
## 使用驗證器
對于大量的表單需要驗證的情況,建議使用[驗證器](http://www.hmoore.net/manual/thinkphp5_1/354102)功能統一進行數據的合規驗證。驗證器的驗證操作應該在控制器或者路由階段使用`validate`方法進行處理,模型的數據驗證功能新版已經取消不再建議使用,模型和數據庫操作的時候應該傳入經過安全處理過的數據。
## XSS攻擊
跨站腳本攻擊(cross-site scripting,簡稱 `XSS`),XSS是一種在web應用中的計算機安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。
在渲染輸出的頁面中,要對一些數據進行安全處理,防止被惡意利用造成XSS攻擊,如果是5.1版本的話,所有的輸出都已經經過了`htmlentities` 轉義輸出,確保安全。如果是5.0版本的話,你可以自定義一個xss過濾函數,在模板文件中對一些關鍵內容變量進行函數處理。
## CSRF
CSRF 跨站請求偽造是 Web 應用中最常見的安全威脅之一,攻擊者偽造目標用戶的HTTP請求,然后此請求發送到有CSRF漏洞的網站,網站執行此請求后,引發跨站請求偽造攻擊。攻擊者利用隱蔽的HTTP連接,讓目標用戶在不注意的情況下單擊這個鏈接,由于是用戶自己點擊的,而他又是合法用戶擁有合法權限,所以目標用戶能夠在網站內執行特定的HTTP鏈接,從而達到攻擊者的目的。
開啟表單令牌驗證,盡量開啟強制路由并嚴格規范每個URL請求,定義單獨的MISS路由規則。
遵循請求類型的使用規范并做好權限驗證,刪除操作必須使用`DELETE`請求,數據更改操作必須使用` POST`、`PUT` 或者 `PATCH` 請求方法,`GET`請求不應該更改任何數據。
## 會話劫持
會話劫持是指攻擊者利用各種手段來獲取目標用戶的`session id`。一旦獲取到`session id`,那么攻擊者可以利用目標用戶的身份來登錄網站,獲取目標用戶的操作權限。
有效的防護策略包括:
在每次會話啟動的時候,調用`regenerate`方法。
```
Session::start();
Session::regenerate(true);
```
更改`session`配置參數,開啟安全選項:
```
'use_trans_sid' => 0,
'httponly' => true,
'secure' => true,
```
## 升級到安全版本
官方會對一些安全隱患和潛在漏洞進行修復,并且發布一個更為安全的版本。請確認你升級到更安全的版本,確保底層的安全和健壯性。
目前各個版本的建議版本如下:
大版本 | 安全建議版本
---|---
3.2| `3.2.4+`
5.0| `5.0.21+`
5.1|`5.1.25+`
關注官方的公眾號和[開發者周刊](http://www.hmoore.net/thinkphp/weekly/content),注意最新的安全更新。
## 業務邏輯安全
這個屬于應用層面的安全,很多漏洞源于某個業務邏輯自身的安全隱患,包括沒有做合理的數據驗證和權限檢查,尤其是涉及資金及財務層面的,一定要做更多的安全檢查,并且開啟事務。一個好的建議是更多的對應用進行分層設計,減少每層的復雜性,獨立的分層設計便于提高安全性。
## 服務器安全
最后一點是運維階段需要特別注意的,及時更新服務器的安全補丁,確保沒有可利用的公開系統漏洞,包括你的數據庫系統安(尤其是數據備份工作)。
## 附錄
附上一些有價值的WEB安全相關內容作為參考(陸續補充)
* [淺談PHP安全規范](http://www.freebuf.com/articles/web/184567.html)
* [前端安全系列(一):如何防止XSS攻擊?](https://my.oschina.net/meituantech/blog/2218539)
* [前端安全系列(二):如何防止CSRF攻擊?](https://my.oschina.net/meituantech/blog/2243958)
* [2018 PHP 應用程序安全設計指北](https://zhuanlan.zhihu.com/p/33163426)
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2