Back-End
php
資訊安全
本篇為 [BE101] 用 PHP 與 MySQL 學習後端基礎 這門課程的學習筆記。如有錯誤歡迎指正。
相關筆記:
我們先前利用 PHP 實作的初階留言板,其實暗藏許多安全性漏洞,接下來的重點,就是說明這些漏洞如何產生,以及該如何解決這些問題。
當我們以「明文」方式將密碼存在資料庫時,可能面臨下列資安風險:
因此我們需要透過「雜湊」來保護密碼。這也是為什麼,當我們忘記密碼時,網站會要我們重設密碼,而不是得到原先的密碼,因為雜湊不可逆,無法回推得到原碼。
兩者最大差別在於:「加密可逆,雜湊不可逆」。
不定長度、無窮可能
的輸入,透過雜湊演算法,轉換成固定長度
的雜湊值password_hash()
PHP 提供內建函式 password_hash()
能夠實現加密, 指令如下:
驗證指令:password_verify("要驗證的字串", "加密過的字串")
,會回傳一個 boolean
參考資料:
以下介紹幾種常見的資安攻擊,其原理與防範方法。
是一種注入式攻擊。發生於應用程式與資料庫層的安全漏洞。
在輸入資料時,夾帶不正當的 SQL 指令,若網頁忽略字元檢查,資料庫將會視為正常的 SQL 指令並執行惡意程式碼,進而破壞或入侵。
' or 1=1#
'
:將 username 的 input 關閉or
:條件式的「或是」#
:代表註解,後面的條件均會被忽略WHERE
條件式中的 1=1
恆正,如此即可略過權限檢查,沒有密碼也能成功登入帳號'), ('admin', 'Hacking!')#
透過 Prepare Statement 進行跳脫,以防止 SQL 注入。
步驟如下:
$sql
prepare()
預處理 $sql
:此時只傳送佔位符號 ?
,可避免利用拼接 SQL 字串語句的攻擊bind_param()
帶入參數。常用參數類型:
s
:string(字串)i
:integer(整數)execute()
執行 SQL 語法:此時才會將參數傳送給資料庫get_result()
取出執行結果程式碼範例:
參考資料:
全名是 Cross Site Scripting(跨網站指令碼攻擊),為了不與 CSS 混淆,故簡稱 XSS。
是一種注入式攻擊。通常是透過 JavaScript 或 HTML,因此又被稱作 JavaScript Injection 攻擊。
攻擊者利用網頁開發時留下的安全漏洞,在網頁插入惡意程式碼,讓使用者載入並執行惡意程式,攻擊者可藉此取得更高的權限,或是竊取使用者的 Cookie 等資料。
XSS 常見的攻擊種類大致上可分為兩種:
以網頁輸入欄位為例。若在輸入欄位內刻意植入 Javascript 語法,例如下列程式碼,即可竊取使用者的 cookie 資料:
以留言板為例。攻擊者將惡意程式碼透過「新增留言」寫入資料庫,當使用者瀏覽到該頁面時,就會觸發程式碼,達到攻擊目的。
責任主要還是歸咎於網頁開發時留下的安全漏洞,但 Server 端與 Client 端可以藉由下列方法,來避免遭受攻擊:
htmlentities()
或 htmlspecialchars()
參考資料:
全名是 Cross Site Request Forgery(跨站請求偽造)。也被稱為 one-click attack 或 session riding。
和 XSS 同樣是跨站式的請求攻擊,兩者卻有明顯區別,不同之處在於:
要完成一個 CRSF 攻擊,必須條件是「使用者仍保持登入狀態」。
假設 A 為目標網站,B 為惡意網站,步驟大致如下:
簡言之,CSRF 就是「在不同 domain 下,偽造使用者本人發出的 request」。
由於 CSRF 攻擊的必要條件,是使用者在被攻擊的網頁處於「已登入狀態」。使用者在每次使用完網站就登出,即可避免 CSRF 攻擊。
在網站加上驗證碼,可多一道檢查程序,常用於金流相關操作。
在 form
裡面加上一個 hidden
的欄位,叫做 csrftoken
,填入的值為 Server 隨機產生的亂碼,並且存在 Server 的 session 中。
按下 submit 後,Server 會比對表單中的 csrftoken 與存在 Server 端的是否相同。
與前一種解法相似,好處是不需要存任何東西在 Server 端。
而是在 cookie 與 form 設置相同的 csrftoken,利用「cookie 只會從相同 domain 帶上來」機制,使攻擊者無法從不同 domain 戴上此 cookie。
和前面提的 Double Submit Cookie 核心概念相同。不同之處在於「改由 Client 端」生成 csrf token。
生成之後放到 form 裡面以及寫到 cookie,其他流程就和之前相同。 此 cookie 只是確保攻擊者無法取得,不含任何資訊,因此由 Client 或 Server 生成都是一樣的。
CSRF 之所以能夠成立,是瀏覽器的機制所導致,但我們也能從瀏覽器著手進行防禦,也就是透過 SameSite cookie。其原理是「幫 Cookie 再加上一層驗證」,防止來自不同 domain 的請求。
做法是在 Set-cookie 的 session_id 後加上 SameSite 即可啟用此功能。由於這是較新的功能,目前瀏覽器中只有 Chrome 支援,使用前須注意。
使用範例如下:
SameSite 有分 Strict(預設)與 Lax 兩種模式:
<a href="">
, <form>
, new XMLHttpRequest
等標籤參考資料: