一個合格程序猿應該知道的基礎知識—XML注入介紹

一個合格程序猿應該知道的基礎知識—XML注入介紹

(圖片源於網絡,侵刪)

ps:竟然有人說我是教小學生的!我就不信小學生能看懂我今天給的東西!

XML,Extensible Markup Language,擴展性標識語言。文件的後綴名為:.xml。就像HTML的作用是顯示數據,XML的作用是傳輸和存儲數據。今天阿姨給你們詳細介紹一下關於XML的知識(敲黑板!文章略長,請仔細閱讀)

1

XML定義

XML由3個部分構成,它們分別是:文檔類型定義(Document Type Definition,DTD),即XML的佈局語言;可擴展的樣式語言(Extensible Style Language,XSL),即XML的樣式表語言;以及可擴展鏈接語言(Extensible Link Language,XLL)。

XML:可擴展標記語言,標準通用標記語言的子集,是一種用於標記電子文件使其具有結構性的標記語言。


它被設計用來傳輸和存儲數據(而不是儲存數據),可擴展標記語言是一種很像超文本標記語言的標記語言。設計宗旨是傳輸數據,而不是顯示數據。它的標籤沒有被預定義。你需要自行定義標籤。


它被設計為具有自我描述性,是W3C的推薦標準。是用來傳輸和存儲數據,其焦點是數據的內容。


一個合格程序猿應該知道的基礎知識—XML注入介紹


2

XML作用

XML應用於wed開發的許多方面,最常用的作用就是配置文件和數據讀寫操作。

  • 文件


許多應用都將配數據存儲在各種文件裡,比如.INI文件。雖然這樣的文件格式已經使

用多年並一直很好用,但是XML還是以更為優秀的方式為應用程序標記配數據。使用. NET裡的類,如XmlDocument和XmlTextReader,將配數據標記為XML格式,能使其更具可讀性,並能方便地集成到應用系統中去。使用XML配文件的應用程序能夠方便地處理 所需數據,不用象其他應用那樣要經過重新編譯才能修改和維護應用系統。


  • 數據讀寫操作

在真實的世界中,計算機系統和數據使用不兼容的格式來存儲數據。XML 數據以純文本格式進行存儲,因此提供了一種獨立於軟件和硬件的數據存儲方法。這讓創建不同應用程序可以共享的數據變得更加容易通過 XML,可以在不兼容的系統之間輕鬆地交換數據。對開發人員來說,其中一項最費時的挑戰一直是在因特網上的不兼容系統之間交換數據。由於可以通過各種不兼容的應用程序來讀取數據,以 XML 交換數據降低了這種複雜性。

一個合格程序猿應該知道的基礎知識—XML注入介紹


3

XML格式說明

這裡我們要給對方傳輸一段數據,數據內容是too young,too simple,sometimes naive”,要將這段話按照屬性拆分為三個數據的話,就是,年齡too young,閱歷too simple,結果sometimes naive。
我們都知道程序不像人,可以體會字面意思,並自動拆分出數據,因此,我們需要幫助程序做拆分,因此出現了各種各樣的數據格式以及拆分方式。比如,可以是這樣的數據為“too young,too simple,sometimes naive”然後按照逗號拆分,第一部分為年齡,第二部分為閱歷,第三部分為結果。
也可以是這樣的數據為“too_young* too_simple*sometimes_naive”從數據開頭開始截取前面十一個字符,去掉號並把下劃線替換為空格作為第一部分,再截取接下來的十一個字符同樣去掉並替換下劃線為空格作為第二部分,最後把剩下的字符同樣去號體會空格作為第三部分。
這兩種方式都可以用來容納數據並能夠被解析,但是不直觀,通用性也不好,而且如果出現超過限定字數的字符串就容納不了,也可能出現數據本身就下劃線字符導致需要做轉義。基於這種情況,出現了xml這種數據格式, 上面的數據用XML表示的話可以是這樣

一個合格程序猿應該知道的基礎知識—XML注入介紹

也可以是這樣

一個合格程序猿應該知道的基礎知識—XML注入介紹

兩種方式都是xml,都很直觀,附帶了對數據的說明,並且具備通用的格式規範可以讓程序做解析。如果用json格式來表示的話,就是下面這樣


一個合格程序猿應該知道的基礎知識—XML注入介紹

其實數據都是一樣的,不同的只是數據的格式而已,同樣的數據,我用xml格式傳給你,你用xml格式解析出三個數據。


4

XML的實體

XML實體分為:參數實體和通用實體兩種。參數實體用在DTD定義中。一般的xml文檔中都使用通用實體。這裡只介紹通用實體。

一個合格程序猿應該知道的基礎知識—XML注入介紹

使用實體之前,必需先聲時,聲明語句位於xml文檔的序言的內部子集中,實體聲明必需使用大寫方式,如: ,ENTITY必需是大寫的。


使用實本時,在實體名稱前面加上 & ,並表在後面加上分號: ;。與HTML中的轉義符類似。在以下xml中:&client;引用了一個實體,&241;引用了一個實體。當xml處理器碰到實體引用時,會使用定義實體時設定的值去代替實體聲時。 


如下面的示例,當處理器解析到&client;時, 會使用"Mr.Rufus Xavier Sasperilla"來代替這個&client;在解析後的文本中,是看不到&client;的。


一個合格程序猿應該知道的基礎知識—XML注入介紹

  • 字符實體

字符實體用來代表單個字符。字符實體分為以下三種:


a、預定義字符實體


由XML規範預先定義好了,如 amp 代表&, apos 代表單引號,gt 代表>, 在使用時加上&號,如: & 表示單個字符&, ' 表示單引號。

b、數字字符實體


在前面我們總結實體的作用時,有一條;可以代表無法輸入的字符。這些字符就是使用數字字符實體表示的。我們可以使用某個字符在字符集中的位 置數來表示該字符。 該數字可以使用10進制或16進制的方式表示,在數字前面加上: , 比如: ç 16進制的表示:ç , 這兩種方式都表示同一個字符。


c、命名字符實體

與數字字符實體類似,只是將數字改為一個更容易記憶的英文標識.

  • 混合內容實體

混合內容實體是xml中使用得最多的實體,它的值不僅限於單個字符,還可以代表不限長度的各種字符塊。混合內容實體分為:內部實體和外部實體


a、內部混合實體


內部混合實體表示該實體在xml文檔內部定義,內部實體常用來代替經常重複的短語,名稱和模板文本。上面的xml示例中,agent實體就是典型。除了agent,clietn, phone 實體都是內部混合實體。


a、外部混合實體

一些實體需要代表大塊的字符,為了便於文件的管理,可以將這些大塊的字符放在其他文件中,這是外部混合實體便發揮作用了。可以在外部文件中定義實體,然後在xml文檔中聲明並使用它。下面是一個例子:

一個合格程序猿應該知道的基礎知識—XML注入介紹

 聲明瞭一個名稱為;“part1"的外部實體,該實體代表的內容處於P1.xml文件中。 part2, part3 也分別代表了 p2.xml, p3.xml 中的內容。

外部混合實體最大的用處是可以將內容太長的xml文檔分成幾個小的xml文檔,便於網絡傳輸。


  • 未析實體


未析實體代表不同於xml文檔內容的其他數據,如:二進制數據等等。當xml處理器無法識別該數據時,不會像對待其他實體一樣,去解析它,而是讓它保持原樣。未析實體的定義與外部混合實體的聲明方式類似,只是後面多了個“NDATA”字符和一些數據標識。比如:


一個合格程序猿應該知道的基礎知識—XML注入介紹



5

XML外部實體注入

XXE注入,即XML External Entity,XML外部實體注入。通過 XML 實體,”SYSTEM”關鍵詞導致 XML 解析器可以從本地文件或者遠程 URI 中讀取數據。


所以攻擊者可以通過 XML 實體傳遞自己構造的惡意值,是處理程序解析它。當引用外部實體時,通過構造惡意內容,可導致讀取任意文件、執行系統命令、探測內網端口、攻擊內網網站等危害。下面介紹兩個注入實例:


  • 文件內容和信息洩露


在早前的一個信息洩露的例子中,我們注意到自定義實體可能引用一個外部文件。

一個合格程序猿應該知道的基礎知識—XML注入介紹

這會把文件內容擴展到自定義的&harmless;實體中。由於所有類似的請求都是在本地完成的,這使得該應用有權限讀取的所有文件內容都可能被洩露。


只要應用的輸出中包含了這個擴展了的實體,攻擊者就可以查看那些文件,包括沒有公開的文件。因這種方式而造成內容洩露的文件是相當有限的,只能是XML文件,和不會造成XML解析錯誤的文件。但是,PHP可以完全忽略這種限制。

一個合格程序猿應該知道的基礎知識—XML注入介紹

PHP允許通過URI訪問PHP wrapper,這是一般文件系統函數,如file_get_contents()、require()、require_once()、file()、和copy()等,接受的協議之一。

PHP wrapper支持一些過濾器,這些過濾器運行在給定的資源上,結果可以通過函數調用返回。在上述例子中,我們對想要讀取的目標文件使用了convert.base-64-encode過濾器。

這意味著,攻擊者通過利用XXE的脆弱性,可以用PHP讀取任何可讀的文件,不論文本格式如何。攻擊者只需用base64將應用輸出解碼,就可以毫無顧忌的分析一大堆非公開文件的內容。

儘管這本身不會直接傷害終端用戶或是應用後臺,但是它能讓攻擊者瞭解目標應用,從而以最小的代價、最低的風險發現應用的其他弱點。

  • 繞過訪問控制


訪問控制可以通過各種方法來實現。由於XXE攻擊是掛在web應用後臺的,它無法使用當前用戶會話產生任何影響,但是攻擊者仍然可以藉助從本地服務器發送請求,來繞過後臺訪問控制。我們來看一下下面這個簡單的訪問控制:


一個合格程序猿應該知道的基礎知識—XML注入介紹

這段PHP和無數的類似代碼都用於限制特定PHP文件對本地服務器的訪問,如 localhost。但是,應用前端的XXE脆弱性,正好為攻擊者提供了繞過訪問控制所需的憑證,因為XML解析器發出的所有HTTP請求都來自localhost。


一個合格程序猿應該知道的基礎知識—XML注入介紹

如果只有本地請求可以查看日誌,攻擊者就可以成功獲取日誌。同樣的思路也適用於只接受本地請求的維護和管理接口。


6

如何抵禦XML外部實體注入

這類攻擊十分“誘人“,但對它的防禦也簡單的出奇。既然DOM、SimpleXML和XMLReader依賴於libxml2,我們可以簡單地利用libxml_disable_entity_loader()函數來禁止外部實體引用。


與此同時,DOCTYPE中預定義的自定義實體卻不會受到影響,因為它們並沒有使用任何需要文件系統操作或發送HTTP請求的外部資源。

一個合格程序猿應該知道的基礎知識—XML注入介紹

在所有涉及通過字符串、文件或者遠程URI來加載XML時,都需要使用這些操作。

當應用程序及其大部分請求都不需要外部實體時,你可以簡單地從全局禁掉外部資源加載。大多數時候,這比找出所有的XML加載實例來逐個操作要更好。記住,許多庫天生自帶XEE脆弱性:

一個合格程序猿應該知道的基礎知識—XML注入介紹


每次需要臨時允許加載外部資源時,加載完後切記再把這裡設為TRUE。例如,在將Docbook XML轉換為HTML時,所使用的XSL樣式就是依賴於外部實體的,這裡需要外部實體,但是是無害的。

但是,libxml2函數絕不是”萬能鑰匙”。我們需要確認,其他用於解析或處理XML的擴展和PHP庫的引用外部實體的功能,都處於關掉狀態。


如果不能通過上述方法來開關外部實體引用,你還可以檢查一下XML文檔是否聲明瞭DOCTYPE。如果聲明瞭,同時禁掉了外部實體,則可以簡單地丟棄XML文檔,拒絕可能造成解析器脆弱性的不受信任的XML訪問,同時將這種行為記錄為一次可能的攻擊。


我們需要將這種行為記錄下來,因為除此之外不會有任何系統報錯記錄。可以在日常輸入驗證中進行這項檢查。但是,這種方法並不理想,我們還是強烈建議從源頭上解決外部實體的問題。


一個合格程序猿應該知道的基礎知識—XML注入介紹


同時,值得注意的是,當我們懷疑一段數據有可能是某個攻擊的結果時,最好的方法是丟棄它,而不是繼續使用它。既然它已經表現出了危險,為什麼還要繼續使用它呢?

因此,將上述兩個步驟合併起來,我們可以在無法丟棄數據時(例如第三方的庫),通過主動跳過壞數據起到保護作用。


之所以我們更願意完全丟棄這些數據,還因為上文提到過的一個理由:libxml_disable_entity_loader()不會將自定義實體完全禁掉,只有引用外部資源的才會被禁掉。因此這仍有可能導致一個被稱為XML實體擴展的注入攻擊。(未完待續)

一個合格程序猿應該知道的基礎知識—XML注入介紹


以上:就是今天的知識點,大家都看明白了嗎,沒看明白的扣個1,讓阿姨看看誰家孩子這麼bèn~


ps:竟然有人不喜歡玩掃雷,白給你的掃雷外掛不要我就自己私藏嘍~今天還能領,私信我03就給你





分享到:


相關文章: