Как предотвратить атаку XXE
У нас был аудит безопасности нашего кода, и он упомянул, что наш код уязвим для атак XML EXternal Entity (XXE).
объяснение
Атрибуты XML External Entities используют функцию XML для динамического создания документов во время обработки. Объект XML позволяет динамически включать данные из заданного ресурса. Внешние объекты позволяют XML-документу включать данные из внешнего URI. Если не настроено иначе, внешние сущности вынуждают парсер XML обращаться к ресурсу, указанному в URI, например, на локальном компьютере или в удаленной системе. Такое поведение предоставляет приложение для атак XML External Entity (XXE), которые могут использоваться для отказа в обслуживании локальной системы, получения несанкционированного доступа к файлам на локальном компьютере, сканирования удаленных компьютеров и отказа в обслуживании удаленных систем,
Следующий XML-документ показывает пример атаки XXE.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
В этом примере может произойти сбой сервера (в системе UNIX), если парсер XML попытается заменить объект содержимым /dev/random file.
Рекомендация
XML unmarshaller должен быть настроен безопасно, чтобы он не позволял внешним объектам быть частью входящего XML-документа.
Чтобы избежать инъекции XXE, не используйте немаршальные методы, которые обрабатывают источник XML напрямую как java.io.File
, java.io.Reader
или java.io.InputStream
. Разбирайте документ с помощью безопасно настроенного анализатора и используйте метод unmarshal, который воспринимает безопасный синтаксический анализатор как источник XML, как показано в следующем примере:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(<XML Source>);
Model model = (Model) u.unmarshal(document);
Код ниже - это то, где аудит обнаруживает атаку 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);
Как я могу реализовать вышеуказанную рекомендацию в своем коде? Где мне не хватает вещей?
Ответы
Ответ 1
Вы можете использовать тот же подход с DocumentBuilderFactory
:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
Чтобы все использовали это автоматически, вам нужно создать свою собственную реализацию (расширив ту, которую вы используете в настоящее время, используйте свой отладчик, чтобы узнать). Задайте функцию в конструкторе.
Затем вы можете передать новый завод для использования в свойстве System javax.xml.parsers.DocumentBuilderFactory
для виртуальной машины Java, и все будут использовать его.
Ответ 2
Обратите внимание, что использование одного только FEATURE_SECURE_PROCESSING кажется недостаточно безопасным (из blackhat-pdf):
... несмотря на рекомендацию оракула XML парсеры фактически не ограничивают внешние соединения, когда ХАРАКТЕРНАЯ ЧЕРТА _SECURE_PROCESSING включен.
OWASP рекомендует ACCESS_EXTERNAL_DTD и ACCESS_EXTERNAL_STYLESHEET.
Вместе это сделало бы:
TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
На самом деле этот вопрос является дубликатом: Как предотвратить внедрение XML внешнего объекта в TransformerFactory
Ответ 3
Вы хотите включить функцию защищенной обработки в TransformerFactory
. Это ограничит некоторые возможные злонамеренные события (атаки DOS и т.д.),
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();
Ответ 4
Я попробовал с Java 8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
И получил следующее исключение:
Caused by: org.xml.sax.SAXParseException: External Entity: Failed to read external document 'logs', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.
Ответ 5
Из-за большого количества XML-синтаксических движков на рынке способ предотвратить атаки XXE отличается от движка к движку. обратитесь к документации по двигателю. Здесь необходимо предотвратить внешнюю декларацию DOCTYPE. Если требуется внешнее объявление DOCTYPE, то отключение внешних общих объектов и внешних объектов параметров предотвратит атаки XXE на ваш код. Ниже приведен пример кода для предотвращения использования XXE при использовании анализатора 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;
}
}