5

要件: 次のリクエストをアプリケーションに渡すと、

1) リスクのある入力 xml に対して XML 検証を行う方法

2) libxml2 で XXE を無効にする方法、つまり ENTITY フィールドを解析しないようにする方法

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY foo SYSTEM "file:///etc/issue">
]><TRANSACTION>
<FUNCTION_TYPE>LINE_ITEM</FUNCTION_TYPE>
<COMMAND>ADD</COMMAND>
<COUNTER>3</COUNTER>
<MAC>qof2EtycqT9YMcmOfKowpyXVbRpgM/7rncS3liK4JOs=</MAC>
<MAC_LABEL>P_206</MAC_LABEL>
<RUNNING_TAX_AMOUNT>0.00</RUNNING_TAX_AMOUNT>
<RUNNING_TRANS_AMOUNT>1.00</RUNNING_TRANS_AMOUNT>
<LINE_ITEMS>
<MERCHANDISE>
<LINE_ITEM_ID>1</LINE_ITEM_ID>
<DESCRIPTION>&foo;</DESCRIPTION>
<QUANTITY>1</QUANTITY>
<UNIT_PRICE>5.00</UNIT_PRICE>
<EXTENDED_PRICE>5.00</EXTENDED_PRICE>
</MERCHANDISE>
</LINE_ITEMS>
</TRANSACTION>

libxml2 バージョン 2.9 以降では、XXE がデフォルトで無効になっていることを理解しています。ただし、現在は 2.7.7 バージョンを使用しています。

このリンクによるとXML_ENTITY_PROCESSING

Enum xmlParserOption には、libxml2 で定義されている次のオプションを含めることはできません。

XML_PARSE_NOENT: エンティティを展開し、置換テキストに置き換えます XML_PARSE_DTDLOAD: 外部 DTD を読み込みます

これまで、xmlParseMemory関数を使用して XML メモリ内ブロックを解析し、ツリーを構築していました。この関数は、xmlParserOption を設定するためのパラメータを取りません。

次に、xmlReadMemory関数と同じことを行いxmlParseMemoryますが、異なるパラメーターを取る関数に変更しました。

docPtr = xmlReadMemory(szXMLMsg, iLen, "noname.xml", NULL, XML_PARSE_RECOVER);

それでも、ENTITY フィールドが解析されていることがわかります。誰でも私を助けることができますか?さらに追加情報が必要な場合はお知らせください。

お時間をいただきありがとうございます。

よろしく

プラヴィーン

4

1 に答える 1

3

を指定しない場合でもXML_PARSE_NOENTENTITY宣言は解析されますが、エンティティは置き換えられません。また、で/etc/issue確認できるファイルは開かれませんstraceXML_PARSE_NOENTしたがって、XXE から保護するには、単純にパーサー オプションを渡さないようにし ます。

オプションの名前は少し誤解を招きXML_PARSE_NOENTます。これは、解析されたドキュメントにエンティティ ノードを作成してはならないことを意味します。その結果、すべてのエンティティが拡張されます。のような名前の方が適切ですXML_PARSE_EXPAND_ENTITIES

確実に確認したい場合、または読み込む URL を細かく制御してエンティティを展開したい場合は、 を使用して独自の外部エンティティ ローダーをインストールできますxmlSetExternalEntityLoader。ハンドラーが常に NULL を返す場合は安全です。ただし、外部エンティティ ローダーはあらゆる種類の外部リソースを読み込むために使用されるため、これを完全に無効にすると、他の要素 (XIncludes や XSLT スタイルシートなど) が壊れる可能性があることに注意してください。

編集:あなたの場合、エンティティが置き換えられる理由がわかりません。テストプログラムは次のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

static xmlNodePtr
find_node(xmlNodePtr parent, const char *name) {
    for (xmlNodePtr cur = parent->children; cur != NULL; cur = cur->next) {
        if (cur->type == XML_ELEMENT_NODE
            && xmlStrcmp(cur->name, (const xmlChar*)name) == 0
        ) {
            return cur;
        }
    }

    fprintf(stderr, "Element '%s' not found\n", name);
    abort();

    return NULL;
}

int
main(int argc, char **argv) {
    static const char buf[] =
        "<?xml version=\"1.0\"?>\n"
        "<!DOCTYPE foo [\n"
        "<!ENTITY foo SYSTEM \"file:///etc/issue\">\n"
        "]><TRANSACTION>\n"
        "<FUNCTION_TYPE>LINE_ITEM</FUNCTION_TYPE>\n"
        "<COMMAND>ADD</COMMAND>\n"
        "<COUNTER>3</COUNTER>\n"
        "<MAC>qof2EtycqT9YMcmOfKowpyXVbRpgM/7rncS3liK4JOs=</MAC>\n"
        "<MAC_LABEL>P_206</MAC_LABEL>\n"
        "<RUNNING_TAX_AMOUNT>0.00</RUNNING_TAX_AMOUNT>\n"
        "<RUNNING_TRANS_AMOUNT>1.00</RUNNING_TRANS_AMOUNT>\n"
        "<LINE_ITEMS>\n"
        "<MERCHANDISE>\n"
        "<LINE_ITEM_ID>1</LINE_ITEM_ID>\n"
        "<DESCRIPTION>&foo;</DESCRIPTION>\n"
        "<QUANTITY>1</QUANTITY>\n"
        "<UNIT_PRICE>5.00</UNIT_PRICE>\n"
        "<EXTENDED_PRICE>5.00</EXTENDED_PRICE>\n"
        "</MERCHANDISE>\n"
        "</LINE_ITEMS>\n"
        "</TRANSACTION>\n";

    xmlDocPtr doc = xmlReadMemory(buf, sizeof(buf), "noname.xml", NULL,
                                  XML_PARSE_RECOVER);

    xmlNodePtr trans = find_node((xmlNodePtr)doc, "TRANSACTION");
    xmlNodePtr items = find_node(trans, "LINE_ITEMS");
    xmlNodePtr merch = find_node(items, "MERCHANDISE");
    xmlNodePtr desc  = find_node(merch, "DESCRIPTION");

    for (xmlNodePtr cur = desc->children; cur != NULL; cur = cur->next) {
        if (cur->type == XML_ENTITY_REF_NODE) {
            printf("entity ref node\n");
        }
        else {
            printf("other node of type: %d\n", cur->type);
        }
    }

    xmlFreeDoc(doc);

    return 0;
}

でコンパイルすると

gcc -std=c99 -O2 -I/usr/include/libxml2 so.c -lxml2 -o so

それを実行すると、結果は

entity ref node
于 2014-04-08T14:48:18.000 に答える