搜尋
首頁後端開發php教程談PHP弱型別安全問題
談PHP弱型別安全問題Apr 27, 2019 am 11:37 AM
php弱類型

這篇文章小編想和大家談談PHP弱類型,PHP弱類型給程式設計師書寫程式碼帶來了很大的便利,但是任何事物都有兩面性,現在隨著小編一起了解一下吧。

0x00 弱型別初探

#沒有人質疑php的簡單強大,它提供了許多特性供開發者使用,其中一個就是弱類型機制。

在弱型別機制下 你能夠執行這樣的操作

<?php
$var = 1;
$var = array();
$var = "string";
?>

php不會嚴格檢驗傳入的變數型別,也可以將變數自由的轉換型別。

例如在$a == $b的比較中

$a = null; $b = false; //为真
$a = &#39;&#39;; $b = 0; //同样为真

然而,php核心的開發者原本是想讓程式設計師藉由這種不需要宣告的體系,更有效率的開發,所以在幾乎所有內建函數以及基本結構中使用了很多鬆散的比較和轉換,防止程式中的變數因為程式設計師的不規範而頻繁的報錯,然而這卻帶來了安全問題。

0x02 知識預備php核心之zval結構

在PHP中宣告的變量,在ZE中都是用結構體zval來保存的

zval的定義在zend/zend.h

typedef struct _zval_struct zval;  
struct _zval_struct {  
  /* Variable information */  
  zvalue_value value; /* value */  
  zend_uint refcount__gc;  
  zend_uchar type;/* active type */  
  zend_uchar is_ref__gc;  
};  
typedef union _zvalue_value {  
  long lval;  /* long value */  
  double dval;/* double value */  
  struct {  
    char *val;  
    int len;  
  } str;  
  HashTable *ht;  /* hash table value */  
  zend_object_value obj;  
} zvalue_value;

其中php透過type判斷變數型別存入value

如上也就是php核心中弱型別的封裝,也是我們後面講的所有東西的原理和基礎。

0x03變數的強制轉換

#透過剛剛的了解,我們知道zval.type決定了儲存到zval.value的類型。

當原始碼進行一些未限制類型的比較,或數學運算的時候,可能會導致zval.type的改變,同時影響zval.value的內容改變。

當int遇到string

cp.1 數學運算

當php進行一些數學運算的時候

ar_dump(0 == &#39;0&#39;); // true
var_dump(0 == &#39;abcdefg&#39;); // true  
var_dump(0 === &#39;abcdefg&#39;); // false
var_dump(1 == &#39;1abcdef&#39;); // true

當有一個對比參數是整數的時候,會把另一個參數強制轉換為整數。

相當於對字串部分

intval再和整數部分比較,其實也就是改變了zval.type的內容尤為注意的是,'1assd'的轉換後的值是1 ,而'asdaf'是0

也說明了intval會從第一位不是數字的單位開始進行

所有也有

var_dump(intval(&#39;3389a&#39;));//输出3389

這個例子就告訴我們,永遠不要相信下面的程式碼

if($a>1000){    
mysql_query(&#39;update ... .... set value=$a&#39;)
}

你以為這時候進入該支的萬無一失為整數了

其實$a可能是1001/**/union...

#cp.2 語句條件的鬆散判斷

舉例php的switch使用了鬆散比較. $which會被自動intval變成0如果每個case裡面沒有break ,就會一直執行到包含,最終執行到我們需要的函數,這裡是成功包含

<?php
if (isset($_GET[&#39;which&#39;]))
{
  $which = $_GET[&#39;which&#39;];
  switch ($which)
  {
  case 0:
  case 1:
  case 2:
    require_once $which.&#39;.php&#39;;
    break;
  default:
    echo GWF_HTML::error(&#39;PHP-0817&#39;, &#39;Hacker NoNoNo!&#39;, false);
    break;
  }

cp.3 函數的鬆散判斷

var_dump(in_array("abc", $array));

in_array — 檢查數組中是否存在某個值參數

needle 待搜尋的值。

Note: 如果 needle 是字串,則比較是區分大小寫的。 haystack 這個數組。

strict 如果第三個參數 strict 的值為 TRUE 則 in_array() 函數也會檢查 needle 的型別是否和 haystack 中的相同。

可以看到,只有加了strict才會對型別做嚴格比較, 那我們再把×××和字串做比較呢?

var_dump(in_array("abc", $array1));</br>
var_dump(in_array("1bc", $array2));

它遍歷了array的每個值,並且作"=="比較(“當設定了strict 用===”)

結果很明顯了

如果array1裡面有個值為0,那麼第一條回傳就會為真//intval('abc')=0

如果array2裡面有個值為1,那麼第二條就會為真//intval('1bc')=1

array_search也是一樣的原理

這裡的應用就很廣泛了,

很多程式設計師都會檢查數組的值,

那麼我們完全可以用建構好的int 0或1 騙過檢測函數,使它回傳為真

總結一下, 在所有php認為是int的地方輸入string,都會被強制轉換,例如

$a = &#39;asdfgh&#39;;//字符串类型的a</br>
echo $a[2];  //根据php的offset 会输出&#39;d&#39;</br>
echo $a[x];  //根据php的预测,这里应该是int型,那么输入string,就会被intval成为0 也就是输出&#39;a&#39;

當陣列遇上string

這一個例子我是在德國的一個ctf中遇到,很有意思前面我們講的都是string和int的比較

那麼array碰上int或是string會有什麼化學反應?

由php手冊我們知道

Array轉換整數int/浮點型float會傳回元素個數;

轉換bool傳回Array中是否有元素;轉換成string回傳'Array',並拋出warning。

那麼實際應用是怎麼樣的呢?

if(!strcmp($c[1],$d) && $c[1]!==$d){
...
}

可以發現,這個分支透過strcmp函數比較要求兩者相等且「==」要求兩者不相等才能進入。

strcmp() 函數比較兩個字串。

此函數傳回:

0 - 如果兩個字串相等

>0 - 如果string1大於string2

這裡的strcmp函數其實是將兩個變數轉換成ascii 然後做數學減法,傳回一個int的差值。

也就是說鍵入'a'和'a'進行比較得到的結果就是0

那麼如果讓$array和‘a’比較呢?

http://localhost:8888/1.php?a[]=1
var_dump(strcmp($_GET[a],&#39;a&#39;));

這時候php回傳了null!

也就是說,我們讓這個函數出錯從而使它恆真,繞過函數的檢查。

0x04時時防備弱型別

#身為程式設計師,弱型別確實為程式設計師書寫程式碼帶來了很大的便利,但也讓程式設計師忘記了$array =array();的習慣。都說一切輸入都是有害的

那麼其實可以說一切輸入的類型也是可疑的,永遠不要相信弱類型的php下任何比較函數,任何數學運算。否則,你絕對是被php出賣的那一個。

相關教學:PHP影片教學

#

以上是談PHP弱型別安全問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:51cto。如有侵權,請聯絡admin@php.cn刪除
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace("&nbsp;","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么查找字符串是第几位php怎么查找字符串是第几位Apr 22, 2022 pm 06:48 PM

查找方法:1、用strpos(),语法“strpos("字符串值","查找子串")+1”;2、用stripos(),语法“strpos("字符串值","查找子串")+1”。因为字符串是从0开始计数的,因此两个函数获取的位置需要进行加1处理。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具