Nous avons eu un audit de sécurité sur notre code, et ils ont mentionné que notre code est vulnérable à l'attaque EXternal Entity (XXE). J'utilise le code suivant -
string OurOutputXMLString=
"<ce><input><transaction><length>00000</length><tran_type>Login</tran_type></transaction><user><user_id>ce_userid</user_id><subscriber_name>ce_subscribername</subscriber_name><subscriber_id>ce_subscriberid</subscriber_id><group_id>ce_groupid</group_id><permissions></permissions></user><consumer><login_details><username>UnitTester9</username><password>pDhE5AsKBHw85Sqgg6qdKQ==</password><pin>tOlkiae9epM=</pin></login_details></consumer></input></ce>"
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(OurOutputXMLString);
Dans le rapport d'audit, ils disent que son échec parce que l'entité XML peut contenir des URL qui peuvent être résolues en dehors du contrôle prévu. Le résolveur d'entité XML tentera de résoudre et de récupérer des références externes. Si du XML contrôlé par l'attaquant peut être soumis à l'une de ces fonctions, l'attaquant pourrait alors accéder aux informations sur un réseau interne, un système de fichiers local ou d'autres données sensibles. Pour éviter cela, j'ai écrit le code suivant mais cela ne fonctionne pas.
MemoryStream stream =
new MemoryStream(System.Text.Encoding.Default.GetBytes(OurOutputXMLString));
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.MaxCharactersFromEntities = 6000;
XmlReader reader = XmlReader.Create(stream, settings);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
mais je peux voir ici que le lecteur n'a aucune valeur à charger dans xmlDoc (XmlDocument). Quelqu'un peut-il m'aider là où je manque des choses? Toute aide est appréciée!
Les ressources externes sont résolues à l'aide de la propriété XmlResolver
fournie via la propriété XmlDocument.XmlResolver
. Si vos documents XML ** ne doivent contenir aucune ressource externe ** (par exemple des DTD ou des schémas), définissez simplement cette propriété sur null
:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.LoadXml(OurOutputXMLString);
Si vous souhaitez filtrer la provenance de ces URL (par exemple pour n'autoriser que certains domaines), dérivez simplement votre propre classe de XmlUrlResolver
et remplacez la méthode ResolveUri()
. Là, vous pouvez vérifier ce qu'est l'URL et la nettoyer (par exemple, vous ne pouvez autoriser que les URL au sein de votre réseau local ou à partir de sources fiables).
Par exemple:
class CustomUrlResovler : XmlUrlResolver
{
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
Uri uri = new Uri(baseUri, relativeUri);
if (IsUnsafeHost(uri.Host))
return null;
return base.ResolveUri(baseUri, relativeUri);
}
private bool IsUnsafeHost(string Host)
{
return false;
}
}
Où IsUnsafeHost()
est une fonction personnalisée qui vérifie si l'hôte donné est autorisé ou non. Voir cet article ici sur SO pour quelques idées. Il suffit de retourner null
de ResolveUri()
à enregistrez votre code contre ce type d'attaques. Si l'URI est autorisé, vous pouvez simplement renvoyer l'implémentation par défaut de XmlUrlResolver.ResolveUri()
.
Pour l'utiliser:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = new CustomUrlResolver();
xmlDoc.LoadXml(OurOutputXMLString);
Pour plus de détails sur la résolution des ressources externes XML, lisez Resolving External Resources sur MS Docs. Si votre code est plus complexe que cet exemple, vous devez absolument lire la propriété Remarks section for XmlDocument.XmlResolver .
Il est donc préférable d'utiliser
new XmlDocument { XmlResolver = null };
Fait intéressant à partir de .net 4.5.2 et 4.6, le résolveur par défaut se comporte différemment et n'utilise pas d'avance XmlUrlResolver implicitement pour résoudre les URL ou les emplacements comme je l'ai vu.
//In pre 4.5.2 it is a security issue.
//In 4.5.2 it will not resolve any more the url references in dtd and such,
//Still better to avoid the below since it will trigger security warnings.
new XmlDocument();