У нас был аудит безопасности нашего кода, и он упомянул, что наш код уязвим для атак 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);
Как я могу реализовать вышеуказанную рекомендацию в своем коде? Где мне не хватает вещей?