Bill Gates 曾言:「All input is invalid.」這句話精準概括了 Web 安全的基石。無論是顯式參數 (Query String、表單欄位) 還是隱式輸入 (Cookie、HTTP Header、環境變數),皆為攻擊面。
# unsafe.cgi
$filepath = "/var/www/bbs/";
$filename = $query->param('page');
$filename = "$filepath/$filename";
open(FILE, $filename); # 直接使用用戶輸入
while (<FILE>) { print $_; }
close(FILE);
攻擊者請求 ?page=../../../../etc/passwd 即可讀取敏感檔案;若傳入 ?page=unsafe.cgi 甚至能獲取腳本原始碼。後續嘗試以 .html 後綴限制,仍可利用 NULL 字元 (%00) 繞過。
# 僅允許英數字、底線、連字號、點號
my $allowed = qr/^[\w\-\.]+$/;
my $page = $query->param('page') || 'index.html';
die "非法參數" unless $page =~ $allowed;
# 進一步檢查檔案是否存在於允許目錄
電子郵件驗證範例:
if ($email !~ /^[\w\.-]+\@[\w\.-]+$/) {
&error("郵件格式錯誤");
}
| 函數/字元 | 風險 | 對策 |
|---|---|---|
system(), exec() | 執行任意系統指令 | 避免使用;若必須用,嚴格白名單驗證所有參數 |
open() 搭配 >, | | 任意檔案寫入/指令執行 | 禁止用戶輸入控制檔名;使用三參數 open 模式 |
反引號 `cmd` | 同 system() | 同左 |
分號 ;, 管道 |, 重導向 > < | 指令注入、流程控制繞過 | 輸入白名單過濾,拒絕所有元字元 |
反斜線 \ 逃逸 | 繞過簡單過濾器 | 使用成熟的逃逸函數庫 (如 CGI.pm) |
尖括號 <> | 跨站腳本 (XSS) | 輸出時進行 HTML 實體編碼 |
-T),強制檢查外部數據流向。CGI 安全不在於語言選擇,而在於開發者是否建立「零信任」輸入處理習慣。白名單驗證、最小權限、輸出編碼、纵深防禦——四大支柱缺一不可。