Подтвердить что ты не робот

Как предотвратить атаку XXE (XmlDocument в .net)

У нас был аудит безопасности на нашем коде, и они отметили, что наш код уязвим для атаки внешнего окружения (XXE). Я использую следующий код -

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);

В отчете аудита говорится, что его отказ, поскольку XML-объект может содержать URL-адреса, которые могут разрешаться вне предполагаемого contronl. Обработчик сущности XML попытается разрешить и получить внешние ссылки. Если XML файл с контролируемым атакующем может быть отправлен на одну из этих функций, злоумышленник может получить доступ к информации о внутренней сети, локальной файловой системе или других конфиденциальных данных. Чтобы этого избежать, я написал следующий код, но он не работает.

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);

но я вижу здесь, что у читателя нет никакой ценности для загрузки в xmlDoc (XmlDocument). Может ли кто-нибудь помочь, где я упускаю вещи? Любая помощь приветствуется!

4b9b3361

Ответ 1

Внешние ресурсы разрешаются с помощью XmlResolver, предоставляемого через свойство XmlDocument.XmlResolver. Если ваши XML-документы ** не должны содержать никакого внешнего ресурса ** (например, DTD или схемы), просто установите это свойство как null:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.LoadXml(OurOutputXMLString);

Если вы хотите отфильтровать, откуда эти URL-адреса (например, разрешить только определенные домены), просто получить свой собственный класс из XmlUrlResolver и переопределить метод ResolveUri(). Там вы можете проверить, что такое URL и дезинфицировать его (например, вы можете разрешать только URL-адреса в своей локальной сети или из надежных источников).

Например:

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; 
    }
}

Где IsUnsafeHost() - это настраиваемая функция, которая проверяет, разрешен ли данный хост или нет. См. этот пост здесь, на SO за несколько идей. Просто верните null из ResolveUri(), чтобы сохранить код от такого рода атак. Если разрешен URI, вы можете просто вернуть реализацию по умолчанию XmlUrlResolver.ResolveUri().

Чтобы использовать его:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = new CustomUrlResolver();
xmlDoc.LoadXml(OurOutputXMLString);

Для получения более подробной информации о том, как разрешены внешние ресурсы XML, просто прочитайте Разрешение внешних ресурсов в MS Docs. Если ваш код более сложный, чем этот пример, вы должны обязательно прочитать Раздел замечаний для XmlDocument.XmlResolver.

Ответ 2

Итак, лучше использовать

new XmlDocument { XmlResolver = null };

Интересно, что из .net 4.5.2 и 4.6, по умолчанию распознаватель ведет себя по-разному и не использует XmlUrlResolver upfront неявно для разрешения любых URL-адресов или местоположений, как я видел.

//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();