XXE (XML External Entity) ist ein betrügerischer Vorgang, bei dem der Inhalt einer Datei im Server erfasst (verloren geht) oder mithilfe der externen Referenzfunktion von XML auf eine Datei im internen Netzwerk zugegriffen wird.
Da XXE in Anwendungen ausgedrückt werden kann, die XML verarbeiten, muss beim Umgang mit XML-Dokumenten vorsichtig vorgegangen werden.
Verwenden Sie javax.xml.parsers.DocumentBuilder, um XML in Java zu verarbeiten. Getan werden.
Daher können Sie es anschließend mit javax.xml.parsers.DocumentBuilder reproduzieren. Lassen Sie uns über Gegenmaßnahmen nachdenken.
Es gibt auch eine Möglichkeit, die Verknüpfung der XXE-Grundlagen mit JavaVM-Eigenschaften zu steuern, sodass dies möglicherweise der schnellste Weg ist. Wenn Sie jedoch ein Java-Programmierer sind, sollte es nicht schwierig sein, den Resolver selbst zu erstellen und zu steuern.
Das folgende Quellcode-Programm gibt die XML-Datei als erstes Argument und den Betriebsmodus der externen Referenz als zweites Argument an, sodass die XML-Datei ([C: \ z \ xmlxxe] der Standardbetriebsmodus ist. \ in1.xml](https://qiita.com/tomoki0sanaki/items/015b6e8b807ed256a6e4#xml%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB--in1xml)) Ich werde lesen.
So was.
Im Fall von Java bedeutet dies, dass es standardmäßig von XXE angegriffen wird.
Als nächstes folgt die Methode javax.xml.parsers.DocumentBuilder # setEntityResolver () Geben Sie in .sax.EntityResolver)) "NULL" ein.
So was.
Im Gegensatz zu .NET Framework ist ** Null das Standard-Resolver-Objekt. Im Fall von Java ist sogar NULL XXE-Angriffen ausgesetzt. ** ** **
Als nächstes lautet "** Ich möchte die externe Referenzfunktion nur eingeschränkt verwenden, aber XXE ** verhindern". Wenn Sie "** Ich möchte die externe Referenzfunktion durch Ändern des Resolvers ** verhindern" sagen, können Sie Ihren eigenen Resolver erstellen.
Das heißt, [javax.xml.parsers.DocumentBuilder # setEntityResolver () -Methode](https://docs.oracle.com/javase/jp/6/api/javax/xml/parsers/DocumentBuilder.html#setEntityResolver (org.xml) .sax.EntityResolver))) hat das erste Argument "org.xml.sax.EntityResolver Da es sich um einen Schnittstellentyp handelt, erstellen Sie eine Klasse, die ihn erbt, und verwenden Sie ihn javax.xml.parsers.DocumentBuilder # setEntityResolver () -Methode. Indem Sie es dem ersten Argument von javax / xml / parsers / DocumentBuilder.html # setEntityResolver (org.xml.sax.EntityResolver) zuweisen, können Sie externe Referenzen frei steuern.
Die Methode, die überschrieben werden muss, lautet "org.xml.sax.InputSource.InputSource resolveEntity (String publicId, String systemId). /EntityResolver.html#resolveEntity (java.lang.String,% 20java.lang.String)) "Methode nur.
Der Hauptteil davon ist der String-Typ, der die URL der externen Referenz im zweiten Argument angibt, also die entsprechende "org.xml.sax.InputSource.InputSource. Der Typ javase / jp / 6 / api / org / xml / sax / InputSource.html) wird gerade zurückgegeben.
Und das entsprechende aus diesem Typ "org.xml.sax.InputSource.InputSource" Klasse "Java.io.InputStream" oder "[java.io.Reader](https :: //docs.oracle.com/javase/jp/6/api/java/io/Reader.html) ”sollte zurückgegeben werden.
Beispielsweise ist eine individuelle Anpassung möglich, z. B. die Anforderung einer Authentifizierung oder das Zulassen nur bestimmter URIs.
Die "exEntityResolver-Klasse" des Quellcodes "exEntityResolver.java" ist schließlich ein leerer java.io.ByteArrayInputStream für systemId, der alle URIs angibt. Ich habe beschlossen, die Klasse "exInputSource" zurückzugeben, die nur jp / 6 / api / java / io / ByteArrayInputStream.html zurückgibt.
Es sieht aus wie das.
XXEtest.java
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import java.io.File;
import org.xml.sax.EntityResolver;
public class XXEtest{
public static void main(String args[]){
System.out.println("java.exe test <<inFile>> <<Resolver>>");
if(0 < args.length){
Boolean IsResolve = false;
exEntityResolver myExEntityResolver = null;
if(1 < args.length){
if(args[1].equals("null") == true){
IsResolve = true;
}else{
myExEntityResolver = new exEntityResolver();
}
}
try{
DocumentBuilderFactory tempDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder tempDocumentBuilder = tempDocumentBuilderFactory.newDocumentBuilder();
if(IsResolve == true){
tempDocumentBuilder.setEntityResolver(null);
}else if(myExEntityResolver != null){
tempDocumentBuilder.setEntityResolver(myExEntityResolver);
}
Document tempDocument = tempDocumentBuilder.parse(new File(args[0]));
System.out.println("getTextContent : " + tempDocument.getTextContent());
System.out.print("getXmlStandalone: ");
tempDocument.setXmlStandalone(true);
System.out.println(tempDocument.getXmlStandalone());
System.out.println("========Detail=================");
PrintNode(tempDocument.getChildNodes(), "");
}catch(Exception e){
e.printStackTrace();
}
}
}
static void PrintNode(NodeList nodeList, String spacer){
Node node = null;
for(int i=0; i< nodeList.getLength(); i++){
node = nodeList.item(i);
String typeStr = "unknown";
switch(node.getNodeType()){
case Node.ELEMENT_NODE:
typeStr = "ELEMENT_NODE";
break;
case Node.ATTRIBUTE_NODE:
typeStr = "ATTRIBUTE_NODE";
break;
case Node.TEXT_NODE:
typeStr = "TEXT_NODE";
break;
case Node.CDATA_SECTION_NODE:
typeStr = "CDATA_SECTION_NODE";
break;
case Node.ENTITY_REFERENCE_NODE:
typeStr = "ENTITY_REFERENCE_NODE";
break;
case Node.ENTITY_NODE:
typeStr = "ENTITY_NODE";
break;
case Node.PROCESSING_INSTRUCTION_NODE:
typeStr = "PROCESSING_INSTRUCTION_NODE";
break;
case Node.COMMENT_NODE:
typeStr = "COMMENT_NODE";
break;
case Node.DOCUMENT_NODE:
typeStr = "DOCUMENT_NODE";
break;
case Node.DOCUMENT_TYPE_NODE:
typeStr = "DOCUMENT_TYPE_NODE";
break;
case Node.NOTATION_NODE:
typeStr = "NOTATION_NODE";
break;
}
System.out.println(spacer + "name =" + node.getNodeName() + ", type=" + typeStr);
System.out.println(spacer + "value=" + node.getNodeValue());
System.out.println(spacer + "getTextContent=" + node.getTextContent());
if(node.hasChildNodes() == true){
PrintNode(node.getChildNodes(), spacer + " ");
}
}
}
}
Ein Resolver, der nur eine InputSource-Klasse zurückgibt, die nur einen leeren ByteArrayInputStream zurückgibt
exEntityResolver.java
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
public class exEntityResolver implements EntityResolver{
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException{
System.out.println("publicId: " + publicId);
System.out.println("systemId: " + systemId);
return (InputSource)new exInputSource();
}
}
Eine InputSource-Klasse, die nur einen leeren ByteArrayInputStream zurückgibt.
exInputSource.java
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.Reader;
import java.io.InputStreamReader;
public class exInputSource extends InputSource{
ByteArrayInputStream myStream;
public exInputSource(){
byte[] hako = new byte[0];
this.myStream = new ByteArrayInputStream(hako);
}
public InputStream getByteStream(){
return (InputStream)this.myStream;
}
public Reader getCharacterStream(){
return (Reader)new InputStreamReader(this.myStream);
}
}
Recommended Posts