Как защитить запросы XML на сервере Джерси? - PullRequest
3 голосов
/ 29 мая 2019

В настоящее время у меня есть простая конечная точка xml (пример), созданная с использованием инфраструктуры jersey-server 1.1. он потребляет и производит XML, используя следующие обозначения:

@POST
@Path("/post")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response getEmployee(Employee employee) {
     return Response.status(Status.OK).entity(employee).build();
}

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

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "file:///etc/passwd">
%a;
]>

Я хочу защитить сервер и не разрешать ему вызывать другие серверы / подавать файлы злоумышленникам.

Есть ли способ сделать это, поскольку все, включая чтение XML, исходит из самой платформы? @Consumes(MediaType.APPLICATION_XML)

Единственный способ сделать это - использовать регулярное выражение в теле запроса с фильтром? заблокировать DOCTYPE, SYSTEM, ENTITY запросы и вернуть ошибку, но мне интересно, есть ли более простой способ сделать это и переопределить поведение по умолчанию @Consumes(MediaType.APPLICATION_XML)?

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Я собираюсь обратиться только к проблеме XXE, потому что вопрос не совсем ясен относительно других конкретных проблем аутентификации / авторизации.

Начиная с Подход Blaise по предотвращению XXE с помощью базового JAXB , что нужно сделать, это получить низкоуровневый доступ к предоставленному XML. Хорошо, что Джерси поддерживает это из коробки. Один из способов сделать это - заменить аргумент Employee на StreamSource.

  1. Сначала овладейте существующим JAXBContext:

    private final @Context Providers providers; //full list of all providers available
    
  2. Измените ваш интерфейс так, чтобы он принимал StreamSource, чтобы у вас был доступ к необработанному входящему XML:

    @POST
    @Path("/post")
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response getEmployee(StreamSource employeeStreamSource)
    
  3. Сконфигурируйте демаршаллер JAXBContext для игнорирования DTD:

    public Response getEmployee(StreamSource employeeStreamSource){
        //we try to get a hold of the JAXBContext
        ContextResolver<JAXBContext> jaxbResolver = provider.getContextResolver(JAXBContext.class, MediaType.APPLICATION_XML_TYPE);
        JAXBContext jaxbContext= null;
        if(null != jaxbResolver) {
            jaxbContext = jaxbResolver.getContext(Employee.class);
        }
        if(null == jaxbContext) {
            jaxbContext = JAXBContext.newInstance(Employee.class);
        }
    
        XMLInputFactory xif = XMLInputFactory.newFactory();
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); //Don't blindly parse entities
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false); //suppress DTD
        XMLStreamReader xsr = xif.createXMLStreamReader(employeeStreamSource); //beging parsing incoming XML
    
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        Employee employee= (Employee) unmarshaller.unmarshal(xsr);  //manually unmarshal
    
        return Response.status(Status.OK).entity(employee).build();
    
    }
    
0 голосов
/ 03 июня 2019

Вам необходимо отключить функции http://apache.org/xml/features/nonvalidating/load-external-dtd и http://xml.org/sax/features/validation как , подробно описанное

  /* Set features to turn off loading of external DTDs. */
    mDocumentBuilderFactoryDelegateBuilderFactory.setFeature(
       LOADEXTERNALDTD_FEATURE, false);
    mDocumentBuilderFactoryDelegateBuilderFactory.setFeature(
       XML_VALIDATION_FEATURE, false);

Системными свойствами Java можно манипулировать программно во время выполнения, и мне пришла в голову идея динамически заменять текущую фабрику компоновщика документов оболочкой, которая устанавливает определенные функции для новых экземпляров фабрики компоновщика документов. Утверждалось, что установка этих функций приводит к тому, что ссылки на документы DTD игнорируются при разборе XML, содержащего такие ссылки.

Сокращенный код :

  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     dbf.setValidating(false);
     dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
     DocumentBuilder db = dbf.newDocumentBuilder();
     Document doc = db.parse(iStream);
...