在昨天有提到「功能寫對」不等於「系統安全」,「服務有運作」不等於「沒有被入侵」。
在了解所有的資安漏洞和風險之前一定要先認識「CIA」這個資安的3個黃金準則,它們分別代表
C : 機密性 (Confidentiality)、I : 完整性 (Integrity)、A :可用性 (Availability)
今天的重點就是機密性( C )和完整性( I )
許多團隊在開發和維運時,為了方便管理,經常把把顧客的信用卡號、身份證字號與公開的商品目錄放在同一個資料庫、設相同權限,,沒有將資產適當地分類會造成機密性與完整性危機
機密性危機 (Confidentiality Breach):
因為沒有「極機密(Confidential)」的定義,開發人員可能將包含用戶個資的資料庫 Log 寫進日誌檔,沒有過濾就直接上傳到雲端,導致敏感資訊公開曝露。
完整性危機 (Integrity Violation):
因為沒有定義敏感資料(如交易金額、帳戶餘額)的存取邊界,導致前端傳入任何的參數都能直接更新資料庫欄位,造成資料遭到篡改。
import logging
def get_user_profile(user_id):
# 1. 忽略機密性:查詢結果包含密碼 Hash、身份證號與信用卡號
user_data = db.query(f"SELECT * FROM users WHERE id = {user_id}")
# 2. 忽略機密性:直接將完整的敏感個資寫入公開的系統 Log 中
logging.info(f"User profile retrieved: {user_data}")
# 3. 忽略機密性:API 未做欄位過濾,全數回傳給前端
return user_data
def update_user_balance(user_id, amount):
# 4. 忽略完整性:未檢驗呼叫來源權限與金額合法性,直接允許修改金流資產
db.execute(f"UPDATE users SET balance = {amount} WHERE id = {user_id}")
def get_user_profile_safe(current_user, target_user_id):
# 驗證存取權限(保護 C)
if current_user.id != target_user_id and not current_user.is_admin:
raise PermissionError("無權存取該資產")
user = db.query_one("SELECT id, name, email FROM users WHERE id = %s", (target_user_id,))
# 日誌去識別化/去敏處理(保護 C)
logging.info(f"User profile accessed for user_id: {target_user_id}")
return user # 僅回傳非敏感資訊
def update_user_balance_safe(current_user, amount):
# 嚴格校驗與事務鎖定(保護 I)
if not current_user.is_system_admin:
raise PermissionError("權限不足")
if amount < 0:
raise ValueError("無效的金額參數")
db.execute("UPDATE users SET balance = balance + %s WHERE id = %s", (amount, current_user.id))
可以看到在錯誤示範裡
在正確示範裡
所有人都不想自己的個資能被別人輕鬆取得,因此才需要針對資料去做許多處理,為了確保資料能被合理的存取,開發者在開發時就應該考慮將資料增設權限,加以驗證、處理,不要等到資安事件發生後才去亡羊補牢,省去後續補救的時間與資源