XXEと.NET Framework (SgmlReaderDll.dll)


XXEと.NET Framework (SgmlReaderDll.dll)

XXEとは

XXE(XML External Entity)とは、XMLの外部参照機能を利用して、サーバ内部のファイル内容を取得(漏えい)したり、内部ネットワーク上のファイルにアクセスしたりする不正行為

XXEは、XMLを扱うアプリケーションで発現する可能性があるので、XML文書を取り扱う際には注意する必要がある。

SgmlReaderDll.dll

SGMLReader(SgmlReaderDll.dll)は、ゆるくXML解釈してくれるので、HTMLをDOM化する際によく使われているのではないかと思う。

一部のHTMLタグだけ許可する」のサンプルコードとしてもHTMLのDOM化に使っている

結論

SGMLReader(SgmlReaderDll.dll)には、XXEは発現しないようだ。

SGMLReaderも最終的には、System.Xml.XmlDocumentクラスに渡るので、念のためにSystem.Xml.XmlDocument#XmlResolver プロパティを「NULL」にしても良いかもしれない。

なぜSystem.Xml.XmlDocument#XmlResolver プロパティをNULLにした方がよいのか(System.Xml.XmlDocumentクラスのXXE対策)は、「XXEと.NET Framework」を参照してくれ。

SgmlReaderDll.dllとXXE

読み込むXMLファイル(in1.xml)はここ

SgmlReaderDll.dllとXXE(HTMLモードで、IgnoreDtd=True で、XmlResolverは無指定)

こんな感じ
XXEが発現していない。

SgmlReaderDll.dllとXXE(HTMLモードで、IgnoreDtd=False で、XmlResolverは無指定)

こんな感じ。in1.xmlには DTDがないので、そりゃぁ~、例外を吐くでしょうね。

SgmlReaderDll.dllとXXE(XMLモードで、IgnoreDtd=True で、XmlResolverは無指定)

こんな感じ。
XXEが発現していない。

SgmlReaderDll.dllとXXE(XMLモードで、IgnoreDtd=False で、XmlResolverは無指定)

こんな感じ。
XXEが発現していない。

SgmlReaderDll.dllとXXE

もう飽きた。

上記のテスト結果だと、SGMLReader(SgmlReaderDll.dll)には、XXEは発現しないようだ。

とはいえ、
SGMLReaderも最終的には、System.Xml.XmlDocumentクラスに渡るので、念のためにSystem.Xml.XmlDocument#XmlResolver プロパティを「NULL」にしても良いかもしれない。

ソースコード見たら・・・

SGMLReader(SgmlReaderDll.dll)のソースコードを見たら、2530行目辺りに「ResolveEntity()」のオーバーライドがあって、

// We never return any entity reference nodes, so this should never be called.

というコメントが確認できる。

つまり、SGMLReader(SgmlReaderDll.dll)を使う場合は、XXE脆弱性はないという事でよいのではないか

ソースコード(Program.cs)

XXEと.NET Frameworkとほぼ同様だが、SGMLReader(SgmlReaderDll.dll)を参照設定する必要がある

Program.cs
using System;
using System.IO;
using System.Xml;

namespace XMLandXXEtest{
    class Program{
        static void Main(string[] args){
            Boolean Isresolve = true;
            exXmlResolver myExXmlResolver = null;
            if (3 < args.Length) {
                if (args[3].ToLower() == "null"){
                    Isresolve = false;
                }else {
                    myExXmlResolver = new exXmlResolver();
                }
            }
            if (args.Length < 3) {
                Console.WriteLine("usage: XMLandXXEtest.exe <<xmlFile>> <<HTML|XML>> <<T|F|N>> [NotResolve]");
            }else{

                StreamReader sr = new StreamReader(new FileStream(args[0], FileMode.Open, FileAccess.Read));
                String str = sr.ReadToEnd();
                sr.Close();

                Sgml.SgmlReader tempSgmlReader = new Sgml.SgmlReader();
                tempSgmlReader.DocType = args[1];
                switch(args[2].ToLower()){
                    case "t":
                        tempSgmlReader.IgnoreDtd = true;
                        break;
                    case "f":
                        tempSgmlReader.IgnoreDtd = false;
                        break;
                    default:
                        break;
                }

                StringReader tempStringReader = new StringReader(str);
                tempSgmlReader.InputStream = tempStringReader;

                XmlDocument tempXmlDocument = new XmlDocument();
                // tempXmlDocument.XmlResolver = null; // 本番では念のためにコメントアウトした方がよい
                if (Isresolve == false){
                    tempXmlDocument.XmlResolver = null;
                }else if (myExXmlResolver != null){
                    tempXmlDocument.XmlResolver = myExXmlResolver;
                }
                tempXmlDocument.Load(tempSgmlReader);
                Console.WriteLine("after XML Resolve is (OuterXml)");
                Console.WriteLine(tempXmlDocument.OuterXml);
                Console.WriteLine("----------------------------------");
                Console.WriteLine("after XML Resolve is (InnerXml)");
                Console.WriteLine(tempXmlDocument.InnerXml);
                Console.WriteLine("----------------------------------");
                Console.WriteLine("after XML Resolve is (InnerText)");
                Console.WriteLine(tempXmlDocument.InnerText);
                Console.WriteLine("----------Detail------------------");
                foreach (XmlNode x in tempXmlDocument.ChildNodes){
                    WroteXMLnode(x, "");
                }
            }
        }
        static void WroteXMLnode(XmlNode node, String spaceStr) {
            Console.WriteLine(spaceStr + "name=" + node.Name + ", type=" + node.NodeType.ToString());
            Console.WriteLine(spaceStr + "valT=" + node.InnerText);
            Console.WriteLine(spaceStr + "valX=" + node.InnerXml);
            if (node.HasChildNodes == true){
                foreach (XmlNode x in node.ChildNodes){
                    WroteXMLnode(x, spaceStr + " ");
                }
            }
        }
    }
}

ソースコード(exXmlResolver.cs)

XXEと.NET Frameworkと全く同じなので、省略

戻る

XXE基本編へ戻る