# 19.5. XMLを扱うモジュール群

PythonのXMLを扱うインタフェースは `xml` パッケージにまとめられています。

警告

XML モジュール群は不正なデータや悪意を持って生成されたデータに対して安全ではありません。信頼できないデータをパースする必要がある場合は、 XML の脆弱性 を参照してください。

注意すべき重要な点として、 `xml` パッケージは少なくとも一つの SAX に対応した XML パーザが利用可能でなければなりません。Expat パーザが Python に取り込まれているので、 `xml.parsers.expat` モジュールは常に利用できます。

`xml.dom` および `xml.sax` パッケージのドキュメントは Python による DOM および SAX インタフェースへのバインディングに関する定義です。

XML に関連するサブモジュール:

- `xml.etree.ElementTree`: ElementTree API、シンプルで軽量な XML プロセッサ

- `xml.dom`: DOM API の定義

- `xml.dom.minidom`: 最小限の DOM の実装

- `xml.dom.pulldom`: 部分的な DOM ツリー構築のサポート

- `xml.sax`: SAX2 基底クラスと便利関数群

- `xml.parsers.expat`: Expat parser バインディング

# 19.6. XML の脆弱性

XML処理モジュールは悪意を持って生成されたデータに対して安全ではありません。 攻撃者は脆弱性を使って、 DoS攻撃、ローカルファイルへのアクセス、他マシンへのネットワーク接続、ファイアーウォールの迂回などが可能になります。 XML に対する攻撃は、エンティティに対するインライン DTD (Document Type Definition) などのマイナーな機能を悪用します。

以下のテーブルは知られている攻撃と、各モジュールがそれに対して脆弱であるかどうかを示しています。

種類 | sax | etree | minidom | pulldom | xmlrpc
--- | --- | --- | --- | --- | ---
billion laughs | 脆弱 | 脆弱 | 脆弱 | 脆弱 | 脆弱
quadratic blowup | 脆弱 | 脆弱 | 脆弱 | 脆弱 | 脆弱
external entity expansion | 脆弱 | 安全 (1) | 安全 (2) | 脆弱 | 安全 (3)
DTD retrieval | 脆弱 | 安全 | 安全 | 脆弱 | 安全
decompression bomb | 安全 | 安全 | 安全 | 安全 | 脆弱

1. `xml.etree.ElementTree` は外部のエンティティを展開せず、 ParserError 例外を発生させます。

2. `xml.dom.minidom` は外部エンティティを展開せず、展開前のエンティティをそのまま返します。

3. `xmlrpclib` は外部エンティティを展開せず、除外します。

billion laughs / exponential entity expansion

  Billion Laughs 攻撃 -- exponential entity expansion とも呼ばれる -- は、複数レベルにネストしたエンティティを用います。 各エンティティは他のエンティティを複数回参照し、最後のエンティティ定義は小さい文字列を含みます。 最終的に、その小さい文字列は数ギガバイトにまで展開されます。 exponential expansion は大量の CPU 時間も消費します。

quadratic blowup entity expansion

  quadratic blowup 攻撃は Billion Laughs 攻撃と似ています。こちらもエンティティの展開を利用します。 ネストしたエンティティを用いる代わりに、数千文字のエンティティ1つを繰り返し利用します。 この攻撃は指数関数的な効率はありませんが、パーサーのエンティティのネスト対策を回避します。

external entity expansion

  エンティティの定義はただのテキスト置換以上のことができます。 public identifier や system identifier を使って外部のリソースを参照することもできます。 system identifier は標準的な URI やローカルファイルを参照できます。 XML パーサーはリソースを HTTP や FTP リクエストを用いて取得し、その内容を XML ドキュメントに埋め込みます。

DTD retrieval

  Python の `xml.dom.pulldom` のような XML ライブラリは DTD をリモートやローカルの場所から読み込みます。 この機能には外部エンティティ展開の問題と同じことが予想されます。

decompression bomb

  decompression bomb (ZIP bomb とも呼ばれる) 問題は、 gzipped HTTP ストリームや LZMA ファイルなどの圧縮された XML ストリームをパースできる全ての XML ライブラリに適用されます。 攻撃者は送信するデータ量を1/3かそれ以下に減らすことができます。

PyPI にある defusedxml のドキュメントは、全ての知られている攻撃手法についてのさらなる情報を、例や参照つきで提供しています。

## 19.6.1. defused packages

これらの拡張パッケージは、信頼出来ない XML データを解析するあらゆるコードでの使用に推奨されます。

defusedxml は、潜在的に悪意のある操作を防止するように修正された標準 XML パーザのサブクラスを含む pure Python パッケージです。このパッケージには、さらに exploit の例や xpath インジェクションのようなより多くの XML exploit についての幅広いドキュメントが付属しています。

defusedexpat は libexpat を改造したものと、 `pyexpat` にパッチを当てた拡張モジュールで、エンティティ展開を使った DoS 攻撃の対策をしています。 defusedexpat は、安全で設定可能な量のエンティティ展開を許可します。 この改造は将来のバージョンの Python にマージされる予定です。

これらのワークアラウンドや改造は、後方互換性のためにパッチレベルのリリースには含められません。また、インライン DTD とエンティティ展開は、正しく定義された XML の機能です。