XXE (XML External Entity) est un acte frauduleux d'acquisition (fuite) du contenu d'un fichier à l'intérieur du serveur ou d'accès à un fichier sur le réseau interne en utilisant la fonction de référence externe de XML.
Puisque XXE peut être exprimé dans des applications qui gèrent XML, il faut être prudent lors de la manipulation de documents XML.
Pour gérer XML en Java, envisagez d'utiliser javax.xml.parsers.DocumentBuilder. Être terminé.
Par conséquent, après cela, vous pouvez le reproduire en utilisant javax.xml.parsers.DocumentBuilder. Pensons aux contre-mesures.
Il existe également un moyen de contrôler le lien des bases de XXE avec les propriétés JavaVM, ce qui peut être le moyen le plus rapide. D'un autre côté, si vous êtes un programmeur Java, il ne devrait pas être difficile de créer et de contrôler le résolveur vous-même.
Le programme de code source suivant est conçu pour spécifier le fichier XML comme premier argument et le mode de fonctionnement de la référence externe comme deuxième argument, de sorte que le fichier XML ([C: \ z \ xmlxxe] est le mode de fonctionnement par défaut. \ in1.xml](https://qiita.com/tomoki0sanaki/items/015b6e8b807ed256a6e4#xml%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB--in1xml)) Je lirai.
Comme ça.
Dans le cas de Java, cela signifie qu'il sera attaqué par XXE par défaut.
Vient ensuite la [méthode javax.xml.parsers.DocumentBuilder # setEntityResolver ()](https://docs.oracle.com/javase/jp/6/api/javax/xml/parsers/DocumentBuilder.html#setEntityResolver (org.xml) Essayez de donner "NULL" dans .sax.EntityResolver)).
Comme ça.
Contrairement au .NET Framework, ** Null est l'objet de résolution par défaut, donc dans le cas de Java, même NULL est sujet aux attaques XXE. ** **
Vient ensuite "** Je veux utiliser la fonction de référence externe de manière limitée, mais je veux empêcher XXE ". Ou, si vous dites " Je veux empêcher la fonction de référence externe en modifiant le résolveur **", vous pouvez créer votre propre résolveur.
Autrement dit, [méthode javax.xml.parsers.DocumentBuilder # setEntityResolver ()](https://docs.oracle.com/javase/jp/6/api/javax/xml/parsers/DocumentBuilder.html#setEntityResolver (org.xml) .sax.EntityResolver))) a le premier argument "org.xml.sax.EntityResolver Puisqu'il s'agit d'un type d'interface, créez une classe qui en hérite et utilisez-la [méthode javax.xml.parsers.DocumentBuilder # setEntityResolver ()](https://docs.oracle.com/javase/jp/6/api/ En l'attribuant au premier argument de javax / xml / parsers / DocumentBuilder.html # setEntityResolver (org.xml.sax.EntityResolver)), vous pouvez contrôler librement la référence externe.
La méthode qui doit être écrasée est "org.xml.sax.InputSource.InputSource resolutionEntity (String publicId, String systemId) /EntityResolver.html#resolveEntity (java.lang.String,% 20java.lang.String)) "méthode uniquement.
L'élément clé de ceci est le type String qui indique l'URL de la référence externe dans le deuxième argument, donc le "[org.xml.sax.InputSource.InputSource] correspondant (https://docs.oracle.com/" javase / jp / 6 / api / org / xml / sax / InputSource.html) ”est simplement renvoyé.
Et le approprié de ce type "org.xml.sax.InputSource.InputSource" Classe "Java.io.InputStream" ou "[java.io.Reader](https :: //docs.oracle.com/javase/jp/6/api/java/io/Reader.html) ”doit être renvoyé.
Par exemple, une personnalisation individuelle est possible, comme exiger une authentification ou autoriser uniquement des URI spécifiques.
La "classe exEntityResolver" du code source "exEntityResolver.java" est finalement vide java.io.ByteArrayInputStream pour l'ID système indiquant tous les URI. J'ai décidé de retourner la classe "exInputSource" qui ne renvoie que jp / 6 / api / java / io / ByteArrayInputStream.html).
Ça ressemble à ça.
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 + " ");
}
}
}
}
Un résolveur qui renvoie simplement une classe InputSource qui renvoie simplement un ByteArrayInputStream vide
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();
}
}
Une classe InputSource qui renvoie simplement un ByteArrayInputStream vide.
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);
}
}
Retour aux principes de base de XXE
Recommended Posts