在開始之前
最近在複習資訊安全的課程內容,原本以為自己不管在作業及作品實作上,都有考慮到資訊安全的眉角,而進行相關防範,但回頭去檢查時,還是有發現自己疏忽跟大意的地方。
回頭再去看 Huli 的自我檢討文章,發現更新很多我們常犯錯的地方,所以這次的複習,打算先把一些重要的提醒提點出來,然後再來進行後續的觀念整理。
- 不要相信任何來自 client 端的資料,保持懷疑精神。
- 預設程式碼已經被駭客看光而且被公開,前後台權限管理不能遺漏。
- 不要存有僥倖心態, escape、權限管理、prepare statement,做好做滿。
- 前端做資料檢查,是為了增進使用者體驗,後端做資料檢查才是真檢查。
明文密碼的風險
透過後端資料庫的設定,儲存會員的密碼資料。若是遇到駭客入侵,盜取資料之後,會員的密碼沒有經過加密處理,將會造成巨大的資安風險:
- 如果有駭客駭進了網站資料庫的主機,那所有使用者的帳號、密碼都赤裸裸地攤在駭客的眼前,每個人的帳戶、個人資料都無法倖免。
- 如果網站管理者居心不良、或是受到威脅、或是起來上廁所時忘了切換電腦畫面,使用者的帳號、密碼隨時都可能外洩。
為了防止資料庫外洩,不讓密碼輕易被盜取,造成使用者更多的傷害,公司的 IT 團隊會運用一些方式,將原本的密碼加以變化,而最常運用的方式有兩種:「雜湊」和「加密」。
大家是不是有過類似的經驗,我們在登入網站時,如果忘記密碼,按下「忘記密碼」的按鈕,都會請你重設密碼,而不是將原本的密碼透過電子郵件或簡訊回覆提供。真正的原因,就要來了解「雜湊」和「加密」背後的機制。
我們不一樣:雜湊與加密
兩者雖然都有相同的功能:幫使用者的密碼變成亂數排列,但他們根本的差別是:「加密可逆推回到原本的密碼,雜湊不能還原」。
雜湊(Hash):多對一關係,沒辦法從結果回推原本的密碼
- 如果使用者密碼輸入為「aaa」,透過雜湊的函式,輸出值為「5u8fed7」,我們無從得知雜湊內建函式的演算機制,所以也沒辦法知道「5u8fed7」雜湊之前的原本密碼是「aaa」。
- 有可能會發生「不同的密碼輸入」卻產生「相同的雜湊值」,若有這樣的狀況,稱為碰撞(collision)。不過,目前現存又知名的雜湊演算法,要發生碰撞的機率非常低。
- 常見的雜湊演算法:
- SHA-256
- MD5(已被證實不安全)
- SHA-1(已被證實不安全)
加密(Encrypt)
明文密碼經過加密後會產生密文與金鑰(Key),透過金鑰,可以逆推回去原本的明文密碼。
PHP 內建雜湊函式:password_hash
使用之前請注意:支援 PHP v5.5.0 以上版本
使用 PASSWORD_DEFAULT 演算法,注意資料庫預設儲存 255 個字元的空間
@handle_register.php:透過雜湊函式進行密碼加密
<?php
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
?>
驗證密碼:password_verify
@handle_login.php:判斷登入時,輸入密碼與雜湊之後的密碼是否相符
<?php
$result = $conn->query($sql);
if (!$result) {
die($conn->error);
}
if ($result->num_rows === 0) {
header("Location: login.php?errCode=2");
exit();
}
// 有查到使用者
$row = $result->fetch_assoc();
if (password_verify($password, $row['password'])) {
// 登入成功
$_SESSION['username'] = $username;
header("Location: index.php");
} else {
header("Location: login.php?errCode=2");
}
?>
雜湊加鹽
為了防堵駭客使用暴力破解法、並建立常用字串對照雜湊值的表單,來突破雜湊密碼防線,我們可以運用「加鹽」(salting)的方式,在密碼進行雜湊之前,先加入一段固定字串(所謂的加鹽),然後與使用者的密碼結合之後,再把加鹽過後的密碼,拿去進行雜湊,產生新的雜湊值之後,存入資料庫,藉以增加駭客破解密碼的難度。
參考資料:
[資訊安全] 密碼存明碼,怎麼不直接去裸奔算了?淺談 Hash , 用雜湊保護密碼
一次搞懂密碼學中的三兄弟 — Encode、Encrypt 跟 Hash
PHP 內建函式表