首頁 後端開發 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

>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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles