在日常的開發中,安全性一直是我們要研究的重點內容之一。而在安全性中,最主要的一點就是我們的輸入資料。所有的攻擊和越權,都是從一個不經意間遺留的請求漏洞發生的。當然,現在很多框架已經為我們解決了大部分的安全性問題,但百密一疏,總會有意想不到的地方忘了加過濾或者遺漏了某些驗證。今天我們要學習的這個擴充套件就是為我們解決這種問題而誕生的。
什麼是 Taint
上篇文章中就得到過,我們還要介紹一個鳥哥的擴充套件工具,Taint 這個擴充套件就是鳥哥大神的作品之一。不過這個擴充套件是不推薦安裝在生產環境的,它主要的戰場是在我們的測試環境中使用。它的主要功能就是如果我們使用了未經處理的 \$_GET 、 $_POST 、 $_COOKIE 之類的變數,就會報出警告資訊。注意,只是警告,而不是錯誤或者異常。一般線上上環境我們都會習慣性地關掉警告資訊的報錯,所以這個擴充套件線上上的功能有限。
擴充套件的安裝非常簡單,下載對應的擴充套件然後進行普通的擴充套件安裝即可,不需要額外的其它作業系統中元件的支援。對於這個擴充套件的詳細資訊,可以參考文末第二條連結中鳥哥文章的說明。
怎麼用?
php.ini 中開啟擴充套件,然後設定 taint.enable = 1 。就正式啟用這個擴充套件了。然後我們通過程式碼來測試。
$a = $_GET['a'];
$file_name = '/tmp' . $a;
$output = "Welcome, {$a} !!!";
$var = "output";
$sql = "Select * from " . $a;
echo $a, "<br/>"; // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 10
echo $output, "<br/>"; // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 12
print $$var; echo "<br/>"; // Warning: main() [print]: Attempt to print a string that might be tainted in /data/www/blog/taint/1.php on line 14
include($file_name);echo "<br/>"; // Warning: main() [include]: File path contains data that might be tainted in /data/www/blog/taint/1.php on line 16
mysqli_query(null, $sql);echo "<br/>"; // Warning: main() [mysqli_query]: SQL statement contains data that might be tainted in /data/www/blog/taint/1.php on line 18
我們使用 php -S 來除錯這個測試檔案,當訪問這個測試檔案並且帶上 a 引數之後,就可以看到下面的這些操作都會報出警告資訊。未經過濾的這個 $a ,不管是拼接到字串中,還是作為可變變數,只要是通過 echo 、 print 、 include 或者是 mysqli_query() 這些函式呼叫後,都會馬上出現報警,提示你使用的這個資料字串是需要進行過濾的。taint 的意思是 汙點 。might be tainted 也就是有汙點內容的意思。
大部分輸出或者運算元據庫之類的函式都會報出這些警告,這些內容的具體資訊可以在官方文件中查詢到。
我們還可以通過一個判斷函式來驗證一個變數中是否包含這類未處理的資料。
var_dump(is_tainted($var)); // bool(false)
echo "<br/>";
var_dump(is_tainted($output)); // bool(true)
echo "<br/>";
怎樣不報警?
怎樣不讓它報警?那當然就是對資料進行處理啦。
$output = "Welcome, ".htmlentities($a)." !!!";
echo $output, "<br/>";
$sql = "Select * from " . mysqli_escape_string(null, $a);
mysqli_query(null, $sql);echo "<br/>";
在輸出的時候進行 html 編碼一下,對應的就是 XSS 攻擊的防範。在資料庫操作的時候 escape 一下,對應的就是處理掉 SQL 注入的攻擊。使用了這些處理函式對資料進行安全性處理之後就不會報警告資訊了。
由此可以看出,這個擴充套件確實是我們在日常開發除錯中,特別是測試環境中的好幫手。就像前面所說的,總會有遺漏和遺忘的地方,通過這個擴充套件讓程式來自動發現這些內容,對於我們開發的安全來說就能夠有非常大的提高。
檢測及轉換函式
最後在 Taint 擴充套件中,還提供了兩個函式用於強制進行警告和解除警告的作用,當然,也是為了我們在測試環境中的除錯方便。
$newOutput = "Welcome !!!";
echo $newOutput, "<br/>";
var_dump(taint($newOutput)); // bool(true)
echo $newOutput, "<br/>"; // // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 39
$newOutput = "Welcome {$a} !!!";
echo $newOutput, "<br/>"; // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 42
var_dump(untaint($newOutput)); // bool(true)
echo $newOutput, "<br/>";
taint() 函式可以讓一個正常的語句報出警告。而 untaint() 則可以讓一個本身應該報警的資料不報警。
總結
同樣還是非常小眾的擴充套件,但是學習了之後發現還真的是挺有用的,而且特別適合在我們的測試環境中向大家提供一個全面檢測安全質量的報警系統。就像文中一直強調的那樣,對於中大型的專案開發來說,遺漏是不可避免的,即使有完善的 code review 機制,但也總會有所有人都遺漏的漏洞存在。通過程式的方式來檢驗自然是最好不過的,大家可以多多嘗試一下。
測試程式碼:
參考文件: