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)を参照設定する必要がある
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と全く同じなので、省略