污染模式
Perl中的一些特性可以幫助你寫出安全的程序。當然這些手段無法取代細致的思考和規(guī)劃,但是能幫助你避免一些微妙的錯誤嫁蛇。
所謂污染模式就是對所有來自程序之外數(shù)據(jù)附加上一個元數(shù)據(jù)以便來跟蹤它們坎弯。從被污染的數(shù)據(jù)(臟數(shù)據(jù))中生成出來的數(shù)據(jù)也是被污染的。你可以在程序中使用被污染的數(shù)據(jù)桦锄,但是如果使用臟數(shù)據(jù)會影響程序之外的內(nèi)容(不安全的使用方式)扎附,Perl就會拋出致命異常。
使用污染模式
perldoc perlsec介紹了污染模式的具體細節(jié)结耀。
使用命令行參數(shù)-T就會啟動污染模式留夜。如果-T寫在#!行當中,就必須直接運行程序图甜,如果你忽略-T標志使用perl mytaintedappl.pl來啟動程序碍粥,Perl就會拋出異常并退出。
污染源
污染來自2個地方:文件輸入和程序環(huán)境黑毅。前者就是指你從文件讀到的或從網(wǎng)站嚼摩、網(wǎng)絡(luò)用戶那收集到的內(nèi)容。后者包括所有的命令行參數(shù)、環(huán)境變量和來自于系統(tǒng)調(diào)用的數(shù)據(jù)低斋,甚至從目錄句柄中讀取到的數(shù)據(jù)也是被污染的蜂厅。
核心模塊Scalar::Util中的函數(shù)tainted()用于測試是否被污染,如果參數(shù)是被污染的就返回真:
die 'Oh no! Tainted data!' if Scalar::Util::tainted( $suspicious_value );
從數(shù)據(jù)中解除污染
要凈化數(shù)據(jù)你就必須精確地提取數(shù)據(jù)中好的部分膊畴。比如如使用正則表達式來捕獲掘猿,捕獲到的數(shù)據(jù)就是干凈數(shù)據(jù)。例如唇跨,如用戶輸入中包含電話號碼稠通,你可以這樣解除污染:
die 'Number still tainted!' unless $number =~ /(\(/d{3}\) \d{3}-\d{4})/;
my $safe_number = $1;
匹配的模式越細致,你的程序就越安全买猖。相反的做法是拒絕指定的項目或忽略風險而運行改橘。當然你也可以捕獲整個值來解除污染,但是這樣就失去了使用污染模式的價值玉控。
從環(huán)境中解除污染
全局變量%ENV里面有程序所在系統(tǒng)的環(huán)境變量飞主。該變量是被污染的,原因是程序之外的力量可以操縱該值高诺。環(huán)境變量控制著Perl或shell如何定位文件和目錄碌识,這也是一個攻擊向量。一個安全敏感的程序應(yīng)該刪除%ENV中的一些鍵虱而,并且設(shè)置$ENV{PATH}到一個安全的路徑:
delete @ENV{ qw( IFS CDPATH ENV BASH_ENV ) };
$ENV{PATH} = '/path/to/app/binaries/';
如果$ENV{PATH}設(shè)置的不當就會收到報告其不安全的消息筏餐。如果環(huán)境變量包含了當前工作目錄,或者包含了相關(guān)目錄牡拇,或者指定的目錄是全局可寫的權(quán)限魁瞪,那么聰明的攻擊者就可以劫持系統(tǒng)調(diào)用來進行惡意攻擊。
出于類似的原因惠呼,@INC在污染模式下并不包含當前工作目錄导俘。Perl也會忽略PERL5LIB和PERLLIB環(huán)境變量。使用lib編譯指示或者使用-l標志來添加庫目錄到程序罢杉。
常見陷阱
污染模式只有打開和關(guān)閉2種狀態(tài)趟畏,也就是要么全有要么全無。有時候需要部分解除污染的時候滩租,就會有人過度放開(比如之前的全面捕獲),這時候污染模式就沒有起到應(yīng)有的作用利朵,所以要仔細審查污染解除的規(guī)則律想。
不幸的是,并不是所有模塊都會妥善處理被污染的數(shù)據(jù)绍弟,CPAN作者應(yīng)認真對待這個BUG技即。如果面對的是歷史遺留代碼,你可以考慮使用-t標志樟遣,這個標志會啟用污染模式但是會將違規(guī)的告警從異常降為警告(也就是不再退出)而叼,但這個并不是完整的污然模式身笤。(在不能使用完整污染模式下的一種折中方案)