機械翻訳について

Java API for XML Processing (JAXP)セキュリティ・ガイド

JDKおよびJava XML APIは、アプリケーションがXML関連の攻撃によって悪用されないようにするのに役立つ様々な手段とツールで何年にもわたり改善されてきました。 このガイドでは、Java API for XML Processing (JAXP)のセキュア処理機能を使用してアプリケーションおよびシステムを保護する方法を示します。

トピック

XML処理中の潜在的な攻撃

XML処理は、アプリケーションを一定の脆弱性に晒すことがあります。 最も顕著で有名な攻撃は、XML外部エンティティ(XXE)インジェクション攻撃と指数関数的エンティティ展開攻撃で、XML爆弾やBillion laughs攻撃とも呼ばれます。 これらの攻撃は、そのサービスを拒否することでシステムの重大な破損を引き起こしたり、さらに悪いことに機密データの喪失につながったりすることがあります。

アプリケーションの要件およびオペレーティング環境を評価して、潜在的な脅威のレベル(たとえば、信頼できないXMLソースにアプリケーションが公開されているかどうか、またはどの程度公開されているか)を評価する必要があります。

XML外部エンティティ・インジェクション攻撃

XML、XMLスキーマおよびXSLT標準では、外部リソースを参照するシステム識別子を通じてXMLドキュメントに外部コンテンツを埋め込むことができる構造をいくつか定義します。 一般に、XMLプロセッサは、これらの外部リソースのほぼすべてを解決および取得します。外部リソースの挿入をサポートするコンストラクトのリストは、「XML、スキーマおよびXSLT標準でサポートされる外部リソース」を参照してください。 また、一部のコンストラクトでは、外部関数を通じてアプリケーションを実行できます。 XML外部エンティティ(XXE)インジェクション攻撃は、解決、取得または実行できる外部リソースの制限によって保護されていないXMLプロセッサを悪用します。 これにより、パスワードなどの機密データが開示されたり、コードを任意に実行できるようになったりすることがあります。

XML、スキーマおよびXSLT標準でサポートされている外部リソース

XML、スキーマおよびXSLT標準では、外部リソースを必要とする次のコンストラクトがサポートされています。 JDK XMLプロセッサのデフォルトの動作では、接続を作成し、指定された外部リソースをフェッチします。

指数関数的エンティティ展開攻撃

XML爆弾またはBillion laughs攻撃とも呼ばれる指数関数的エンティティ展開攻撃は、XMLパーサーを含むサービス拒否攻撃です。 基本的な悪用は、各レイヤーが次のレイヤーのいくつかのエンティティを参照する、ネストされたエンティティの複数のレイヤーの使用です。 次に、深くネストされたエンティティ参照を含むSOAPドキュメントのサンプルを示します。

<?xml version="1.0" encoding ="UTF-8"?>
<!DOCTYPE bbb[
    <!ENTITY x100 "bbb">
    <!ENTITY  x99 "&x100;&x100;">
    <!ENTITY  x98 "&x99;&x99;">
    ...
    <!ENTITY   x2 "&x3;&x3;">
    <!ENTITY   x1 "&x2;&x2;">
]>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
    <SOAP-ENV:Body>
        <ns1:aaa xmlns:ns1="urn:aaa" SOAP-ENV:encodingStyle="...">
            <foobar xsi:type="xsd:string">&x1;</foobar>
        </ns1:aaa>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

XMLパーサーは、このようなドキュメントを検出すると、参照を展開してエンティティ宣言を解決しようとします。 参照はネストされているため、展開は、それぞれが参照するエンティティ数によって指数関数的になります。 このようなプロセスによって、XMLパーサーが100%のCPU時間と大量のメモリーを消費し、最終的にシステムのメモリーが不足する可能性があります。

セキュアなXML処理のためのJAXPの構成

JAXPは、XMLドキュメントの解析、直列化、変換、問合せおよびトラバースを行うためのAPIのセットで構成されます。 JAXP APIを参照してください。

JAXPは、ファクトリおよびプロセッサを通じてセキュリティのレイヤーを追加します。 ファクトリを通じてJAXPからAPIにアクセスします。これにより、セキュリティ要件に基づいて設定したJAXPプロパティに従ってAPIが構成されます。 ファクトリは、それぞれのプロセッサを使用して構成し、インスタンス化します。 ファクトリおよびプロセッサを参照してください。

JAXPプロセッサは、JAXPプロパティを使用して構成します。 JAXPプロパティは、JAXPファクトリを通じて、システム・プロパティとして、またはJAXP構成ファイルで設定できます。 JAXPプロパティを使用した構成を参照してください。

セキュリティ関連のプロパティでは、セキュアなXML処理のためにJAXPを構成する際に設定できるプロパティについて説明します。

「コンポジット・プロセッサ」では、バリデータやトランスフォーマなどのコンポジット・プロセッサでFEATURE_SECURE_PROCESSING (FSP)を有効にすると、コンポジット・プロセッサが使用する内部パーサーでもFSPが有効になる方法について説明します。

また、JAXPではカスタム・リゾルバを登録できます。このリゾルバは、外部リソースへの参照をインターセプトし、ローカル・リゾルバで解決します。 これにより、外部リソースの読取りとアクセスの必要がなくなるため、潜在的なリスクのソースを除去するのに役立ちます。 Java XMLリゾルバの使用を参照してください。

JAXP API

JAXPは、XML処理に不可欠なXMLの技術および標準を構築したAPIのセットで構成されます。 これには、次のAPIが含まれています:

ファクトリおよびプロセッサ

ファクトリは、各JAXP APIのエントリ・ポイントです。 これらは、アプリケーションがプロセッサを作成する前にJAXPプロパティをプログラムで設定できるようにするメソッドを提供します。 ファクトリはJAXP検索メカニズムもサポートしており、JDK実装ではなくサードパーティ実装を使用してアプリケーションをデプロイできます。

プロセッサは、それぞれの領域で処理を制御および実行するパーサー(またはリーダー)、シリアライザ(またはライター)、バリデータおよびトランスフォーマを集約したものです。 ファクトリは、対応するファクトリを構成し、インスタンス化します。 たとえば、DocumentBuilderおよびSAXParserプロセッサをそれぞれDocumentBuilderFactoryおよびSAXParserFactoryファクトリを使用して構成し、インスタンス化します。

JAXPプロパティを使用した構成

JAXPプロセッサは、JAXPプロパティを使用して構成します。 次に、JAXPプロパティを設定する方法を、優先順位の高いものから低いものの順に示します。 たとえば、ファクトリを通じてJAXPプロパティの値を設定すると、別の方法で設定された他の値がオーバーライドされます。

すべてのJAXPプロパティをこれらの方法で設定できるわけではありません。

JAXPファクトリを使用したJAXPプロパティの設定

アプリケーションのコードを変更したり、新しいアプリケーションを作成する場合は、JAXPファクトリまたはパーサーを通じてJAXPプロパティを設定することをお薦めします。 これらのプロパティは、次のインタフェースを使用して設定します。

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute(name, value);
 
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty(name, value);

SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
schemaFactory.setProperty(name, value);
 
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(name, value);
 
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(name, value);

XPathFactory xf = XPathFactory.newInstance();
xf.setProperty(name, value);

次に、処理制限の設定例を示します。

dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", "2000");

dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/maxGeneralEntitySizeLimit", "100000");

dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/maxParameterEntitySizeLimit", "10000"); 

dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/maxElementDepth", "100");

factory.setAttribute("jdk.xml.xpathTotalOpLimit", "1000"); 
xf.setProperty("jdk.xml.xpathExprGrpLimit", "20");

次に、DOMパーサーを外部DTDのローカル接続のみに制限する例を示します。

dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "file, jar:file");

アプリケーション内のパーサー・モジュールが信頼できないソースを処理する場合、さらにアクセスを制限できます。 次のコードは、jaxp.propertiesファイルおよびシステム・プロパティによって指定されたコードをオーバーライドし、XMLプロセッサがローカル・ファイルのみを読み取れるようにします。

DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();   
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "file");

// ...   

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);   
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "file");   
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");

「JAXPプロパティの設定のスコープおよび順序」で説明したように、JAXPファクトリを通じて指定されたJAXPプロパティは、最も狭いスコープを持ち、ファクトリによって作成されたプロセッサにのみ影響するため、デフォルト設定、システム・プロパティおよびjaxp.propertiesファイル内の設定をオーバーライドします。 JAXPファクトリを使用してJAXPプロパティを設定すると、使用しているJDKリリースや、JAXPプロパティを他の手段で設定するかどうかに関係なく、アプリケーションの動作が同じようになります。

システム・プロパティとしてのJAXPプロパティの設定

システム・プロパティは、アプリケーションのコードを変更できない場合に便利です。

JDKの起動全体に対してJAXPプロパティを設定するには、コマンド行で対応するシステム・プロパティを設定します。

JAXPプロパティをアプリケーションの一部のみに設定するには、対応するシステム・プロパティをその部分の前に設定し、後でクリアします。 たとえば、アプリケーションで外部DTDおよびスキーマへのアクセスが必要な場合、これらの行をアプリケーションの初期化コード・ブロックに追加します。

System.setProperty("javax.xml.accessExternalDTD", "file, http");
System.setProperty("javax.xml.accessExternalSchema", "file, http");

その後、アプリケーションでXMLドキュメントの処理を実行した後、またはアプリケーションを終了する前に、次のようにプロパティをクリアします。

System.clearProperty("javax.xml.accessExternalDTD");   
System.clearProperty("javax.xml.accessExternalSchema");

Javaチュートリアル処理制限サンプルにある次のコードは、処理制限maxGeneralEntitySizeLimitに対してこれを行う方法を示す別の例です:

public static final String SP_GENERAL_ENTITY_SIZE_LIMIT =
    "jdk.xml.maxGeneralEntitySizeLimit";

// Set limits using System property;
// this setting will affect all processing after it's set
System.setProperty(SP_GENERAL_ENTITY_SIZE_LIMIT, "2000");

// Perform some processing here

// After it is done, clear the property
System.clearProperty(SP_GENERAL_ENTITY_SIZE_LIMIT);

処理制限の値は整数であることに注意してください。 処理制限の値が解析可能な整数でない場合、NumberFormatExceptionがスローされます。java.lang.Integer.parseInt(String)メソッドを参照してください。

次の例では、アプリケーションの一部の外部スキーマを解決できます。

// Allow resolution of external schemas
// This setting will affect all processing after it's set
System.setProperty("javax.xml.accessExternalSchema", "file, http");

// Perform some processing here

// After it's done, clear the property
System.clearProperty("javax.xml.accessExternalSchema");

JAXP構成ファイルでのJAXPプロパティの設定

すべてのJDK呼出しに影響するJAXPプロパティを指定する場合は、<java-home>/lib/jaxp.propertiesという名前の構成ファイルを作成し、その中にJAXPプロパティの名前と値(各行に1つの名前と値のペア)を指定します。 たとえば、次のjaxp.propertiesファイルは、maxGeneralEntitySizeLimit処理制限プロパティを2000に設定し、stylesheet処理命令、document関数、およびimport要素とinclude要素によって設定された外部参照のファイルおよびHTTPプロトコルへのアクセスを制限します。

jdk.xml.maxGeneralEntitySizeLimit=2000
javax.xml.accessExternalStylesheet=file, http

XMLプロセッサによる外部接続を許可しない場合は、すべてのアクセス外部制限をfileのみに設定できます:

javax.xml.accessExternalDTD=file
javax.xml.accessExternalSchema=file
javax.xml.accessExternalStylesheet=file

アプリケーションがXMLプロセッサを通じて外部ファイルを誤って読み取ることを防ぐには、jaxp.propertiesファイルで次のように外部アクセス制限を設定します。

javax.xml.accessExternalDTD=""   
javax.xml.accessExternalSchema=""   
javax.xml.accessExternalStylesheet=""

ノート:

JAXPプロパティの設定のスコープおよび順序

JAXPプロパティは、APIメソッド、システム・プロパティ、JAXP構成ファイルなど、複数の方法で設定できます。 明示的に設定しない場合、FEATURE_SECURE_PROCESSING (FSP)を有効にすると、デフォルト値またはより限定的な値で初期化されます。 プロパティの優先順位は、高い順に次のとおりです:

jdk.xml.entityExpansionLimitプロパティを例として使用すると、次のルールがどのように適用されるかを示します。

セキュリティ関連のプロパティ

次の項では、セキュアなXML処理のためにJAXPを構成する際に設定できるプロパティについて説明します 2種類のJAXPのセキュリティ関連プロパティがあります:

API定義プロパティ

FEATURE_SECURE_PROCESSINGセキュリティ・ディレクティブ

FEATURE_SECURE_PROCESSING (FSP)セキュリティ・ディレクティブは、XMLドキュメントを処理するためのセキュリティ制限を有効にする意図を通知します。 JAXP APIによって定義され、JAXP実装からセキュア・モードをリクエストするための標準メカニズムを提供します。 JAXPファクトリを介してtrueに設定されている場合、パーサーなどのJAXPプロセッサに、プロセッサのセキュリティ・モデルに基づいて様々な制限を適用するように指示します。たとえば:

factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

また、FEATURE_SECURE_PROCESSINGがtrueに設定されている場合、JDKは外部アクセス・プロパティ(EAP)およびJDK固有のプロパティを使用してセキュリティ制限をアクティブ化します。

デフォルトでは、JDKはSAX、DOMおよび検証に対してFSPをオンにします。

セキュリティ・マネージャが存在する場合、JAXPセキュリティ処理は自動的にオンになります。

JAXPプロパティの優先順位およびFEATURE_SECURE_PROCESSING

DOM、SAX、スキーマ検証、XSLTおよびXPathなどのXMLプロセッサには、FSPが必要です。

FSPをオンにすると、デフォルトの処理制限(「処理制限用のJAXPプロパティ」を参照)が適用されます。 FSPをオフにしても制限は変更されません。

FSPがAPIを介して「明示的に」オンになっている場合(たとえば、factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true))、外部アクセス・プロパティ(EAP)は空の文字列に設定されます。これは、どのプロトコルにも権限が付与されていないことを意味します。 DOM、SAXおよびスキーマ検証ではFSPがデフォルトでオンになっていますが、明示的にオンになっているかのように扱われません。したがって、EAPのデフォルト値はallです。つまり、権限がすべてのプロトコルに付与されます。

Javaセキュリティ・マネージャが存在する場合、FSPはオンになり、オフにはできません。

外部アクセス・プロパティ

外部アクセスプロパティ(EAP)は、対応するシステムプロパティとともに、外部接続を規制できます。

EAPを使用すると、許可できるまたは許可できない外部接続のタイプを指定できます。 プロパティ値は、プロトコルのリストです。 JAXPプロセッサは、プロトコルをリスト内のプロトコルと照合することによって、特定の外部接続が許可されているかどうかをチェックします。 プロセッサは、リスト上にある場合は接続を確立しようとし、そうでない場合は拒否しようとします。 EAPをカスタム・リゾルバとともに使用して(Java XMLリゾルバの使用を参照)、ローカル・リソースで外部接続を拒否および解決することで外部接続のリスクを軽減します。

ノート: APIを介してFSPを明示的にオンにすると(たとえば、factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true))、すべての外部接続が無効になります。

EAPは、javax.xml.XMLConstantsで次のように定義されます。

ACCESS_EXTERNAL_DTD
属性 説明
名前 http://javax.xml.XMLConstants/property/accessExternalDTD
定義 外部DTDおよび外部エンティティ参照へのアクセスを指定されたプロトコルに制限します。
外部アクセス・プロパティの値を参照してください
デフォルト値 all。すべてのプロトコルへの接続が許可されます
システム・プロパティ javax.xml.accessExternalDTD
ACCESS_EXTERNAL_SCHEMA
属性 説明
名前 http://javax.xml.XMLConstants/property/accessExternalSchema
定義 schemaLocation属性、import要素およびinclude要素によって設定された外部参照用に指定されたプロトコルへのアクセスを制限します。
外部アクセス・プロパティの値を参照してください
デフォルト値 all。すべてのプロトコルへの接続が許可されます。
システム・プロパティ javax.xml.accessExternalSchema
ACCESS_EXTERNAL_STYLESHEET
属性 説明
名前 http://javax.xml.XMLConstants/property/accessExternalStylesheet
定義 stylesheet処理命令、document関数、およびimport要素とinclude要素によって設定された外部参照用に指定されたプロトコルへのアクセスを制限します。
外部アクセス・プロパティの値を参照してください
デフォルト値 all。すべてのプロトコルへの接続が許可されます。
システム・プロパティ javax.xml.accessExternalStylesheet
外部アクセス・プロパティの値

すべてのEAPの値は同じフォーマットです:

外部アクセス制限をいつ使用するか

XMLプロセッサは、デフォルトで、XMLソースで参照される外部リソースへの接続および読取りを試行します。 これにより、アプリケーションおよびシステムは、外部接続によって発生するリスクに晒される可能性があることに注意してください。 そのため、アプリケーションではEAPを使用した外部接続の制限を検討することをお薦めします。

信頼できるXMLドキュメントのみを処理する内部アプリケーションおよびシステムでは、これらの制限が不要な場合があります。 外部接続を規制するためにJavaセキュリティ・マネージャに依存するアプリケーションおよびシステムでも、それらが不要な場合があります。 ただし、EAPは XMLプロセッサに固有であり、プロセスの最上位レイヤーに固有であるため、プロセッサは接続を行う前にこれらのEAPをチェックします。 したがって、外部接続リスクに対する、より直接的な追加の保護として機能します。

EAPをカスタム・リゾルバおよびカタログとともに使用して(Java XMLリゾルバの使用を参照)、外部接続を効果的に管理し、リスクを低減できます。

信頼できるソースを含む信頼できる環境であっても、EAPとリゾルバの両方を使用して外部ソースへの依存を最小限にすることをお薦めします。

JAXPプロパティの優先順位および外部アクセス・プロパティ

EAPは、次のような状況で制限しようとする関連コンストラクトには影響しません。

JDK固有のプロパティ

処理制限用のJAXPプロパティ

XML処理は、メモリー集中型の操作である場合があります。 信頼できないソースからのXML、XSDおよびXSLを受け入れるアプリケーションでは特に、処理制限用のJAXPプロパティを使用して、過剰なメモリー消費を回避するステップをとる必要があります。

アプリケーションの要件およびオペレーティング環境を評価して、システム構成の許容可能な処理制限を判断し、それに応じてこれらの制限を設定します。 たとえば、サイズ関連の制限を使用して、不適切なXMLソースによる大量のメモリー消費を防止します。 EntityExpansionLimitを使用して、アプリケーションが許容可能なレベルでメモリー消費を制御できるようにします。

JDK XMLパーサーは、デフォルトで処理制限を監視します。 DOMおよびSAXパーサーでは、セキュア処理機能(FSP)がデフォルトでオンになっているため、制限がオンになります。 また、StAXパーサーは、FSPをサポートしていなくても、デフォルトで処理制限を遵守します。

JDK XMLプロセッサを使用すると、処理制限を3つの方法で個別に調整できます。

「JAXPプロパティを使用した構成」および「JAXPプロパティの設定のスコープと順序」を参照してください。

次の表に、JDKでサポートされる処理制限用のJAXPプロパティを示します。

プロパティ名 システム・プロパティ 説明 デフォルト値
http://www.oracle.com/xml/jaxp/properties/elementAttributeLimit jdk.xml.elementAttributeLimit 1つの要素で使用できる属性の数を制限します。 10000
http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit jdk.xml.entityExpansionLimit エンティティの展開数を制限します。 64000
http://www.oracle.com/xml/jaxp/properties/entityReplacementLimit jdk.xml.entityReplacementLimit すべてのエンティティ参照のノードの合計数を制限します。 3000000
http://www.oracle.com/xml/jaxp/properties/maxElementDepth jdk.xml.maxElementDepth 要素の最大の深さを制限します。 0
http://www.oracle.com/xml/jaxp/properties/maxGeneralEntitySizeLimit jdk.xml.maxGeneralEntitySizeLimit すべての一般エンティティの最大サイズを制限します。 0
http://www.oracle.com/xml/jaxp/properties/maxOccurLimit jdk.xml.maxOccurLimit "バインドなし"以外の値を持つmaxOccurs属性を含むW3C XMLスキーマの文法を作成するときに作成できるコンテンツ・モデル・ノードの数を制限します。 5000
http://www.oracle.com/xml/jaxp/properties/maxParameterEntitySizeLimit jdk.xml.maxParameterEntitySizeLimit 複数のパラメータ・エンティティのネストの結果を含む、パラメータ・エンティティの最大サイズを制限します。 1000000
http://www.oracle.com/xml/jaxp/properties/maxXMLNameLimit jdk.xml.maxXMLNameLimit 要素名、属性名、名前空間の接頭辞やURIなど、XML名の最大サイズを制限します。 1000
http://www.oracle.com/xml/jaxp/properties/totalEntitySizeLimit jdk.xml.totalEntitySizeLimit 一般エンティティとパラメータ・エンティティを含むすべてのエンティティの合計サイズを制限します。 サイズはすべてのエンティティの集約として計算されます。 5x10^7
jdk.xml.xpathExprGrpLimit jdk.xml.xpathExprGrpLimit XPath式に含めることができるグループの数を制限します。 10
jdk.xml.xpathExprOpLimit jdk.xml.xpathExprOpLimit XPath式に含めることができる演算子の数を制限します。 100
jdk.xml.xpathTotalOpLimit jdk.xml.xpathTotalOpLimit XSLスタイルシートのXPath演算子の総数を制限します。 100000
レガシー・システム・プロパティ

これらのプロパティはJDK 5.0および6で導入されたもので、下位互換性のために引き続きサポートされます。

システム・プロパティ 導入されたバージョン 新規システム・プロパティ
entityExpansionLimit 1.5 jdk.xml.entityExpansionLimit
elementAttributeLimit 1.5 jdk.xml.elementAttributeLimit
maxOccurLimit 1.6 jdk.xml.maxOccur
FEATURE_SECURE_PROCESSINGのデフォルトの制限

次の表に、無効化されているXML関連のファクトリ・クラスと、FEATURE_SECURE_PROCESSING (FSP)が有効になっている場合に設定される処理制限を示します。

XML関連ファクトリ・クラス 有効? 処理制限
DocumentBuilderFactory true jdk.xml.entityExpansionLimit = 64000
jdk.xml.elementAttributeLimit = 1000
jdk.xml.maxOccurLimit = 5000
SAXParserFactory true jdk.xml.entityExpansionLimit = 64000
jdk.xml.elementAttributeLimit = 10000
jdk.xml.maxOccurLimit = 5000
SchemaFactory true jdk.xml.maxOccurLimit = 5000
TransformerFactory false 拡張関数が無効です
XPathFactory false 拡張関数が無効です
エンティティ展開の制限

システム・プロパティjdk.xml.entityExpansionLimitまたはパーサー・プロパティhttp://apache.org/xml/properties/entity-expansion-limitを設定して、エンティティ拡張の数を制限します。 どちらのプロパティもjava.lang.Integer値を受け入れます。 エンティティ展開の上限に達すると、パーサーは致命的なエラーをスローします。 デフォルトでは、entityExpansionLimitは64,000に設定されています。

次のコマンド行の例では、エンティティ展開制限が10,000に設定されます。

java -DentityExpansionLimit=10000 MyApp

次のコード例では、エンティティ展開制限が10,000に設定されます。

System.setProperty("jdk.xml.entityExpansionLimit","10000");

次のコード例では、パーサー・プロパティhttp://apache.org/xml/properties/entity-expansion-limitを10,000に設定します。

DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
dfactory.setAttribute(
        "http://apache.org/xml/properties/entity-expansion-limit",
        new Integer("10000"));
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
要素属性数の制限

システム・プロパティjdk.xml.elementAttributeLimitを設定するか、パーサー・プロパティhttp://apache.org/xml/properties/elementAttributeLimitを設定して、要素内の属性数を制限します。 どちらのプロパティもInteger値を受け入れます。 デフォルトでは、jdk.xml.elementAttributeLimitは10,000に設定されています。 パーサー・プロパティhttp://apache.org/xml/properties/elementAttributeLimitを設定すると、システム・プロパティがオーバーライドされます。 要素内の属性数が制限を超えると、パーサーは致命的エラーをスローします。

次のコマンド行の例では、要素属性制限が20に設定されます。

java -Djdk.xml.elementAttributeLimit=20 MyApp

次のコード例では、要素属性制限が20に設定されます。

System.setProperty("jdk.xml.elementAttributeLimit","20");

次のコード例では、パーサー・プロパティhttp://apache.org/xml/properties/entity-expansion-limitを20に設定します。

DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
dfactory.setAttribute(
    "http://apache.org/xml/properties/elementAttributeLimit",
    new Integer(20));
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
maxOccursを含むコンストラクトにより作成されるノード数の制限

xsd:sequenceなどの構文では、検証パーサーは、maxOccursオカレンス・インジケータの値に比例した領域(メモリー)を使用できます。 これによってVMのメモリーが不足したり、非常に長時間実行される場合があります。 この動作を悪用する潜在的攻撃を防ぐには、次のようにファクトリのセキュアな処理を有効にします。

factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);

xsd:elementおよびxsd:anyの場合、検証パーサーは、maxOccursオカレンス・インジケータの値とは関係なく、一定量の領域を使用します。

jdk.xml.maxOccurLimitのデフォルト値は5000です。 このシステム・プロパティは、W3C XMLスキーマの文法を構築するときに作成されるコンテンツ・モデル・ノードの数を制限します。このスキーマには、maxOccursオカレンス・インジケータと"unbounded"以外の値が含まれます。

処理制限をいつ使用するか

適用する処理制限および使用する値を決定する場合は、システム・レベルで、アプリケーションで使用可能なメモリー量、および信頼できないソースからのXML、XSDまたはXSLソースが受け入れられて処理されるかどうかを検討します。 アプリケーション・レベルでは、DTDなどの特定のコンストラクトを使用するかどうかを検討します。

メモリー設定および制限

XML処理では、メモリーが大量に消費される可能性があります。 消費できるメモリー量は、特定の環境におけるアプリケーションの要件によって異なります。 不適切なXMLデータの処理によってメモリーが過剰に消費されるのを防ぐ必要があります。

通常、デフォルトの制限は、メモリー使用量がPCなどの小規模なハードウェア・システムに対して許容される量であるほとんどのアプリケーションで正当なXML入力が可能になるように設定されます。 不正な入力が大量のメモリーを消費する前にそれを捕捉できるように、制限を可能な最小値に設定することをお薦めします。

制限は相関していますが、完全に冗長ではありません。 すべての制限に適切な値を設定する必要があります。通常、制限はデフォルトより大幅に小さい値に設定する必要があります。

たとえば、ENTITY_EXPANSION_LIMITおよびGENERAL_ENTITY_SIZE_LIMITは、過剰なエンティティ参照を防ぐために設定できます。 ただし、拡張サイズとエンティティ・サイズの正確な組合せが不明な場合、TOTAL_ENTITY_SIZE_LIMITは全体的な制御として機能します。 同様に、TOTAL_ENTITY_SIZE_LIMITは置換テキストの合計サイズを制御します。テキストがXMLの非常に大きなチャンクである場合、ENTITY_REPLACEMENT_LIMITはテキストに表示できるノードの合計数に制限を設定し、システムのオーバーロードを防止します。

getEntityCountInfoプロパティを使用した制限の見積り

制限に対して設定する必要がある値を分析するために、http://www.oracle.com/xml/jaxp/properties/getEntityCountInfoという特別なプロパティを使用できます。 Javaチュートリアル 処理制限サンプルに関する項の次のコード・スニペットは、プロパティの使用例を示しています。

public static final String ORACLE_JAXP_PROPERTY_PREFIX =
    "http://www.oracle.com/xml/jaxp/properties/";
// ...
public static final String JDK_ENTITY_COUNT_INFO = 
    ORACLE_JAXP_PROPERTY_PREFIX + "getEntityCountInfo";
// ...
parser.setProperty(JDK_ENTITY_COUNT_INFO, "yes");

W3C MathML 3.0のDTDで処理制限サンプルを実行すると、次の表が出力されます。

プロパティ 制限 合計サイズ Size エンティティ名
ENTITY_EXPANSION_LIMIT 64000 1417 0 null
MAX_OCCUR_NODE_LIMIT 5000 0 0 null
ELEMENT_ATTRIBUTE_LIMIT 10000 0 0 null
TOTAL_ENTITY_SIZE_LIMIT 50000000 55425 0 null
GENERAL_ENTITY_SIZE_LIMIT 0 0 0 null
PARAMETER_ENTITY_SIZE_LIMIT 1000000 0 7303 %MultiScriptExpression
MAX_ELEMENT_DEPTH_LIMIT 0 2 0 null
MAX_NAME_LIMIT 1000 13 13 null
ENTITY_REPLACEMENT_LIMIT 3000000 0 0 null

この例では、エンティティ参照の合計数(エンティティ展開)は1417で、デフォルトの上限は64000です。 すべてのエンティティの合計サイズは55425で、デフォルトの上限は50000000です。 最大のパラメータ・エンティティは、すべての参照が解決された後、長さが7303の%MultiScriptExpressionです。デフォルトの制限は1000000です。

これがアプリケーションで処理されることが想定される最大ファイルである場合、制限は小さい数値に設定することをお薦めします。 たとえば、ENTITY_EXPANSION_LIMITの場合は2000、TOTAL_ENTITY_SIZE_LIMITの場合は100000、PARAMETER_ENTITY_SIZE_LIMITの場合は10000です。

拡張関数

TransformerおよびXPathではFSPがデフォルトでオフになっているため、拡張関数を使用できます。 信頼できないソースからのドキュメントを処理するアプリケーションでは、拡張関数機能をオフにすることをお薦めします。 これを行うには、次の2つの方法があります。

Javaセキュリティ・マネージャのインストールの結果として拡張関数が無効になっている場合、アプリケーションも、プロパティenableExtensionFunctionsをtrueに設定して拡張関数機能の再有効化を選択できます。 次の表で、このプロパティを定義します。

enableExtensionFunctions
属性 説明
名前 http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions
定義 XSLTおよびXPath拡張関数が許可されるかどうかを決定します。
ブール Trueは拡張関数が許可されることを示します。それ以外の場合はFalseです。
デフォルト値 true
システム・プロパティ jdk.xml.enableExtensionFunctions
導入されたバージョン 7u60
サードパーティ製パーサー

JDKでは、クラスパスにサードパーティ製のパーサーが存在する場合でも、常にシステムデフォルト・パーサーが使用されます。 JDKシステム・デフォルト・パーサーをオーバーライドするには、jdk.xml.overrideDefaultParserプロパティをtrueに設定します。

overrideDefaultParser
属性 説明
名前 jdk.xml.overrideDefaultParser
定義 サードパーティのパーサー実装を使用して、JDKのTransformerValidatorおよびXPath実装のシステム・デフォルト・パーサーをオーバーライドできます。 このプロパティは、JAXPファクトリ、システム・プロパティまたはjaxp.propertiesファイルを通じて設定できます。
ブール trueに設定すると、XML変換、XML検証またはXPath操作中にサードパーティ製パーサーの実装でシステムデフォルト実装をオーバーライドできます。 falseに設定すると、サードパーティ製パーサー実装の使用が無効になります。 値がStringとして指定されている場合、戻り値はBoolean.parseBooleanの値になります。
デフォルト値 false
システム・プロパティ jdk.xml.overrideDefaultParser
導入されたバージョン 6u181、7u171、8u161、9.0.4
サード・パーティ・パーサーの使用例

次のコード・スニペットは、setFeatureメソッドでjdk.xml.overrideDefaultParserプロパティを設定することで、クラスパスで見つかった場合、サード・パーティ・パーサーを使用するようにファクトリに指示します:

static final String JDK_OVERRIDE_PARSER = "jdk.xml.overrideDefaultParser";
// ...
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setFeature(JDK_OVERRIDE_PARSER, true);
// ...
XPathFactory xf = XPathFactory.newInstance();
xf.setFeature(JDK_OVERRIDE_PARSER, true);
// ...
SchemaFactory schemaFactory =
    SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setFeature(JDK_OVERRIDE_PARSER, true);
// ...
Schema schema = schemaFactory.newSchema(new File("mySchema.xsd"));
Validator validator = schema.newValidator();
validator.setFeature(JDK_OVERRIDE_PARSER, true);

次のコード・スニペットは、jdk.xml.overrideDefaultParserをシステム・プロパティとして設定します:

System.setProperty("jdk.xml.overrideDefaultParser", "true"));

jaxp.propertiesファイルに次の行を追加すると、サードパーティ製パーサーを有効にできます。

jdk.xml.overrideDefaultParser=true
DTD処理の無効化

アプリケーションでDTDが必要ない場合は、DTD処理を無効化して、サービス拒否、XML外部エンティティ(XXE)、サーバー側リクエストの偽造(SSRF)など、多くの一般的なDTD関連の攻撃に対抗することを検討してください。

SAXおよびDOMパーサーに対するDTD処理の無効化

SAXパーサーおよびDOMパーサーのDTD処理を無効にするには、ファクトリを介して機能http://apache.org/xml/features/disallow-doctype-declをtrueに設定します。 次のコード・スニペットはSAXパーサーのDTDを無効化します。 受け取ったXMLドキュメントにDOCTYPE宣言が含まれていると、致命的なエラーがスローされます。

final static String DISALLOW_DTD =
    "http://apache.org/xml/features/disallow-doctype-decl";
// ...
SAXParserFactory spf = SAXParserFactory.newInstance();      
spf.setFeature(DISALLOW_DTD, true);
StAXパーサーのDTD処理の無効化

StAXパーサーのDTD処理を無効にするには、XMLInputFactory.setPropertyメソッドを使用してプロパティSupportDTDを設定します:

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);

コンポジット・プロセッサ

バリデータ、トランスフォーマ、XPathプロセッサなどのコンポジット・プロセッサは、内部で作成されたパーサーを使用して、ソースがDOMSourceまたはDocumentでない場合にソースを読み取ります。 SchemeFactoryTransformerFactoryXPathFactoryなどのファクトリを介してFEATURE_SECURE_PROCESSING (FSP)がオンになると、内部パーサー・インスタンスでもオンになります。 これは、内部パーサーがSAXParserFactoryまたはDocumentBuilderFactoryで作成されたパーサーと同じように動作することを意味します。

たとえば、次のコードでは、FSPを使用してXPathFactoryのインスタンスを作成します。

XPathFactory xf = XPathFactory.newInstance(); 
xf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

このプロセスにより、RAW XMLソースの評価に使用される場合など、XPathプロセッサで必要な内部パーサーに対してもFSPがオンになります。 結果として、パーサーによって定義された制限が適用されます。 たとえば、カタログまたはリゾルバによって解決されない外部参照がXMLソースに含まれている場合、FSPが明示的にオンになっているため、「外部アクセス・プロパティ」の説明に従って拒否されます。

Java XMLリゾルバの使用

JDK XMLプロセッサでカスタム・リゾルバおよびカタログを登録して、外部リソースへの参照を捕捉し、ローカル・リソースで解決できます。 この機能によって、外部リソースの読み取りとアクセスの必要がなくなるため、潜在的なリスクのソースを除去するのに役立ちます。

Java XML APIでは、JDK XMLプロセッサに登録して外部リソースを解決できる様々なリゾルバがサポートされます。 これらのリゾルバには、SAXパーサーおよびDOMパーサーのエンティティ・リゾルバ、StAXパーサーのXMLリゾルバ、検証用のLSResourceResolverおよび変換用のURIResolverが含まれます。

SAXおよびDOMのエンティティ・リゾルバ

SAXは、DOMがサポートするインタフェースorg.xml.sax.EntityResolverも定義します。 これにより、アプリケーションでエンティティ解決プロセスをトレース実行し、独自のタームでエンティティ解決を実行できます。 インタフェースの定義は次のとおりです。

package org.xml.sax;

public interface EntityResolver {
    public InputSource resolveEntity(String publicID, String systemID)
        throws SAXException;
}

その後、SAXドライバでインタフェースの実装を登録できます。

EntityResolver resolver = ...;
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setEntityResolver(resolver);

または、DOMビルダーで登録できます。

DocumentBuilder builder =
    DocumentBuilderFactory.newInstance().newDocumentBuilder();       
docBuilder.setEntityResolver(resolver);

StAXの場合はXMLResolver

StAXは、javax.xml.stream.XMLResolverインタフェースを定義します:

package javax.xml.stream;

public interface XMLResolver {
    public Object resolveEntity(
        String publicID, String systemID,
        String baseURI, String namespace)
        throws XMLStreamException;
}

これをStAXファクトリに登録できます。

XMLResolver resolver = ...;
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.RESOLVER, resolver);

javax.xml.transformの場合はURIResolver

javax.xml.transform APIは、URIResolverインタフェースを介して外部リソースのカスタム解決をサポートします:

package javax.xml.transform;

public interface URIResolver {
    public Source resolve(String href, String base)
        throws TransformerException;
}

URIResolverの実装は、次のようにTransformerに登録できます:

URIResolver resolver = ...;
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer(
    new StreamSource(new StringReader("xsl source")));
t.setURIResolver(resolver);

javax.xml.validationの場合はLSResourceResolver

javax.xml.validation APIは、LSResourceResolverインタフェースを介して、Document Object Model Level 3 Load and Save (DOM LS) DOMをサポートしています:

package org.w3c.dom.ls;

public interface LSResourceResolver {
    public LSInput resolveResource(
        String type, String namespaceURI, String publicId,
        String systemId, String baseURI);
}

LSResourceResolverの実装は、次のようにSchemaFactoryに登録できます:

SchemaFactory schemaFactory =
    SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
LSResourceResolver resolver = ...;
schemaFactory.setResourceResolver(resolver);

セキュリティ・マネージャとの関係

JAXPプロパティは、SecurityManagerが存在するかどうかに関係なく、接続が試行される前に最初にチェックされます。 つまり、SecurityManagerによって権限が付与されている場合でも、接続がブロックされる可能性があります。 たとえば、JAXPプロパティがHTTPプロトコルを禁止するように設定されている場合、アプリケーションがSocketPermissionを持っている場合でも、接続試行は事実上ブロックされます。

接続を制限するために、SecurityManagerを下位レベルとみなすことができます。 JAXPプロパティが評価された後、アクセス権がチェックされます。 たとえば、アプリケーションにSocketPermissionがない場合、JAXPプロパティがHTTP接続を許可するように設定されていても、SecurityExceptionがスローされます。

SecurityManagerが存在する場合、保護処理の機能(FSP)はtrueに設定されます。 この動作によって外部アクセス制限がオンになることはありません。

JAXPプロパティからのエラーの処理

JAXPプロパティの設定時にアプリケーションがorg.xml.sax.SAXNotRecognizedExceptionを捕捉して、それらをサポートしていない古いリリースで正常に動作するようにすることをお薦めします。

たとえば、「Javaチュートリアル」「処理制限サンプル」にある次のメソッドisNewPropertySupportedは、JDK_GENERAL_ENTITY_SIZE_LIMITプロパティをサポートするJDKのバージョンでサンプルが実行されているかどうかを検出します:

public boolean isNewPropertySupported() {
    try {
        SAXParser parser = getSAXParser(false, false, false);
        parser.setProperty(JDK_GENERAL_ENTITY_SIZE_LIMIT, "10000");
    } catch (ParserConfigurationException ex) {
        fail(ex.getMessage());
    } catch (SAXException ex) {
        String err = ex.getMessage();
        if (err.indexOf("Property '" + JDK_GENERAL_ENTITY_SIZE_LIMIT +
                                       "' is not recognized.") > -1) {
            // expected before this patch
            debugPrint("New limit properties not supported. Samples not run.");
            return false;
        }
    }
    return true;
}

入力ファイルに、over-the-limit例外を引き起こすコンストラクトが含まれている場合、アプリケーションはエラー・コードをチェックして失敗の性質を判断できます。 処理制限について、次のエラー・コードが定義されています。

エラー・コードの形式は、次のとおりです。

"JAXP" + components (two digits) + error category (two digits) + sequence number

したがって、コードJAXP00010001は、JAXPベース・パーサーのセキュリティ制限EntityExpansionLimitを表します。

外部アクセス制限によって設定された制限が原因で外部リソースへのアクセスが拒否された場合、次の形式でエラーとともに例外がスローされます。

[type of construct]: Failed to read [type of construct]
    "[name of the external resource]", because "[type of restriction]"
    access is not allowed due to restriction set by the
    [property name] property.

たとえば、次のように仮定します。

エラー・メッセージは次のようになります。

External DTD: Failed to read external DTD
    "http://www.example.com/dtd/properties.dtd", because "http"
    access is not allowed due to restriction set by the
    accessExternalDTD property.

XMLおよびJAXPプロパティ用のストリーミングAPI

Streaming API for XML (StAX)、JSR 173では、FSPはサポートされず、EAPもサポートされません。 ただし、JDKのStAX実装では処理制限がサポートされ、JAXPのコンテキストのStAXではEAPがサポートされます。

StAXおよび処理制限

JDKのStAX実装では、処理制限およびそれらに対応するシステム・プロパティがサポートされます。 ただし、FSPはサポートされていないため、FSPをオンまたはオフにすることによってStAXの処理制限をオンまたはオフにすることはできません。 処理制限は引き続き「処理制限用のJAXPプロパティ」に説明されているように動作します。

StAXおよび外部アクセス・プロパティ

JDKのStAX実装では、外部アクセス・プロパティ(EAP)に関連するJAXPプロパティがサポートされます。 これらの設定はSAXまたはDOMに似ていますが、XMLInputFactoryクラスを介して次のように設定します:

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(
    "http://javax.xml.XMLConstants/property/accessExternalDTD",
    "file");

互換性を保つために、StAXのプロパティおよび機能は、処理制限および外部アクセス制限のプロパティよりも優先されます。 たとえば、SupportDTDプロパティをfalseに設定すると、入力ファイルにDTDが含まれているときに例外がスローされてから解析されます。 したがって、DTDに対する処理制限および外部アクセス制限は、SupportDTDプロパティをfalseに設定することで、DTDを無効にしたアプリケーションには影響しません。

JAXPセキュリティに関する一般的な推奨事項

アプリケーションおよびシステムのセキュリティを確保するためのJAXPのプロパティと機能の構成に関する一般的な推奨事項を次に示します。

付録A: Java API for XML Processingの用語および定義の用語集

用語 定義
JAXP Java API for XML Processing
Java SE XML API JAXP JSRに定義され、Java SEに統合されているAPI
Java XML API Java SE XML APIと同等の用語
Java XMLの機能およびプロパティ Java SEの仕様で定義されているXML関連の機能とプロパティ
JDK XML Java XML APIのJDK実装
JDK XMLパーサー XMLパーサーのJDK実装
JDK XMLプロパティ JDK実装専用プロパティ
EAP 外部アクセス・プロパティ
FSP FEATURE_SECURE_PROCESSINGセキュリティ・ディレクティブ

付録B: JavaおよびJDK XMLの機能とプロパティの命名規則

JavaおよびJDK XMLの機能およびプロパティは、javax.xml.XMLConstantsクラスで定義されます。 機能にはプレフィクスhttp://javax.xml.XMLConstants/feature、プロパティhttp://javax.xml.XMLConstants/propertyがあります。 対応するSystemプロパティがある場合、プレフィクスはjavax.xmlです。

JDK XMLプロパティは、JDK実装専用のプロパティです。 プレフィクスは、JDKのバージョンによって異なります。 次の表に、この命名規則をまとめます。

有効範囲 APIプロパティ接頭辞 システム・プロパティ接頭辞 Java SEおよびJDKバージョン
Java SE http://javax.xml.XMLConstants/feature
http://javax.xml.XMLConstants/property
javax.xml 導入されたバージョン 1.4
JDK http://www.oracle.com/xml/jaxp/properties jdk.xml 導入されたバージョン 7

Copyright © 1993, 2025, Oracle and/or its affiliates. All rights reserved.