web安全/滲透測試--23--XML注入攻擊
阿新 • • 發佈:2018-12-10
1、漏洞描述:
可擴充套件標記語言(Extensible Markup Language, XML),用於標記電子檔案使其具有結構性的標記語言,可以用來標記資料、定義資料型別,是一種允許使用者對自己的標記語言進行定義的源語言。XML是標準通用標記語言(SGML)的子集,非常適合Web傳輸。XML提供統一的方法來描述和交換獨立於應用程式或供應商的結構化資料。XML注入攻擊,和SQL注入的原理一樣,都是攻擊者輸入惡意的程式碼來執行自身許可權以外的功能。
XML是儲存資料的一種方式,如果在修改或者查詢時,沒有做轉義,直接輸入或輸出資料,都將導致XML注入漏洞。攻擊者可以修改XML資料格式,增加新的XML節點,對資料處理流程產生影響。
2、檢測條件:
被測網站使用可擴充套件標記語言。
3、檢測方法
看一個儲存註冊使用者資訊為XML格式的例子:
final String GUESTROLE = "guest_role";
...
//userdata是準備儲存的xml資料,接收了name和email兩個使用者提交來的資料。
String userdata = "<USER role="+GUESTROLE+">
<name>"+request.getParameter("name")+"</name>
<email>" +request.getParameter("email")+"</email>
</USER>";
//儲存xml
userDao.save(userdata);
可以看到,這段程式碼沒有進行任何的過濾操作。一個普通使用者註冊後,會產生這樣一條資料記錄:
<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
<name>user1</name>
<email>[email protected] </email>
</USER>
攻擊者輸入自己email時,可以輸入如下程式碼:
[email protected]</email></USER><USER role="admin_role"><name>lf</name><email>[email protected]
終端使用者註冊後,資料就變成了:
<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
<name>user1</name>
<email>[email protected]</email>
</USER>
<USER role="admin_role">
<name>lf</name>
<email>[email protected]</email>
</USER>
可以看到,多出了一條role=“admin_role”的管理員lf。達到攻擊目的。
插入元字元
單引號: 當未被過濾時,如果被注入的值是標籤屬性值的一部分,該字元會在XML解析過程中引發異常。<node attrib=’foo’’> //注意是一邊是兩個單引號。
雙引號: 和單引號同義。
尖括號: 實現開放或閉合。<username>foo<</username>
註釋標籤: <!--/-->。註釋的開始和結尾。<username>foo<!--</username>
與符號: &。在XML演算法中表示實體。<username>&foo</username> //新節點被建立但文件無效
CDATA區段分隔符: <![CDATA[/]]>。如<username><! [CDATA [/] ]></username> //無效XML片段
4、修復方案:
1、常見的XML解析方法有:
DOMDocument、SimpleXML、XMLReader,這三者都基於libxml庫解析XML,所以均受影響;xml_parse函式則基於expact解析器,預設不載入外部DTD,則不受影響。可以在php解析xml檔案之前使用libxml_disable_entity_loader(true)來禁止載入外部實體(該方法對上述三種XML解析元件都有效),並使用libxml_use_internal_errors()禁止報錯。
2、對關鍵字串進行轉義:
& --> &
< --> <
> --> >
" --> "
' --> '
3、在XML儲存和展示之前,對資料部分,單獨做轉義即可:
String userdata = "<USER role="+GUESTROLE+">
<name>"+StringUtil.xmlencode(request.getParameter("name"))+"</name>
<email>"+StringUtil.xmlencode(rrequest.getParameter("email"))+"</email>
</USER>";