Nous avons procédé à un audit de sécurité de notre code, qui indique que notre code est vulnérable aux attaques par XML EXternal Entity (XXE).
Explication
Les attaques d'entités externes XML bénéficient d'une fonctionnalité XML permettant de créer des documents de manière dynamique au moment du traitement. Une entité XML Permet d'inclure des données de manière dynamique à partir d'une ressource donnée. Les entités externes permettent à un document XML d'inclure des données À partir d'un URI externe. Sauf configuration contraire, les entités externes forcent l'analyseur XML à accéder à la ressource spécifiée Par l'URI, par exemple, un fichier sur la machine locale ou sur un système distant. Ce comportement expose l'application aux attaques XML External Entity (XXE), qui peuvent être utilisées pour effectuer un déni de service du système local, obtenir un accès non autorisé à des fichiers sur la machine locale , Analyser à distance machines, et effectuer un déni de service des systèmes distants.
Le document XML suivant montre un exemple d'attaque XXE.
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
Cet exemple peut provoquer le blocage du serveur (sur un système UNIX) si l’analyseur XML tente de substituer à l’entité le contenu du fichier Du fichier/dev/random.
Recommandation
Le désarmement XML doit être configuré de manière sécurisée afin d'empêcher les entités externes de faire partie d'un document XML Entrant.
Pour éviter les injections XXE, n'utilisez pas de méthodes non-marchandes qui traitent directement une source XML en tant que
Java.io.File
,Java.io.Reader
ouJava.io.InputStream
. Analyser le document avec un analyseur configuré de manière sécurisée et utiliser une méthode unmarshal qui prend l'analyseur sécurisé en tant que source XML, comme illustré dans l'exemple suivant:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(<XML Source>); Model model = (Model) u.unmarshal(document);
Le code ci-dessous est l'endroit où l'audit a trouvé l'attaque XXE:
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
System.out.println("outputing to : " + outputLocation);
File outputFile = new File(outputLocation);
StreamResult result = new StreamResult(outputFile);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
Comment puis-je implémenter la recommandation ci-dessus dans mon code? Où est-ce que je manque des choses?
Vous pouvez utiliser la même approche avec DocumentBuilderFactory
:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
Pour que tout le monde l'utilise automatiquement, vous devez créer votre propre implémentation (en étendant celle que vous utilisez actuellement; utilisez votre débogueur pour le savoir). Définissez l'entité dans le constructeur.
Ensuite, vous pouvez transmettre la nouvelle fabrique à utiliser dans la propriété système javax.xml.parsers.DocumentBuilderFactory
à Java VM et tout le monde l’utilisera.
Vous voudrez activer la fonctionnalité de traitement sécurisé sur la TransformerFactory
. Cela limitera certaines choses potentiellement malveillantes (attaques de DOS, etc.)
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();
Notez que l'utilisation de FEATURE_SECURE_PROCESSING à elle seule ne semble pas suffisamment sécurisée (de blackhat-pdf ):
Malgré les recommandations de Oracle, les analyseurs syntaxiques XML ne restreignent pas les connexions externes lorsque FEATURE _SECURE_PROCESSING est activé.
OWASP recommande ACCESS_EXTERNAL_DTD et ACCESS_EXTERNAL_STYLESHEET.
Ensemble cela ferait:
TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
En réalité, cette question est une copie de: Comment empêcher l’injection d’entité externe XML sur TransformerFactory
En raison du grand nombre de moteurs d'analyse xml sur le marché, la manière de prévenir les attaques XXE diffère d'un moteur à l'autre. veuillez vous reporter à la documentation de votre moteur. Le funda ici est d'empêcher la déclaration DOCTYPE externe. Si la déclaration DOCTYPE externe est nécessaire, la désactivation des entités générales externes et des entités de paramètres externes empêche les attaques XXE sur votre code. Vous trouverez ci-dessous un exemple de code permettant d'éviter XXE lors de l'utilisation d'un analyseur SAX.
public class MyDocumentBuilderFactory{
public static DocumentBuilderFactory newDocumentBuilderFactory(){
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try{
documentBuilderFactory.setFeature("http://Apache.org/xml/features/disallow-doctype-decl",true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);
documentBuilderFactory.setfeature("http://xml.org/sax/features/external-parameter-entities",false)
}catch(ParserConfigurationException exp){
exp.printStackTrace();
}
return documentBuilderFactory;
}
}