輸入值的驗證是非常重要的,如果今天忘記加上SQL Injection的過濾器,甚至是一些可利用性的漏洞被發現,有做格式的驗證至少還能將傷害降低,驗證可說是必做的工作。
有些人可能會問,二進制安全到底是什麼問題? 簡單來講,有些 function 會將某些符號看做是有意義性的字元,如:\n、\0 等,故二進制安全的 functon 會將 input 都看做是 raw input ,於是乎\n => '\'+'n'、\0 => '\'+'0',從而避免掉一些問題。
而會有什麼樣的問題呢?
舉例來說,我們有一個php檔,內容為:
<?php
$p = $_GET['p'];
if (ereg('^[0-9]+$', $p) == FALSE) {
die('integer plz');
}
echo $p;
?>
localhost/test.php?p=1234 會顯示正確的處理,但若改成 localhost/test.php?p=1%00<script>alert('xss')</script> 網頁就會跳出 alert !
出問題的原因在於 ereg 並不是一個二進制安全函式,因此 %00 會讓 ereg 誤以為要檢查的字串已經結束了,則 %00 後面的內容就會直接略過檢查,從而引發問題。
最根本的解決方案就是使用二進制安全函式,但是這方法卻很難實現,原因在於各種函式指南都沒有說明何種函式是二進制安全的,因此我們能做的便是去檢查輸入值是否有控制字元的出現,這工作可以輕易地用正則表達式來完成。以下提供 PHP 的範例;
if (preg_match('/\A[[:^cntrl:]]{0,100}\z/u', $s) == 1)
輸入值驗證是非常需要看重的地方,有非常多的 0 day 都會發生在這種 input 處理不當上,像是最近的 shellshock 跟之前的 heartbleed 都是 based on 在這種問題上面,因此重要性不言可喻!
明天就要開始講解攻擊手法囉