談談 Web 安全

攻擊者無時無刻不在準備對你的 Web 應用程序進行攻擊,因此提高你的 Web 應用程序的安全性是非常有必要的晦攒。幸運的是,來自開放式 Web 應用程序安全項目 (OWASP) 的有心人已經整理了一份包含了已知安全問題和防御方式的全面的清單哟旗。這份清單對于具有安全意識的開發(fā)者來說是必讀的闸餐。由 Padraic Brady 著作的 生存手冊:PHP 安全 也是一份很不錯的 PHP 安全閱讀資料矾芙。

密碼哈希

每個人在建構 PHP 應用時終究都會加入用戶登錄的模塊。用戶的帳號及密碼會被儲存在數據庫中拂铡,在登錄時用來驗證用戶感帅。

在存儲密碼前正確的 哈希密碼 是非常重要的地淀。哈希密碼是單向不可逆的,該哈希值是一段固定長度的字符串且無法逆向推算出原始密碼实苞。這就代表你可以哈希另一串密碼烈疚,來比較兩者是否是同一個密碼,但又無需知道原始的密碼胞得。如果你不將密碼哈希,那么當未授權的第三者進入你的數據庫時跃巡,所有用戶的帳號資料將會一覽無遺牧愁。有些用戶可能(很不幸的)在別的網站也使用相同的密碼猪半。所以務必要重視數據安全的問題偷线。

密碼應該單獨被 加鹽處理 声邦,加鹽值指的是在哈希之前先加入隨機子串摆舟。以此來防范「字典破解」或者「彩虹碰撞」(一個可以保存了通用哈希后的密碼數據庫,可用來逆向推出密碼)媳瞪。

哈希和加鹽非常重要蛇受,因為很多情況下厕鹃,用戶會在不同的服務中選擇使用同一個密碼,密碼的安全性很低。

值得慶幸的是诗赌,在 PHP 中這些很容易做到铭若。

使用 password_hash 來哈希密碼

password_hash 函數在 PHP 5.5 時被引入。 此函數現在使用的是目前 PHP 所支持的最強大的加密算法 BCrypt 瞳腌。 當然镜雨,此函數未來會支持更多的加密算法荚坞。 password_compat 庫的出現是為了提供對 PHP >= 5.3.7 版本的支持。

在下面例子中各淀,我們哈希一個字符串诡挂,然后和新的哈希值對比临谱。因為我們使用的兩個字符串是不同的(’secret-password’ 與 ‘bad-password’)悉默,所以登錄失敗麦牺。

<figure class="highlight" style="box-sizing: border-box; background: rgb(255, 255, 255); margin: 0px 4px; font-size: 0.8em;">

<?php
require 'password.php';

$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);

if (password_verify('bad-password', $passwordHash)) {
    // Correct Password
} else {
    // Wrong password
}

</figure>

password_hash() 已經幫你處理好了加鹽鞭缭。加進去的隨機子串通過加密算法自動保存著岭辣,成為哈希的一部分。password_verify() 會把隨機子串從中提取仑濒,所以你不必使用另一個數據庫來記錄這些隨機子串偷遗。

數據過濾

永遠不要信任外部輸入氏豌。請在使用外部輸入前進行過濾和驗證。filter_var()filter_input() 函數可以過濾文本并對格式進行校驗(例如 email 地址)泪电。

外部輸入可以是任何東西:$_GET$_POST 等表單輸入數據纪铺,$_SERVER 超全局變量中的某些值,還有通過 fopen('php://input', 'r') 得到的 HTTP 請求體突诬。記住攒霹,外部輸入的定義并不局限于用戶通過表單提交的數據浆洗。上傳和下載的文檔,session 值抠刺,cookie 數據,還有來自第三方 web 服務的數據速妖,這些都是外部輸入罕容。

雖然外部輸入可以被存儲、組合并在以后繼續(xù)使用露泊,但它依舊是外部輸入旅择。每次你處理、輸出沉噩、連結或在代碼中包含時川蒙,請?zhí)嵝炎约簷z查數據是否已經安全地完成了過濾长已。

數據可以根據不同的目的進行不同的 過濾 。比如胶果,當原始的外部輸入被傳入到了 HTML 頁面的輸出當中斤斧,它可以在你的站點上執(zhí)行 HTML 和 JavaScript 腳本霎烙!這屬于跨站腳本攻擊(XSS)悬垃,是一種很有殺傷力的攻擊方式。一種避免 XSS 攻擊的方法是在輸出到頁面前對所有用戶生成的數據進行清理烘豌,使用 strip_tags() 函數來去除 HTML 標簽或者使用 htmlentities() 或是 htmlspecialchars() 函數來對特殊字符分別進行轉義從而得到各自的 HTML 實體看彼。

另一個例子是傳入能夠在命令行中執(zhí)行的選項囚聚。這是非常危險的(同時也是一個不好的做法)顽铸,但是你可以使用自帶的 escapeshellarg() 函數來過濾執(zhí)行命令的參數谓松。

最后的一個例子是接受外部輸入來從文件系統(tǒng)中加載文件践剂。這可以通過將文件名修改為文件路徑來進行利用。你需要過濾掉"/", "../", null 字符或者其他文件路徑的字符來確保不會去加載隱藏拧簸、私有或者敏感的文件男窟。

數據清理

數據清理是指刪除(或轉義)外部輸入中的非法和不安全的字符歉眷。

例如,你需要在將外部輸入包含在 HTML 中或者插入到原始的 SQL 請求之前對它進行過濾淑际。當你使用 PDO 中的限制參數功能時春缕,它會自動為你完成過濾的工作艘蹋。

有些時候你可能需要允許一些安全的 HTML 標簽輸入進來并被包含在輸出的 HTML 頁面中,但這實現起來并不容易宅荤。盡管有一些像 HTML Purifier 的白名單類庫為了這個原因而出現浸策,實際上更多的人通過使用其他更加嚴格的格式限制方式例如使用 Markdown 或 BBCode 來避免出現問題。

查看 Sanitization Filters

反序列化 Unserialization

使用 unserialize() 從用戶或者其他不可信的渠道中提取數據是非常危險的事情惫确。這樣做會觸發(fā)惡意實例化對象(包含用戶定義的屬性)改化,即使對象沒用被使用,也會觸發(fā)運行對象的析構函數盏档。所以你應該避免從不可信渠道反序列化數據燥爷。

如果你必須這樣做,請你使用 PHP 7 的 allowed_classes 選項來限制反序列化的對象類型稚配。

有效性驗證

驗證是來確保外部輸入的是你所想要的內容道川。比如立宜,你也許需要在處理注冊申請時驗證 email 地址、手機號碼或者年齡等信息的有效性尊流。

查看 Validation Filters

配置文件

當你在為你的應用程序創(chuàng)建配置文件時灯帮,最好的選擇時參照以下的做法:

  • 推薦你將你的配置信息存儲在無法被直接讀取和上傳的位置上钟哥。
  • 如果你一定要存儲配置文件在根目錄下,那么請使用 .php 的擴展名來進行命名吁恍。這將可以確保即使腳本被直接訪問到银受,它也不會被以明文的形式輸出出來鸦采。
  • 配置文件中的信息需要被針對性的保護起來,對其進行加密或者設置訪問權限顶霞。
  • 建議不要把敏感信息如密碼或者 API 令牌放到版本控制器中选浑。

注冊全局變量

注意: 自 PHP 5.4.0 開始,register_globals 選項已經被移除并不再使用拓提。這是在提醒你如果你正在升級舊的應用程序的話隧膘,你需要注意這一點。

register_globals 選項被開啟時蹦疑,它會使許多類型的變量(包括 $_POST, $_GET$_REQUEST)被注冊為全局變量歉摧。這將很容易使你的程序無法有效地判斷數據的來源并導致安全問題腔呜。

例如:$_GET['foo'] 可以通過 $foo 被訪問到,也就是可以對未聲明的變量進行覆蓋券盅。如果你使用低于 5.4.0 版本的 PHP 的話膛檀,請 確保 register_globals 是被設為 off 的。

錯誤報告

錯誤日志對于發(fā)現程序中的錯誤是非常有幫助的泳炉,但是有些時候它也會將應用程序的結構暴露給外部花鹅。為了有效的保護你的應用程序不受到由此而引發(fā)的問題枫浙。你需要將在你的服務器上使用開發(fā)和生產(線上)兩套不同的配置。

開發(fā)環(huán)境

為了在 開發(fā) 環(huán)境中顯示所有可能的錯誤真友,將你的 php.ini 進行如下配置:

<figure class="highlight" style="box-sizing: border-box; background: rgb(255, 255, 255); margin: 0px 4px; font-size: 0.8em;">

display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On

</figure>

將值設為 -1 將會顯示出所有的錯誤盔然,甚至包括在未來的 PHP 版本中新增加的類型和參數。 和 PHP 5.4 起開始使用的 E_ALL 是相同的愈案。- php.net

E_STRICT 類型的錯誤是在 5.3.0 中被引入的,并沒有被包含在 E_ALL 中遭铺。然而從 5.4.0 開始恢准,它被包含在了 E_ALL中。這意味著什么锰蓬?這表示如果你想要在 5.3 中顯示所有的錯誤信息芹扭,你需要使用 -1 或者 E_ALL | E_STRICT赦抖。

不同 PHP 版本下開啟全部錯誤顯示

  • < 5.3 -1E_ALL
  • 5.3 -1E_ALL | E_STRICT
  • 5.3 -1E_ALL

生產環(huán)境

為了在 生產 環(huán)境中隱藏錯誤顯示,將你的 php.ini 進行如下配置:

<figure class="highlight" style="box-sizing: border-box; background: rgb(255, 255, 255); margin: 0px 4px; font-size: 0.8em;">

display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On

</figure>

當在生產環(huán)境中使用這個配置時轮锥,錯誤信息依舊會被照常存儲在 web 服務器的錯誤日志中舍杜,唯一不同的是將不再顯示給用戶赵辕。更多關于設置的信息,請參考 PHP 手冊:

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末饲握,一起剝皮案震驚了整個濱河市救欧,隨后出現的幾起案子锣光,更是在濱河造成了極大的恐慌,老刑警劉巖骑疆,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件替废,死亡現場離奇詭異,居然都是意外死亡诈火,警方通過查閱死者的電腦和手機状答,發(fā)現死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門惊科,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人充活,你說我怎么就攤上這事』炻眩” “怎么了窖张?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵宿接,是天一觀的道長。 經常有香客問我睦霎,道長,這世上最難降的妖魔是什么低剔? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任襟齿,我火速辦了婚禮枕赵,結果婚禮上,老公的妹妹穿的比我還像新娘拷窜。我一直安慰自己涧黄,他們只是感情好笋妥,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布春宣。 她就那樣靜靜地躺著嫉你,像睡著了一般蜻直。 火紅的嫁衣襯著肌膚如雪何之。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天距误,我揣著相機與錄音深寥,去河邊找鬼。 笑死惋鹅,一個胖子當著我的面吹牛,可吹牛的內容都是我干的沽讹。 我是一名探鬼主播武鲁,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼挚瘟!你這毒婦竟也來了饲梭?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤订框,失蹤者是張志新(化名)和其女友劉穎穿扳,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體矛物,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡泽谨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年吧雹,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雄卷。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡丁鹉,死狀恐怖悴能,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情漠酿,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布宇姚,位于F島的核電站夫凸,受9級特大地震影響,放射性物質發(fā)生泄漏夭拌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一道逗、第九天 我趴在偏房一處隱蔽的房頂上張望滓窍。 院中可真熱鬧巩那,春花似錦此蜈、人聲如沸裆赵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽植兰。三九已至璃吧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筒繁,已是汗流浹背巴元。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呕缭,地道東北人臊旭。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓离熏,卻偏偏與公主長得像戴涝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子奸鸯,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容

  • 關于Mongodb的全面總結 MongoDB的內部構造《MongoDB The Definitive Guide》...
    中v中閱讀 31,898評論 2 89
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理娄涩,服務發(fā)現蓄拣,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • Welcome 目前網絡上充斥著大量的陳舊信息辜昵,讓PHP新手誤入歧途咽斧,傳播著錯誤的實踐和糟糕的代碼,這必須得到糾正...
    layjoy閱讀 21,657評論 7 118
  • 圖片 1 錢是男人的膽 男人在社會上立足需要錢,沒有錢番挺,在家 人面前就沒有價值玄柏,在社會上就沒有地位,也很難得到認可...
    鋒芒所指閱讀 270評論 0 0
  • 時間:2008年12月28日 目的地:杭州 窗外一片漆黑粪摘,只有街燈在無力地低吟徘意⌒郑“天空是綿綿的糖,就算塌下來又怎樣...
    星之碎片03閱讀 230評論 0 0