php弱类型漏洞,php代码审计之弱类型引发的灾难
天融信阿爾法實驗室 李喆
有人說php是世界上最好的語言,這可能是對開發人員來說,確實有這方面的特點,因為它開發起來不像其他語言那樣麻煩,就比如:弱類型,它不需要像java等語言那樣明確定義數據類型。這給開發帶來了很大的便利,所有的數據類型都可以用$xx來定義,而不需要int i,string a,fload b等等這樣去定義它。這樣確實很方便,因為php幫助你判斷了數據類型,比如整形int ,你只要$a=1;那這個1就是整形,$a=’abc’那這個abc就會被php判斷為字符串類型。但是弱類型方便是方便,但是帶來的安全問題也是巨大的,很多的php安全漏洞都是因為它帶來的。
本文是給做代碼審計漏洞挖掘和滲透測試人員總結的一個思路,有不對的地方請多多指出。
這里主要是介紹如何通過利用弱類型來做php代碼審計的漏洞挖掘。漏洞挖掘關鍵點肯定在變量上,因為變量可以承接外來參數和內部數據的交互工作,這是漏洞的起因,也是必要條件。如果外來參數是惡意代碼,同時再因為使用了弱類型的函數或者比較運算符導致了惡意參數的數據進入了程序里比如數據庫,就可能引發想象不到的破壞力。這里我介紹了三種可以導致惡意數據進入判斷體里的函數和比較運算符,他們有共同的特點,就是和數據比較,然后把外來變量做自動類型轉換,如果外來變量是惡意變量,利用一定的方法就可以繞過你想繞過的地方比如判斷if條件,讓惡意變量進入到條件體內,惡意變量如果在判斷體內被代入到了數據庫的增刪改查操作中就可以引發sql注入等漏洞問題。
01第一個要介紹的是 is_numeric,它的功能是,判斷參數是否為數字或者數字字符串,如果是則返回true,假返回false,它的弱類型問題是他支持十六進制0x格式,如何引發的安全問題讓我們繼續觀看。
安全問題描述:is_numeric在做判斷時候,如果攻擊者把payload改成二進制0x..,is_numeric會先對十六進制做類型判斷,十六進制被判斷為數字型,為真,就進入了條件語句,如果再把這個代入進入sql語句進入mysql數據庫,mysql數據庫會對hex進行解析成字符串存入到數據庫中,如果這個字段再被取出來二次利用,就可能因為二次注入漏洞.比如這樣:
if(is_numeric($_GET['num']))
{
echo $_GET['num'];
echo “”;
//假設這個插入進了mysql數據庫,mysql數據庫就會把十六進制轉換成了字符串,這里為了方便用 Hex2String 函數代替
echo Hex2String($_GET['num']);
//輸入http://127.0.01/equal.php?num=0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f21212729
// 輸出0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f2121272
//輸出9999999999999 union all (select ‘Hello!!’)
}
function Hex2String($hex){
$string=”;
for ($i=0; $i < strlen($hex)-1; $i+=2){
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
可以看到,數據庫存入的是 9999999999999 union all (select ‘Hello!!’) ,如果被取出來再輸出沒做過濾就會引發二次注入
防御方法:用intval函數獲取變量整數值,對從數據庫取出變量做過濾
上面的不理解,可以看一個案例分析:
這里有個例子:
圖1.1
問題出現在if (!isset($_POST['id'], $_POST['vote']) || !is_numeric($_POST['id'])) 如果能繞過is_numeric,就可以執行mysql_query(“INSERT INTO vote VALUES ({$id}, {$vote}, ‘{$login}’)”); 注入sql語句。
999999999999 union all \(select ‘Hello!!’\)
轉成 hex=0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f21212729
我們提交的參數:
vote=1&submit=&id=0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f21212729
圖1.2
我們可以清楚的在圖片里看到,我們插入的Hello!在其他查詢位置被顯示了出來,引發了二次注入漏洞問題。
02 第二個介紹的是比較運算符的安全隱患,比如 ==,!= ,同時還會介紹他們和恒等式和=== ,!==的區別和安全問題
函數功能:
==和!=是比較運算符號 不會檢查條件式的表達式的類型
安全問題描述:php是弱類型,在做匹配和比較時候,會根據匹配的類型做類型轉換,如果后面是整形,如$a==1,因為后面的1是整形,那前面gpc傳進來就會轉換成整形,轉換規則是前面的數字不變后面字母被當成字符型舍去,也就是1a會變成1,判斷為真進入判斷體;如果這樣$a==”1″,那么后面的就是字符串1,如果gpc傳進來1a會發現為假,因為傳進來的1a做類型轉換成字符串后就是1a,字符串1a和字符串1不想等,所以為假,這時候要改成1才能進入判斷體內;同樣在進行加減乘除比較運算判斷時候也會做自動類型轉換,如果跟整形比較,1a會轉換成1,跟字符串比較,a1就會轉換成字符串a1,其他類型也一樣。
如果你覺得這樣很繞看不懂,那就簡單說,如果和字符串做比較,就會轉換成字符串,如果和整形做比較,就會自動轉換成整形,只不過整形自動轉換的時候php就是用的intval 函數導致1a為1。intval函數可以自查下,大致如:intval(“a”)=0; intval(12.3223)=12; intval(“12abc”)=12;
比如:
$a = $_GET['a'];
if ($a==1)
{
echo ‘vul->’.$a;
}
同樣!=也會有這個問題,換成2就可以進到判斷體內
$a = $_GET['a'];
if ($a!=1)
{
echo ‘vul->’.$a;
}
防范方法:用===和!==來做判斷,他們是恒等計算符, 同時檢查表達式的值與類型
跟數字有關的運算都可能引起弱類型漏洞,比如下面這個運算
但是這樣也不完全可以,比如加減乘除運算符也會做類型轉換
假如這樣:
$a = $_GET['a'];
$b = $_GET['b'];
if($a+$b===2)
{
echo “vul->”.$a.””.$b;
}
所以最安全的防范是對gpc獲取數字型的參數值進行intval強制類型轉換或者過濾,再做判斷
$a = intval($_GET['a']);
$b = intval($_GET['b']);
if($a+$b===2)
{
echo “vul->”.$a.””.$b;
}
03 第三個要就介紹的是in_array()函數
函數功能:判斷一個值是否在數組中存在
安全問題描述:這個函數的弱類型問題是,判斷的值在比較之前會做類型轉換,同樣是弱類型問題,比如in_array($_GET['id'],array(1,2,3,4,5)),如果我們傳入 id=1’ union select… ,判斷就會為真,因為id被轉換成1,這時候假如我們再把$_GET['id']拼接到數據庫語句中,就會引起sql注入漏 洞。
if(in_array($_GET['id'],array(1,2,3,4,5)))
{
echo $_GET['id'];
//輸入http://127.0.01/equal.php?id=1′id
//輸出: 1′id
}
防范方法:外來變量要做過濾,或者強制類型轉換
總結
以上是生活随笔為你收集整理的php弱类型漏洞,php代码审计之弱类型引发的灾难的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arcgis标注牵引线_解析ArcGis
- 下一篇: php时间戳本周,php获取今天,昨天,