XXEと.NET Framework (SgmlReaderDll.dll)

# XXEと.NET Framework (SgmlReaderDll.dll)

## XXEとは

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

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

## SgmlReaderDll.dll

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

「[一部のHTMLタグだけ許可する](https://qiita.com/tomoki0sanaki/items/2203caf5e162ab232050)」のサンプルコードとしてもHTMLのDOM化に使っている

## 結論

[SGMLReader](https://github.com/mindtouch/sgmlreader)(SgmlReaderDll.dll)には、XXEは発現しないようだ。

[SGMLReader](https://github.com/mindtouch/sgmlreader)も最終的には、[System.Xml.XmlDocumentクラス](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument?view=netframework-4.7.2)に渡るので、念のために[System.Xml.XmlDocument#XmlResolver プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument.xmlresolver?view=netframework-4.7.2#System_Xml_XmlDocument_XmlResolver)を「**NULL**」にしても良いかもしれない。

なぜ[System.Xml.XmlDocument#XmlResolver プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument.xmlresolver?view=netframework-4.7.2#System_Xml_XmlDocument_XmlResolver)をNULLにした方がよいのか([System.Xml.XmlDocumentクラス](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument?view=netframework-4.7.2)のXXE対策)は、「[XXEと.NET Framework](https://qiita.com/tomoki0sanaki/items/1987ecd472a1fd325d71)」を参照してくれ。

## SgmlReaderDll.dllとXXE

読み込むXMLファイル(in1.xml)は[ここ](https://qiita.com/tomoki0sanaki/items/015b6e8b807ed256a6e4#xml%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB--in1xml)

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

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

![079.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/b814dd7b-407f-3813-9f8c-3bf6658e3122.png)

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

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

![080.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/915aff1c-6aa5-1cf6-367d-10510b9ab741.png)

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

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

![081.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/b3e7bf52-0bdc-cc27-ecfa-53829d3c85ea.png)

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

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

![082.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/946b63ca-d7cf-6ee7-8aaf-23927854ac4b.png)

## SgmlReaderDll.dllとXXE

もう飽きた。

上記のテスト結果だと、[SGMLReader](https://github.com/mindtouch/sgmlreader)(SgmlReaderDll.dll)には、XXEは発現しないようだ。

とはいえ、
[SGMLReader](https://github.com/mindtouch/sgmlreader)も最終的には、[System.Xml.XmlDocumentクラス](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument?view=netframework-4.7.2)に渡るので、念のために[System.Xml.XmlDocument#XmlResolver プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmldocument.xmlresolver?view=netframework-4.7.2#System_Xml_XmlDocument_XmlResolver)を「**NULL**」にしても良いかもしれない。

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

[SGMLReader](https://github.com/mindtouch/sgmlreader)(SgmlReaderDll.dll)の[ソースコード](https://github.com/MindTouch/SGMLReader/blob/master/sgmlreaderdll/SgmlReader.cs)を見たら、2530行目辺りに「ResolveEntity()」のオーバーライドがあって、

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

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

つまり、[SGMLReader](https://github.com/mindtouch/sgmlreader)(SgmlReaderDll.dll)を使う場合は、XXE脆弱性はないという事でよいのではないか

# ソースコード(Program.cs)

[XXEと.NET Framework](https://qiita.com/tomoki0sanaki/items/1987ecd472a1fd325d71)とほぼ同様だが、[SGMLReader](https://github.com/mindtouch/sgmlreader)(SgmlReaderDll.dll)を参照設定する必要がある


```csharp: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](https://qiita.com/tomoki0sanaki/items/1987ecd472a1fd325d71)と全く同じなので、省略

## 戻る

[XXE基本編へ戻る](https://qiita.com/tomoki0sanaki/items/015b6e8b807ed256a6e4)