2 Oracle XML Developer's Kitのセキュリティ上の考慮事項

この章では、XDKを使用して構築されたソフトウェア・プログラムの使用時に実行されるセキュリティ手段について説明します。

2.1 Javaのセキュリティの実装

Javaプログラムのセキュリティを実装するプロセス。

2.1.1 Oracle XML Developer's Kitを使用したXSLT処理の保護

XSLT処理のためにOracle XML Developer's Kitを使用する前に、いくつかの構成オプションを設定して保護する必要があります。

次のように、XSLProcessor APIとJAXPトランスフォーマAPIの両方でセキュアな処理を有効にする必要があります。

  • このJavaコードを使用して、XSLProcessorのセキュアな処理モードを有効にします。

    processor.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); 
  • JAXPトランスフォーマAPIのSAXTransformerFactoryのセキュアな処理モードを有効にするには、次のJavaコードを使用します。

    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); 

これらの設定によって、次のようにXML解析セキュリティが向上します。

  • デフォルトでは、この設定によって外部リソースへのアクセスがブロックされます。

    開発者は、XSLスタイルシートのinclude要素およびimport要素を解決するために、org.xml.sax.EntityResolverまたはjavax.xml.transform.URIResolverを使用できるようになります。JavaインタフェースURIResolverを使用して、信頼できる外部リソースへのXPath関数またはXSLT関数のアクセスを提供できます。

  • 設定によってJavaリフレクションの使用がブロックされ、Javaコードが実行されます。

    開発者は、信頼できるJavaクラスをインタフェースjavax.xml.xpath.XPathFunctionに変換し、インタフェースjavax.xml.xpath.XPathFunctionResolverを使用して解決できます。

  • 設定によって再帰エンティティ拡張が制限されます。

    これにより、過剰なリソース消費による一般的なサービス拒否攻撃を防ぐことができます。

    注意:

    これにより、再帰的なエンティティ拡張を制限できますが、XDKではXML変換中はリソース消費を制限できません。XSLスタイルシートには無限ループを含められます。含めない場合、リソースは大幅に消費されます。このため、信頼できないソースまたは外部エンティティからXSLスタイルシートを受け入れることはできません。使用されているすべてのスタイルシートをテストし、過剰なリソースが消費されないようにします。

さらに、ユーザーまたは外部の信頼できないエンティティから取得されるデータまたはファイルのXSLT処理を実行するすべてのコードは、XSLProcessor APIとJAXPトランスフォーマAPIの両方でセキュアな処理が有効になっていることを確認します。これを行わないと、セキュリティの脆弱性を開放してしまいます。XSLプロセッサが保護されると、外部リソースへのアクセスおよびJava拡張関数の実行は許可されません。

任意のセキュリティ免除

セキュリティ制限を任意でオーバーライドする場合は、次のオプションを使用できます。

  • 次のいずれかの変更を実行して、一部の外部ソースへのアクセスを許可します。

    • メソッドsetURIResolver()を使用して、URIResolverSAXTransformerFactoryまたはXSLProcessorに設定します。

    • メソッドsetEntityResolver()を使用して、EntityResolverXSLProcessorに設定します。

  • Javaインタフェースoracle.xml.xslt.XSLSecurityManagerを使用して、Javaリフレクション拡張機能を使用できるJavaクラスとメソッドのホワイトリストを登録します。

  • XSLProcessorのメソッドsetAttribute()を使用してXSLSecurityManagerを登録し、安全であるとわかっている拡張関数を実行します。

    processor.setAttribute(XSLProcessor.SECURITY_MANAGER, securityManager);
  • XSLSecurityManagerの単純なAPIを使用して、Javaクラスおよびメソッドのホワイトリストを実装します。

    boolean checkExtensionFunction(String className, String fnName);

2.1.2 Oracle XML Parserの安全な使用

多くのXMLパーサーと同様に、XDKパーサーはデフォルトで外部参照の解決を試みます。攻撃者は、この動作を悪用してXML外部エンティティ(XXE)攻撃およびXMLエンティティ拡張(XEE)攻撃を実行できます。この脆弱性を回避するには、外部リソースへの任意の参照の使用を無効にし、制約のないエンティティ拡張を無効にします。

システム内に作成されたすべてのパーサーを外部エンティティの使用からブロックするグローバル・セキュリティ設定を実装するには、Javaシステム・プロパティoracle.xdkjava.security.resolveEntityDefaultfalseに設定します。

特定のパーサーのエンティティ拡張をブロックしたり、エンティティ拡張のレベル数を制限するには、属性XMLParser.RESOLVE_ENTITY_DEFAULTまたはXMLParser.ENTITY_EXPANSION_DEPTHをパーサーに設定します。

次に例を示します。

DOMParser domParser = new DOMParser(); // Extend oracle.xml.parser.v2.XMLParser
domParser.setAttribute(DOMParser.EXPAND_ENTITYREF, false); // Do not  expand entity references
domParser.setAttribute(DOMParser.DTD_OBJECT, dtdObj);  // dtdObj is an instance of oracle.xml.parser.v2.DTD
domParser.setAttribute(DOMParser.ENTITY_EXPANSION_DEPTH, 12); // Do not allow more than 11 levels of entity expansion

JAXPを使用してXML解析を行う場合は、DocumentBuilderFactoryまたはSAXParserFactorに対してFEATURE_SECURE_PROCESSINGtrueに設定します。これにより、外部エンティティの拡張がブロックされ、エンティティ拡張が深さ11に制限され、エンティティ拡張数が64000に制限されます。

my_factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

例2-1 XMLパーサーを使用するJavaコードの安全性の向上

このJavaスニペットは、外部エンティティの解決をブロックし、エンティティ拡張レベルの数を制限し、エンティティ拡張の数を制限します。

try {
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  dbf.setNamespaceAware(true);
  dbf.setXIncludeAware(false);
  dbf.setExpandEntityReferences(false);  // Disable expanding of entities
  try {
    dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSINGtrue);
  } catch (Throwable e) {
      //handle old parser version
      ...
  }
  DocumentBuilder dp = dbf.newDocumentBuilder();
  // Make resolveEntity just throw an exception.
  //   (If you really need to support external references
  //    then resolve publicId only against trusted values.)
  dp.setEntityResolver(new EntityResolver() {
    public InputSource resolveEntity(String publicId, String systemId)
                         throws DOMException, IOException {
      throw new DOMException((short)0, "Security Violation");
    }
  });
...

2.2 Cのセキュリティの実装

Cプログラムのセキュリティを実装するプロセス。

安全でないアクセスのブロック

通常、XXE攻撃のリスクを負うXDK C APIの2つのセットがあります。1セットは関数LpxInitEncoded()を使用し、もう1セットは関数XmlCreate()またはXmlCreateNew()を使用します

LpxInitEncoded()の場合、フラグLPX_FLAG_URL_DONT_OPEN およびLPX_FLAG_FILE_DONT_OPENをパーサーAPIにフィードして、外部リソース・アクセスをブロックします。

次に例を示します。

LpxBufferParse ( ctx,
                 (oratext *) buf,
                 (size_t) lstlen ( buf ),
                 (oratext *) "UTF-8", (lx_langid) 0, (lxglo *) 0,
                 LPX_FLAG_URL_DONT_OPEN | LPX_FLAG_FILE_DONT_OPEN);

XmlCreate()またはXmlCreateNew()の場合、コンテキストxctxの作成時にパラメータno_ri_openTRUEに設定します。この設定により、xctxを使用するパーサーAPIの安全でないアクセスがブロックされます。

次に例を示します。

xctx = XmlCreateNew(&xerr, (oratext *) "test",
                    (oratext **)NULL, 0, (oratext *)NULL,
                    "data_encoding", “AL32UTF8”,
                    "input_encoding", "AL32UTF8",
                    "no_ri_open",  "TRUE", /* disallow URI resolution */
                    "error_handler", test_errmsg,
                    NULL);

安全でないアクセスをブロックするために、DOM APIでパラメータno_ri_openTRUEに設定することもできます。DOM APIでこのフラグを設定すると、このフラグがXmlCreate()で設定されていない場合でもセキュリティが強制されます。

次に例を示します。

doc = XmlLoadDom(xctx, &xerr,
                 "file", filename,
                 "discard_whitespace", TRUE,
                 "validate", TRUE,
                 "no_ri_open", TRUE, /* disallow URI resolution */
                 NULL);

任意のアクセスを許可

ユーザーが外部リソースへの任意の参照を許可したり、アクセスをユーザー自身のコントロールの下で行ったりする場合、次のステップを実装できます。

  1. 前の例で示した場所でno_ri_openFALSEに設定します。

  2. カスタマイズされたオープン、読取りおよびクローズのコールバック関数を開発し、これらの関数を使用してOraSteamを初期化します。

  3. xctxへのアクセスをOraSteamでオーバーライドします

次に例を示します。

ostream = OraStreamInit(actx, (oratext *)"test", &oerr,
                        "open", http_open,
                        "read", http_read,
                        "close", http_close,
                        NULL);
xerr = XmlAccess(xctx, XML_ACCESS_HTTP, ostream);

このコードは、3つのコールバックによって、ostreamのインスタンスを作成します。作成されたストリームは、XmlAccessを使用してxctx内のアクセスをオーバーライドします。xctxXmlLoadDomなどのAPIを呼び出すときに使用されます。したがって、ユーザーには外部リソースにアクセスできるルールを作成する選択肢があります。

2.3 C++のセキュリティ

デフォルトでは、C++ APIは外部リソースへのアクセスをブロックするため、セキュリティが保証されます。ただし、ユーザーはこのセキュリティ制限をオーバーライドし、自分の判断に基づいて外部リソースへの任意の参照を許可できます。

xmlctx.hppヘッダー・ファイルでは、CXmlCtx(bool no_ri_open) APIを使用してxctxコンテキストを初期化し、パラメータno_ri_openを設定します。no_ri_openパラメータがtrueに設定されている場合、xctxを使用するパーサーAPIは外部リソースにアクセスできません。no_ri_openパラメータをfalseに設定すると、xctxを使用するパーサーAPIは外部リソースにアクセスできます。

デフォルトでは、xctxを使用するパーサーAPIは外部リソースにアクセスできません。アクセスを許可するには、次に示すようにno_ri_openパラメータをfalseに設定します。

xctx = CXmlCtx(FALSE); /* allow URI resolution */ 

注意:

外部リソースへのアクセスを許可すると、XML外部エンティティ(XXE)およびXMLエンティティ拡張(XEE)攻撃が発生する場合があります。セキュリティ制限をオーバーライドし、外部リソースへのアクセスを許可する場合は、注意が必要です。