1. 程式人生 > >PHP安全之道學習筆記2:編碼安全指南

PHP安全之道學習筆記2:編碼安全指南

編碼安全指南

程式設計本身就應該是一門藝術,而安全程式設計更是一種在刀尖上舞蹈的藝術,不僅要小心腳下的鋒利寒刃,更要小心來自網路黑客或攻擊者的狂轟亂炸。
- by code artist

  • 1.hash比較的缺陷
    經過試驗發現,當Hash值以"0e"開頭且後面都為數字,當和數字進行比較的時候總會被判斷和0相等

例如:

var_dump('0e1327544' == 0); // bool(true)

當密碼被md5計算後,可能會以"0e"開頭,下面這個例子可以繞過密碼驗證。
經過我的驗證PHP 7.1.x後沒有這種問題。

<?php
    $password_from_db = "0e23434";
    $password = "2323"; // 隨意的一個密碼。來自$_POST,即表單提交
    if ($password_from_db == md5($password)) {
        echo "login success!";
    } else {
        echo "login fails";
    }

更安全的hash比較:
可以使用內建函式hash_equals()來比較hash值。(PHP版本必須是5.6及其以上)

 if (hash_equals($password_from_db, md5($password)) {
     .....// other logic
 }
  • 2.bool比較的缺陷

json_decode和unserialize函式可能將部分結構解析成bool值,造成一些比較上的缺陷。

先舉例json_decode的案例:

<?php
$str = '{"user":true, "pass": true}';

$data = json_decode($str, true);

if ($data['user'] == 'root' && $data['pass'] == 'pass') {
    echo "login success\r\n";
} else {
    echo "login fails\r\n";
}

執行結果為:login success
這樣利用bool比較的漏洞就繞過了登入或者授權驗證。

unserialize過程相逆,結果類似,也會出現安全問題。

正確的做法還是使用"==="來進行比較,這不光是php,包括一些其他指令碼語言或者靜態語言,都請嚴謹地使用全等於符號進行比較。

  • 3.數值比較

PHP雖然是弱型別語言,但是資料型別也有數值範圍。對於整型而言,最大值為PHP_INT_MAX(即9223372036854775807)
攻擊者可以利用最大值越界,繞過一些驗證,如登入、賬號充值等等。

舉例:

$a = 9223372036854775807;
$b = 9223372036854775827;
var_dump($a === $b); // bool(true)
var_dump($a % 100); // int(0)

由此,可見全等號(===)也不是萬能的,具體場景下要更小心。經驗證,PHP7.1.x後不會出現該問題,5.x的可能出現。

在實際業務邏輯裡面一定要注意判斷最大值問題,避免越界帶來的問題。

當使用超長浮點數變數的時候,PHP也會出錯。

<?php
$uid = 0.999999999999999999;
if ($uid == "1") {
    echo "search uid is 1 for data\r\n"; // 這裡PHP將$uid約等於1了,進入該判斷條件裡的邏輯
}

同理,2.999999999999也會被當成3,這就是超越浮點數精度造成的偏差。

解決辦法有很多,最簡單的就是用is_int()函式進行判斷,如果不是整型,則報錯或做錯誤處理。

  • 4.switch缺陷

當用case判斷數字的時候,switch會把引數轉換成int型別進行計算,程式碼如下:

<?php
$num = "1FreePHP";
switch ($num) {
    case 0: echo "nothing";
        break;
    case 1: echo "1 hacker here!";
        break;
    case 2: echo "2 hackers here";
        break;
    default:
        echo "confused";
}

最後輸出:1 hacker here!

所以,請使用is_numeric()函式進行判斷,保證資料型別如預期的一致。

  • 5.陣列缺陷。
    in_array()和array_search()函式在沒有使用嚴格模式的情況下會用鬆散比較,可能造成一些錯誤。
    例如:
<?php
$arr = [0, 2, 3, "4"];
var_dump(in_array('freephp', $arr)); // true
var_dump(array_search('freephp', $arr)); // 0: 下標
var_dump(in_array('2freephp', $arr)); // true
var_dump(array_search('3freephp', $arr)); // 2: 下標

總的來說,PHP工程師對於這種弱型別語言的使用上要更加小心,雖然平時寫起業務來“短平快”,但安全程式設計也不要忘記,能用上hint的高版本PHP就進行標註清楚入參、出參,讓PHP程式碼更加健壯。