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時間と大量のメモリーを消費し、最終的にシステムのメモリーが不足する可能性があります。

セキュア処理機能(FSP)

javax.xml.XMLConstants.FEATURE_SECURE_PROCESSINGと定義されているセキュア処理(FSP)の機能が、XML処理を保護するための中心的なメカニズムです。 パーサーやトランスフォーマなどのXMLプロセッサに、XMLを安全に処理するよう指示します。

デフォルトでは、JDKはDOMおよびSAXパーサーやXMLスキーマ・バリデータのFSPをオンにします。これらは、プロセッサに対して多数の処理制限を設定します。 反対に、JDKではデフォルトでトランスフォーマとXPathのFSPがオフになります。これにより、XSLTおよびXPathの拡張関数が使用可能になります。

ファクトリのsetFeatureメソッドをコールし、XMLConstants.FEATURE_SECURE_PROCESSINGtrueまたはfalseに設定して、FSPのオンとオフを切り替えます。 たとえば、次のコード・スニペットは、XMLConstants.FEATURE_SECURE_PROCESSINGtrueに設定することでファクトリspfによって作成されたSAXパーサーのFSPをオンにします:

    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

FSPはファクトリを通じてオンまたはオフにすることができますが、Javaセキュリティ・マネージャが存在する場合は常にオンになり、オフにはできません。 このため、Java XMLプロセッサは、Javaセキュリティ・マネージャが存在する場合に制限と制約を適用します。 ただし、アプリケーションの具体的なニーズに応じて、個々のプロパティを調整できます。 JAXPプロパティには、次の2種類があります。

次の項では、これらの2種類のJAXPプロパティについて説明します。

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

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

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

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

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

「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

外部アクセス制限用のJAXPプロパティ

外部アクセス制限用のJAXPプロパティを対応するシステム・プロパティとともに使用すると、外部接続を規制できます。

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

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

外部アクセス制限のJAXPプロパティは、javax.xml.XMLConstantsで次のように定義されます:

ACCESS_EXTERNAL_DTD

属性 説明
名前 http://javax.xml.XMLConstants/property/accessExternalDTD
定義 外部DTDおよび外部エンティティ参照へのアクセスを指定されたプロトコルに制限します。
「外部アクセス制限のJAXPプロパティの値」を参照してください
デフォルト値 all。すべてのプロトコルへの接続が許可されます
システム・プロパティ javax.xml.accessExternalDTD

ACCESS_EXTERNAL_SCHEMA

属性 説明
名前 http://javax.xml.XMLConstants/property/accessExternalSchema
定義 schemaLocation属性、import要素およびinclude要素によって設定された外部参照用に指定されたプロトコルへのアクセスを制限します。
「外部アクセス制限のJAXPプロパティの値」を参照してください
デフォルト値 all。すべてのプロトコルへの接続が許可されます。
システム・プロパティ javax.xml.accessExternalSchema

ACCESS_EXTERNAL_STYLESHEET

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

外部アクセス制限のJAXPプロパティの値

外部アクセス制限用のすべてのJAXPプロパティが同じ形式の値を持ちます。

スコープと順序

セキュア処理機能の設定のスコープ

XMLプロセッサ(DOM、SAX、スキーマ検証、XSLT、XPathなど)には、セキュア処理機能(FSP)が必要です。

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

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

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

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

一般に、より小さいスコープに設定されたJAXPプロパティは、より大きいスコープのJAXPプロパティより優先されます。

外部アクセス制限の設定のスコープ

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

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

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

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

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

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

適用する処理制限および使用する値を決定する場合は、システム・レベルで、アプリケーションで使用可能なメモリー量、および信頼できないソースからの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です。

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

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

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

外部アクセス制限プロパティをカスタム・リゾルバおよびカタログ(「Java XMLリゾルバの使用」を参照してください)とともに使用して、外部接続を効果的に管理し、リスクを軽減できます。

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

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プロパティを他の手段で設定するかどうかに関係なく、アプリケーションの動作が同じようになります。

システム・プロパティの使用

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

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.propertiesファイルの使用

すべての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プロパティの設定時にアプリケーションが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

XML (StAX)用のストリーミングAPI、JSR 173では、FSPがサポートされず、外部アクセス制限もサポートされません。 一方、JDKのStAX実装では処理制限がサポートされ、JAXPのコンテキストでのStAXでは外部アクセス制限がサポートされます。

StAXおよび処理制限

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

StAXおよび外部アクセスの制限

JDKのStAX実装では、外部アクセス制限に関連する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を無効にしたアプリケーションには影響しません。

拡張関数

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

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);

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);

サードパーティ製パーサー

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

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実装専用プロパティ
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.