Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095 — Relatório de investigação sobre as vulnerabilidades S2-045, S2-055 do Struts2 e as vulnerabilidades CVE-2017-7525, CVE-2017-15095 do Jackson | Kitploit
Ferramentas/GitHubGitHub/secureskytechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095
Análise de VulnerabilidadesAnálise de CódigoExploração de Aplicações WebPapers e PesquisaAprendizado e EducaçãoArchived
GitHubsecureskytechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095

study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095

Relatório de investigação sobre as vulnerabilidades S2-045, S2-055 do Struts2 e as vulnerabilidades CVE-2017-7525, CVE-2017-15095 do Jackson

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório
10621há 8 anosRevisado pelo Kitploit

Relatório de investigação sobre as vulnerabilidades S2-054, S2-055 do Struts2 e as vulnerabilidades CVE-2017-7525, CVE-2017-15095 do Jackson

Publicamos um resumo simplificado e de fácil leitura. Recomendado para quem deseja uma visão geral ou tem pouco tempo.

  • SSTtechlog 08 Sobre S2-054, S2-055 e as vulnerabilidades do jackson-databind CVE-2017-7525, CVE-2017-15095 | SST SecureSky Technology Co., Ltd.
    • https://www.securesky-tech.com/column/techlog/08.html

Em 1º de dezembro de 2017, foi publicada uma atualização de segurança do Struts2. Antes da publicação, já circulava na lista de discussão a informação de que as vulnerabilidades do Jackson (biblioteca JSON popular em Java) estavam relacionadas. O autor, que utiliza Jackson em sistemas e ferramentas internas, também estava preocupado com o conteúdo específico.

  • https://lists.apache.org/thread.html/ed74083f2d7187e71ee5ed644c5e45ba58d0792b515d1d1cc28bfadf@%3Cdev.struts.apache.org%3E

Quanto ao conteúdo realmente divulgado, os dois problemas de segurança a seguir foram corrigidos. A vulnerabilidade do jackson-databind, componente do Jackson, afeta apenas o S2-055.

  • S2-055 : https://cwiki.apache.org/confluence/display/WW/S2-055
    • Esta é a correção correspondente ao CVE-2017-7525 do jackson-databind.
    • A dependência do Struts foi atualizada para jackson-databind 2.9.2. Com isso, também é compatível com o CVE-2017-15095 mencionado posteriormente.
    • https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.14.1
  • S2-054 : https://cwiki.apache.org/confluence/display/WW/S2-054
    • Esta correção substitui o uso da antiga biblioteca JSON-lib (http://json-lib.sourceforge.net/) no plugin REST, que apresentava problemas de DoS, pela biblioteca Jackson.

No plugin REST, parece que anteriormente já estavam integrados handlers que usavam JSON-lib e handlers que usavam Jackson, permitindo que o usuário escolhesse. Acredita-se que a correção completa desta vez consiste em: no S2-054, alterar o handler padrão para Jackson e, no S2-055, atualizar a versão antiga do Jackson para a mais recente.

Afinal, que tipo de vulnerabilidade é o CVE-2017-7525? Como o autor costuma usar Jackson ao processar JSON em Java, este artigo é o resultado de uma investigação sobre o problema durante o fim de semana de 2 e 3 de dezembro.


Ambiente do autor utilizado para verificação do código de amostra:

  • SO : Windows 10 Pro 64 bits
  • Java : Oracle JDK 1.8.0_92 64 bits
  • Groovy : 2.3.1

Sobre a vulnerabilidade do jackson-databind CVE-2017-7525

No blog de Adam Caudill, foi publicada uma explicação sobre o CVE-2017-7525.

  • https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

Em resumo, com minhas próprias palavras: o jackson-databind fornece a funcionalidade de mapear JSON para objetos Java (classe ObjectMapper). Ao chamar ObjectMapper.enableDefaultTyping(), é possível mapear usando um nome de classe inserido de forma personalizada no JSON. Quem pensou "quando é possível especificar o nome da classe a partir do JSON de entrada, já dá um mau pressentimento" acertou em cheio: esse mau pressentimento se concretizou no CVE-2017-7525.

Antes de entrar na explicação da vulnerabilidade, explico por que essa funcionalidade foi implementada.

Sobre a funcionalidade ObjectMapper.enableDefaultTyping()

Consulte o código de amostra a seguir para o uso básico da desserialização com jackson-databind. (Neste artigo, usamos Groovy para os códigos de amostra do Jackson. É conveniente poder alternar facilmente a versão do jackson-databind com @Grab.)

  • objectmapper-demo.groovy

No código de amostra acima, a chave "animal" pode ser mapeada diretamente para a classe Animal. E nos casos a seguir, como fica?```java class Zoo { Animal animal; }

abstract class Animal { String name; protected Animal() { } }

class Dog extends Animal { double barkVolume; Dog() { } }

class Cat extends Animal { boolean likesCream; int lives; Cat() { } }

root@kitploit:~
Nesta configuração, surgem dois tipos de conteúdo para a chave "animal": um apontando para a classe Dog e outro para a classe Cat. Portanto, são necessárias informações adicionais para saber qual classe deve ser usada no mapeamento.

Para resolver isso, o jackson-databind incorporou um processamento próprio que permite embutir o nome da classe a ser mapeada no JSON.
Por exemplo, como mostrado a seguir, o conteúdo da chave "animal" é transformado em um array, e o primeiro elemento especifica o nome da classe.```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}

Isso permite que ObjectMapper.readValue() reconheça o conteúdo da chave "animal" como da classe Dog e realize o mapeamento.

Naturalmente, não é possível distinguir, apenas com isso, se o conteúdo da chave "animal" era originalmente um array ou se continha informações de nome de classe específicas do jackson-databind.

Quem faz essa alternância é o método ObjectMapper.enableDefaultTyping().

Também existe a possibilidade de definir a anotação @JsonTypeInfo na classe. Para mais detalhes, consulte a documentação do Jackson abaixo:

  • JacksonPolymorphicDeserialization
    • https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

A seguir, apresentamos um código de exemplo que realmente utiliza o método ObjectMapper.enableDefaultTyping():

  • enable-default-type-demo.groovy

Correlação do CVE-2017-7525 com a verificação da lista negra de nomes de classe

Como vimos acima, ao fornecer o nome da classe e suas propriedades em JSON, é possível, embora com algumas limitações, instanciar classes arbitrárias com propriedades arbitrárias.

A vulnerabilidade CVE-2017-7525 explora exatamente isso, e acredita-se que o gatilho tenha sido o seguinte relatório:

  • Java Unmarshaller Security - Turning your data into code execution
    • https://github.com/mbechler/marshalsec

Bibliotecas de serialização/desserialização comuns em Java, como Jackson, foram relatadas como perigosas, pois manipulações de nomes de classe podem levar à execução de código arbitrário. Além disso, foram listados nomes de classes concretas que representam risco.

Não se sabe se foi em resposta a isso, mas cronologicamente, logo após o primeiro commit do repositório acima, foi aberta a seguinte Issue no jackson-databind e iniciou-se o tratamento:

  • Jackson Deserializer security vulnerability
    • https://github.com/FasterXML/jackson-databind/issues/1599

Como seriam, na prática, os dados JSON e o código Java que exploram essa vulnerabilidade?

O código de teste do jackson-databind 2.8.9, que tratou essa Issue, fornece uma dica:

  • https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java

Com base nesse código de teste, apresentamos a seguir um exemplo de código ajustado para permitir verificação de funcionamento:

  • cve-2017-7525-check.groovy

Se você executar especificando a versão 2.8.9 com @Grab, será exibido your jackson version IS SAFE to CVE-2017-7525. Isso ocorre porque a correção da versão 2.8.9 adicionou uma verificação de lista negra para nomes de classes que são instanciadas.

Se você executar especificando a versão 2.8.8 com @Grab, a saída será a seguinte:``` your jackson version MAY NOT BE SAFE to CVE-2017-7525 com.fasterxml.jackson.databind.JsonMappingException: N/A at [Source: { "id" : 124, "obj" : [ "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", { "transletBytecodes" : [ "AAIAZQ==" ], "transletName" : "a.b", "outputProperties" : { } } ] } ; line: 9, column: 28] (through reference chain: Bean1599["obj"]->com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl["outputProperties"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277) (...) at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128) Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) at java.security.AccessController.doPrivileged(Native Method) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:399) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:451) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:116) ... 30 more null

root@kitploit:~
Na saída do resultado, há uma linha `at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)`.
Neste código de exemplo, uma NullPointerException está sendo lançada, mas pelo nome do método, pode-se perceber que algum processamento com efeitos colaterais está ocorrendo.

Para construir um JSON que realmente consiga executar o código, parece ser necessária uma investigação mais aprofundada.
Neste artigo, vamos nos limitar a esta introdução por enquanto, mas se artigos de investigação adicionais forem publicados em outros sites, gostaríamos de adicioná-los aqui.

A propósito, onde está implementada a lista negra crucial? É a seguinte classe:
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L51

Na verdade, parece que na versão 2.8.9 havia uma falha nesta lista negra. Esse problema é o CVE-2017-15095.

### Melhoria do CVE-2017-15095 que aprimorou a lista negra

Quanto à melhoria da falha na lista negra, primeiro, em https://github.com/FasterXML/jackson-databind/issues/1680, foi adicionado `s.add("com.sun.rowset.JdbcRowSetImpl");`.
Depois que o 2.9.0 foi lançado com isso, adicionalmente, em https://github.com/FasterXML/jackson-databind/issues/1737, a seguinte verificação de lista negra foi adicionada.```java
// [databind#1737]; JDK provided
s.add("java.util.logging.FileHandler");
s.add("java.rmi.server.UnicastRemoteObject");
// [databind#1737]; 3rd party
s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor");
s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean");
s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource");
s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource");

Assim, as versões 2.8.10 / 2.9.1 foram lançadas e a correção para CVE-2017-15095 está concluída.

Código de teste para verificar o funcionamento da lista negra na versão 2.8.10:

  • https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.10/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java#L57

Com base neste código de teste, segue um código de exemplo ajustado para verificar o funcionamento:

  • cve-2017-15095-check.groovy

Ao executar a versão 2.8.10, que supostamente tem a correção concluída, especificando-a com @Grab, a mensagem your jackson version IS SAFE to CVE-2017-15095 é exibida. Em seguida, ao executar a versão 2.8.9 (antes da melhoria da lista negra) especificando-a com @Grab, a seguinte saída é exibida:``` your jackson version MAY NOT BE SAFE to CVE-2017-15095 com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.logging.FileHandler, problem: \tmp\foobar.txt.lck at [Source: { "v" : [ "java.util.logging.FileHandler", "/tmp/foobar.txt" ] } ; line: 5, column: 5] (through reference chain: PolyWrapper["v"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277) (...) Caused by: java.nio.file.NoSuchFileException: \tmp\foobar.txt.lck (...) at java.util.logging.FileHandler.openFiles(FileHandler.java:459) at java.util.logging.FileHandler.(FileHandler.java:292) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call1(AnnotatedConstructor.java:129) at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:318) ... 31 more null

root@kitploit:~
Na versão anterior, o nome da classe `java.util.logging.FileHandler` escapava da verificação da lista negra e, ao ser instanciado, tentava abrir um arquivo. Na versão posterior, ele é capturado pela verificação da lista negra e uma exceção `JsonMappingException` é lançada.

A lista negra no momento da versão 2.8.10 ficou assim. O que começa com o comentário `[databind#1737]` é a lista negra adicional correspondente ao CVE-2017-15095.
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.10/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L52

### Sobre as condições de impacto da vulnerabilidade, a viabilidade do ataque e as contramedidas no lado da aplicação

Resumindo os resultados acima, as seguintes condições são necessárias para ser afetado pela vulnerabilidade do jackson-databind:
1. Estiver usando jackson-databind 2.8.9 / 2.9.0 ou inferior.
2. Para JSON obtido de fontes não confiáveis, estiver realizando um dos seguintes processamentos:
   * Chamar `ObjectMapper.enableDefaultTyping()` e depois desserializar.
   * Não chamar `ObjectMapper.enableDefaultTyping()`, mas usar a anotação `@JsonTypeInfo` na declaração da classe para permitir mapeamento e desserializar.
   * Mesmo que não seja usado no código da aplicação, o framework pode desserializar automaticamente em resposta ao cabeçalho da requisição `Accept` ou à extensão da URL.
3. O classpath contiver classes ("Gadgets") que podem ser exploradas na vulnerabilidade de serialização/desserialização Java.
4. Os campos de membro da classe Java de destino usarem tipos que podem aceitar classes Gadget, como o tipo `Object`.
   * Se o tipo for uma classe Bean específica da aplicação que não seja compatível com a classe usada no Gadget, é possível bloquear antes da criação da instância com um erro de verificação de tipo (a menos que a própria classe Bean específica da aplicação tenha uma vulnerabilidade de desserialização).

Se você realmente será afetado parece depender muito do uso/configuração do `ObjectMapper`, da combinação da anotação `@JsonTypeInfo`, e dos campos de membro da classe de destino, ou seja, do código da aplicação.

Além disso, se o nome da chave no JSON não existir na classe Java de destino, o Jackson simplesmente o ignora.
Portanto, para que o ataque seja bem-sucedido, é necessária uma personalização de acordo com o JSON de cada aplicação, e parece muito difícil criar um código de ataque que possa ser reutilizado em várias aplicações.

Além disso, sobre a condição 4, em uma escrita comum, acho que primeiro ninguém faria um campo de classe Java ser do tipo `Object`.
Acredito que, na maioria dos casos, as classes que permitem execução de código arbitrário também não são compatíveis com as classes Bean criadas pela aplicação.

Portanto, acredita-se que a possibilidade de ocorrer um ataque em larga escala ou de causar danos reais explorando essa vulnerabilidade (ou seja, o ataque ser bem-sucedido) é baixa.

Quanto às contramedidas no lado da aplicação, para a condição 3, como classes incluídas no JDK também podem ser exploradas, parece que, na prática, não é possível tomar medidas.
Portanto, a medida básica é atualizar o jackson-databind para a versão mais recente.
Se não for possível atualizar o jackson-databind para a versão mais recente, será necessário remover a chamada `ObjectMapper.enableDefaultTyping()` ou a anotação `@JsonTypeInfo` e reformular o design para não depender disso. Por exemplo, criar um serializador personalizado.

No entanto, se você já estiver usando como uma API chamável remotamente, não pode simplesmente alterar o formato JSON.
Parece que, dependendo da configuração da anotação `@JsonTypeInfo`, é possível aceitar apenas nomes de classes previstos pelo programador, limitando as subclasses, etc.
Consulte a documentação abaixo para mais detalhes.
* JacksonPolymorphicDeserialization
  * https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

#### Sobre os prós e contras da contramedida de lista negra e a criação de um desserializador personalizado

O jackson-databind 2.8.10 / 2.9.1 respondeu ao CVE-2017-7525 e CVE-2017-15095 com a contramedida de lista negra.
No entanto, como é evidente nos problemas relacionados ao OGNL do Struts2, a contramedida de lista negra não é infalível.
(Na opinião pessoal do autor, acho que é uma medida com alguma eficácia para o nível dos chamados "script kiddies" que apenas aplicam ferramentas de varredura.)

Portanto, se você realmente deseja uma contramedida fundamental, o autor acredita que é importante desabilitar/não usar funcionalidades que incorporam informações de classe no JSON, como `ObjectMapper.enableDefaultTyping()`.
Então, como resolver o problema que `ObjectMapper.enableDefaultTyping()` estava tentando resolver?

Sobre isso, o próprio autor não tem uma alternativa que possa ser considerada a resposta correta.
A raiz do problema é, na minha opinião, "poder mapear quando a classe Java de destino é ambígua, sem depender de JSON não confiável".
Uma abordagem que pode tornar isso possível, o autor acredita, é criar um desserializador personalizado.
Um desserializador personalizado permite receber JSON durante a desserialização no lado do código do programa e controlar o objeto gerado por conta própria.

Por exemplo, se chegar `{"animal":{"name":"dog1","barkVolume":1.2}}`, é possível decidir no programa: "Como há a chave `barkVolume`, isso será instanciado como classe Dog".
Se chegar `{"animal":{"name":"cat1","likesCream":true,"lives":10}}`, é possível decidir no programa: "Como há as chaves `likesCream` e `lives`, isso será instanciado como classe Cat".
Usando isso, não é mais necessário incorporar o nome da classe no JSON.

Pessoalmente, tive a impressão de que o formato JSON com nomes de classe incorporados prejudica a interoperabilidade com outras linguagens/bibliotecas (se houver algo que permita extensões semelhantes em outras linguagens ou bibliotecas, por favor, me avise).
Em um cenário de interoperabilidade com outros sistemas, parece mais adequado criar um desserializador personalizado no lado do Jackson do que fazer com que os outros incorporem nomes de classe exclusivos para atender às necessidades do Jackson.

Acredito que existam outras soluções, e ficaria grato se os leitores pudessem compartilhar suas opiniões sobre "também existe esta solução".
(Um exemplo extremo seria não mapear para classes individuais e desserializar tudo no formato `Map<String, Object>` ou `List<String, Object>`.)

Encontrei alguns artigos de referência para criar um desserializador personalizado, então vou colocar links, embora sejam em inglês.
* Jackson: create a custom JSON deserializer with StdDeserializer and JsonToken classes | Dede Blog
  * http://www.davismol.net/2015/05/20/jackson-create-a-custom-json-deserializer-with-stddeserializer-and-jsontoken-classes/
* Getting Started with Deserialization in Jackson | Baeldung
  * http://www.baeldung.com/jackson-deserialization
* Custom JSON Deserialization with Jackson - DZone Integration
  * https://dzone.com/articles/custom-json-deserialization-with-jackson
* Building a Custom Jackson Deserializer - The Boy Wonders
  * http://www.robinhowlett.com/blog/2015/01/01/building-a-custom-jackson-deserializer/

JavaDoc do jackson-databind (versões 2.8 e 2.9):
* https://fasterxml.github.io/jackson-databind/javadoc/2.8/
* https://fasterxml.github.io/jackson-databind/javadoc/2.9/

O autor também criou um código de exemplo de desserializador personalizado, espero que sirva como dica.
* [custom-deserializer-demo.groovy](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/blob/master/custom-deserializer-demo.groovy)

## Sobre o S2-055

Até aqui, vimos vulnerabilidades do próprio Jackson. Agora, como isso afeta o plugin REST do Struts2? Verificamos usando o struts2-rest-showcase que acompanha o Struts2.

O uso do plugin REST do Struts foi baseado no seguinte:
* http://struts.apache.org/plugins/rest/

### O plugin REST do Struts2 não chama ObjectMapper.enableDefaultTyping()

A propósito, as condições para ser realmente vulnerável no CVE-2017-7525 eram as seguintes:
* Para JSON obtido de fontes não confiáveis, estiver realizando um dos seguintes processamentos:
  * Chamar `ObjectMapper.enableDefaultTyping()` e depois desserializar.
  * Não chamar `ObjectMapper.enableDefaultTyping()`, mas usar a anotação `@JsonTypeInfo` na declaração da classe para permitir mapeamento e desserializar.

Verificamos se o plugin REST do Struts2 contém código que se enquadra nessas condições e confirmamos que nenhuma delas está incluída.
Na verdade, nem `ObjectMapper.enableDefaultTyping()` nem `@JsonTypeInfo` são usados no plugin REST, e nem mesmo em toda a árvore de fontes do Struts2, mesmo na versão 2.5.14 anterior à correção.
* https://github.com/apache/struts/tree/STRUTS_2_5_14

Na árvore de fontes completa do Struts2, a única classe que usa o ObjectMapper do Jackson é `org.apache.struts2.rest.handler.JacksonLibHandler`. Após verificar o código-fonte, confirmamos que na versão 2.5.14 de fato não usa `ObjectMapper.enableDefaultTyping()`.
* https://github.com/apache/struts/blob/STRUTS_2_5_14/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonLibHandler.java
  * Este arquivo Java não mudou de conteúdo na versão 2.5.14.1.

Portanto, acredita-se que o próprio plugin REST não apresentava problemas em relação ao CVE-2017-7525 mesmo na versão 2.5.14.
A vulnerabilidade ocorre quando a anotação `@JsonTypeInfo` é definida no campo da classe que mapeia o JSON no lado da aplicação.
Assim, na verificação usando struts2-rest-showcase abaixo, definimos `@JsonTypeInfo` no campo de destino do mapeamento adicionado no lado da aplicação e verificamos.

Aliás, parece que o Struts2 também tem um plugin JSON.
* http://struts.apache.org/plugins/json/
* Olhando o código-fonte do plugin JSON, o pom.xml não inclui nenhuma outra biblioteca JSON como dependência.
* Parece que ele implementa o processamento JSON por conta própria.
* https://github.com/apache/struts/tree/STRUTS_2_5_14/plugins/json
* Portanto, acredita-se que a vulnerabilidade do jackson-databind não afeta o plugin JSON.

### Tornando o struts2-rest-showcase compatível com Jackson

O struts2-rest-showcase é um exemplo que implementa CRUD da classe Order usando o plugin REST. Adicionaremos a ele as classes Zoo / Animal / Cat / Dog usadas no código de exemplo da vulnerabilidade do Jackson, e um ZooController para processar o CRUD em JSON.

O código-fonte completo pode ser verificado abaixo (verificamos a construção e execução com JDK8 neste artigo).
* [rest-showcase](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/tree/master/rest-showcase)

Principais modificações:
* Porta de escuta pelo jetty-maven-plugin alterada para 18088. (`mvn jetty:run`)
* Adicionadas dependências jackson-core e jackson-databind.
* Adicionadas classes Zoo, Animal (abstract), Dog, Cat. Adicionada classe ZooService como camada de serviço.
* Adicionado ZooController com CRUD mínimo (JSP de visualização omitido).
* No struts.xml, o handler para JSON foi alterado para JacksonLibHandler.
* Incorporado maven-wrapper para que, com apenas o JDK instalado, seja possível construir e executar diretamente com mvnw / mvnw.bat.

Construção e execução:
1. Após clonar o repositório, vá para o diretório rest-showcase e execute `mvnw jetty:run`. (Atenção: na primeira execução, o download do maven ocorrerá, podendo levar alguns minutos ou até mais de 10 minutos dependendo do caso.)
1. Acesse http://localhost:18088/struts2-rest-showcase/ e, se a lista de Orders for exibida, é sucesso.
1. Para encerrar a execução, pressione Ctrl-C.
1. Se modificar arquivos Java, encerre com Ctrl-C e execute `mvnw jetty:run` novamente.

Verificação com o comando curl: (assumindo que passa pelo proxy local localhost:8080 como proxy http)```
一覧取得:
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo"

ID指定:
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo/1"
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo/2"

削除:
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo/2" -X DELETE

No repositório, o campo animal em Zoo.java é do tipo Animal (classe abstrata) com @JsonTypeInfo comentado, como mostrado abaixo.```java //@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public Animal animal; //public Object animal;

root@kitploit:~
Aqui, vamos enviar uma requisição JSON usando o método POST e chamar o método ZooController.create().```
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo" -X POST -H "Content-Type: application/json" -d '{"id":"3","animal":{"name":"dog2","barkVolume":2.3}}'

Então ocorreu uma exceção contendo a seguinte mensagem de erro. A classe Animal é abstrata, portanto não foi possível gerar uma instância.``` Can not construct instance of org.demo.rest.example.Animal: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

root@kitploit:~
Portanto, descomente o `@JsonTypeInfo` do campo `animal` para ativá-lo. Pare a aplicação web com Ctrl-C e execute `mvnw jetty:run` novamente.```java
// 次のimportを忘れずに追加
import com.fasterxml.jackson.annotation.JsonTypeInfo;
//...
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
    public Animal animal;
    //public Object animal;

Isso permite incorporar o nome da classe no JSON. Com o seguinte comando curl, vamos fazer POST do JSON com o nome da classe incorporado.``` curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo" -X POST -H "Content-Type: application/json" -d '{"id":"3","animal":["org.demo.rest.example.Dog",{"name":"dog2","barkVolume":2.3}]}'

root@kitploit:~
→ `HTTP/1.1 201 Created` é retornado. Ao listar, podemos confirmar que foi adicionado.

### Verificando CVE-2017-7525 no Struts2 REST plugin 2.5.14

No pom.xml do repositório, o artifact struts do `<parent>` especifica a versão 2.5.14, portanto, por padrão, é vulnerável ao CVE-2017-7525.
Para verificar, execute o seguinte comando curl. O nome da classe e seu conteúdo são baseados em cve-2017-7525-check.groovy, portanto, se a mesma resposta do jackson-databind 2.8.8 for retornada, considera-se vulnerável.```
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo" -X POST -H "Content-Type: application/json" -d '{"id":"3","animal":["com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",{"transletBytecodes":["AAIAZQ=="],"transletName":"a.b","outputProperties":{}}]}'

→ Uma exceção contendo a seguinte mensagem de erro foi lançada.``` java.lang.IllegalArgumentException: Class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl not subtype of [simple type, class org.demo.rest.example.Animal]

root@kitploit:~
O tipo do campo `animal` é a classe `Animal`, que não é um subtipo da classe `com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl`, então parece que foi lançada uma `IllegalArgumentException`.

Bem, vamos corrigir o campo `animal` em `Zoo.java` para o tipo `Object` e executar novamente com `mvnw jetty:run`.```java
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
    //public Animal animal;
    public Object animal;

Ao executar novamente o comando curl anterior, ocorreu uma exceção com o seguinte stack trace.``` Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) ~[?:1.8.0_92]

root@kitploit:~
Este é o mesmo caso de exceção vulnerável verificado com cve-2017-7525-check.groovy.

A partir disso, confirmamos a existência da vulnerabilidade CVE-2017-7525 no jackson-databind no Struts2 REST plugin 2.5.14.

Também descobrimos que é necessário usar o tipo Object além de `@JsonTypeInfo`.

Abaixo está uma opinião pessoal do autor, mas acredito que não seja comum especificar a classe Object ou classes compatíveis com gadgets de vulnerabilidade de desserialização Java como tipo de campo em classes de dados ao criar APIs REST. Portanto, sinto que seria difícil obter sucesso real em um ataque.

### Confirmando a correção no Struts2 REST plugin 2.5.14.1

Vamos verificar se a vulnerabilidade foi corrigida na versão 2.5.14.1.

Altere a versão do artefato `<parent>` no pom.xml para 2.5.14.1, reinicie com `mvnw jetty:run` e execute o mesmo comando curl de antes.```
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo" -X POST -H "Content-Type: application/json" -d '{"id":"3","animal":["com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",{"transletBytecodes":["AAIAZQ=="],"transletName":"a.b","outputProperties":{}}]}'

→ 以下のエラーメッセージを含む例外が発生しました。``` com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl: Illegal type (com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl) to deserialize: prevented for security reasons

root@kitploit:~
Esta é a mesma exceção após a correção da vulnerabilidade, como verificada no cve-2017-7525-check.groovy.

Ao abrir com uma IDE que suporta Maven, como Eclipse, e verificar a versão do jackson-databind após a resolução das dependências, você poderá confirmar que é realmente 2.9.2. Se não tiver uma IDE, você pode usar `mvnw help:effective-pom` para gerar o pom final e pesquisar por jackson-databind para confirmar que está usando a versão 2.9.2.

Sobre o CVE-2017-15095, omitirei, mas com base no exposto, foi confirmado que a versão 2.5.14.1 corrigiu a vulnerabilidade do jackson-databind.

### PoC do S2-055

※ Adicionado em 2017-12-08

Um artigo de pesquisa e relatório de PoC sobre o S2-055 foi publicado.
* Análise e Configuração do Ambiente da Vulnerabilidade S2-055 | Blog da NSFOCUS
  * http://blog.nsfocus.net/s2-055/

Ao ler com a ajuda do Google Tradutor, parece que há o mesmo entendimento sobre as condições de ocorrência e a viabilidade do ataque.

Na verdade, foi mostrado um PoC que modificou o rest-showcase e o HTTP communication que iniciou a calculadora.

Peguei apenas a parte JSON e primeiro testei com Jackson sozinho, que é o seguinte código de amostra.
* [cve-2017-7525-poc.groovy](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/blob/master/cve-2017-7525-poc.groovy)

Ao executar especificando a versão 2.8.8 aqui, no ambiente do autor foi gerada a seguinte saída.```
your jackson version MAY NOT BE SAFE to CVE-2017-7525
(...)
Caused by: java.lang.NullPointerException
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)
(...)

cve-2017-7525-check.groovy の時と同様、run()メソッドが走ってNullPointerExceptionが発生しました。ただ、電卓は起動しませんでした。

推測になりますが、xalanのTemplatesImplはJavaの中に入ってるクラスなので、Java側で何かしら修正をしている可能性が考えられます。 あるいは、実際の攻撃成功にはもっとナイーブな条件が必要なのかもしれません。

PoC記事の方では検証に使ったJavaのバージョンまでは示されておらず、電卓を動かすところまで辿り着けませんでした。 追加情報が出たら、また検証してみたいと思います。

Sobre o S2-054

Até agora, começando pelo S2-055, apresentamos principalmente as vulnerabilidades do Jackson CVE-2017-7525 e CVE-2017-15095. Então, sobre o outro S2-054, resumirei os resultados de uma pesquisa superficial sobre a situação.

Para ser direto, no momento da redação deste artigo (03/12/2017), não encontrei informações específicas. Também não encontrei PoCs capazes de testar a existência da vulnerabilidade.

Na página de divulgação de informações do S2-054, é explicado que o plugin REST usa uma biblioteca JSON-lib antiga, e que um JSON adulterado pode permitir um ataque de DoS.

  • https://cwiki.apache.org/confluence/display/WW/S2-054

The REST Plugin is using an outdated JSON-lib library which is vulnerable and allow perform a DoS attack using malicious request with specially crafted JSON payload.

Na página da versão 2.5.14.1 lançada como resposta a este problema, o ticket JIRA correspondente, WW-4892, está vinculado.

  • https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.14.1

Verifiquei o WW-4892, mas não há menção a DoS ou vulnerabilidades do JSON-lib em lugar nenhum. Lendo a "Descrição", parece apenas que, como o JSON-lib está desatualizado e sem manutenção, o handler padrão foi alterado para o Jackson.

  • https://issues.apache.org/jira/browse/WW-4892

O pull request no GitHub é o seguinte, mas também não menciona problemas específicos do JSON-lib.

  • https://github.com/apache/struts/pull/187

Então, decidi dar uma olhada no lado do JSON-lib. O site oficial é o seguinte.

  • http://json-lib.sourceforge.net/

Além disso, em 2017, parece que é gerenciado no GitHub.

  • https://github.com/aalmiray/Json-lib

Qual é o mais recente? No momento da redação deste artigo, não há lançamentos no lado do GitHub. Então, verifiquei a situação do registro no repositório Maven Central. Pesquisando por "json-lib", alguns groupIds são encontrados.

  • http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22json-lib%22

Para confirmar qual groupId está correto, verifiquei o pom.xml do plugin REST do Struts2 2.5.14.1.

  • https://github.com/apache/struts/blob/STRUTS_2_5_14_1/plugins/rest/pom.xml
  • → groupId = net.sf.json-lib, artifactId = json-lib.

Observando as versões lançadas do groupId = net.sf.json-lib, artifactId = json-lib, a versão 2.4 de dezembro de 2010 foi o último lançamento.

  • http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22net.sf.json-lib%22%20AND%20a%3A%22json-lib%22

Verificando a página do sourceforge, parece que também a versão 2.4 de dezembro de 2012 foi o último lançamento.

  • https://sourceforge.net/projects/json-lib/files/json-lib/

Na verdade, no lado do GitHub, embora não haja tags de lançamento, seguindo o histórico de commits, há um commit de lançamento da versão 2.4 em dezembro de 2010. Além disso, desde então, pull requests estão sendo mesclados, mas não houve movimento de lançamento.

Olhando as Issues do lado do GitHub, incluindo as fechadas, não encontrei títulos que sugerissem DoS.

  • https://github.com/aalmiray/Json-lib/issues?utf8=%E2%9C%93&q=is%3Aissue

Olhando os tickets do lado do sourceforge, finalmente encontrei tickets sobre problemas de memory leak. Parece que nenhum foi corrigido ainda.

  • Json-lib / Bugs / #124 memory leak in 2.2.2, not fixed correctly in 2.4
    • https://sourceforge.net/p/json-lib/bugs/124/
  • Json-lib / Bugs / #118 Possible memory leak in Tomcat
    • https://sourceforge.net/p/json-lib/bugs/118/
  • → Entendi que o conteúdo do ticket é que houve um problema de memory leak devido ao uso de ThreadLocal até a versão 2.2, e que na versão 2.4 foi tratado com SoftReference, mas isso não é uma solução fundamental.

Finalmente consegui chegar ao ponto em que parece que ainda existe um problema de memory leak, mas devido à minha capacidade e limitação de tempo, não consegui investigar mais a fundo. Se houver informações concretas de que esse padrão de JSON realmente causou memory leak ou DoS, ficaria muito grato se pudesse me informar.

Referência: Exemplo de resposta do Spring Security (junho de 2017)

Como muitos OSS usam Jackson, existem outras bibliotecas e frameworks afetados por essa vulnerabilidade. Como exemplo, o Spring Security, parte dos produtos Pivotal, foi afetado e as informações foram divulgadas em junho de 2017.

  • CVE-2017-4995: Jackson Configuration Allows Code Execution with Unknown “Serialization Gadgets” | Security | Pivotal
    • https://pivotal.io/security/cve-2017-4995

Quanto a outros, como o próprio Spring Framework, pelo menos em https://pivotal.io/security/ não foram divulgadas informações de atualização provenientes do Jackson.

No entanto, não se pode ficar tranquilo por isso. Originalmente, o design do Jackson no Spring Framework é bastante fácil de personalizar, sendo possível gerar ObjectMapper específicos da aplicação. É melhor verificar se a configuração/funcionalidade do Jackson não foi personalizada no lado da aplicação, ou se @JsonTypeInfo não está sendo usado, por precaução.

Breve resumo cronológico do CVE-2017-7525 e CVE-2017-15095

Organizei em ordem cronológica as Issues/Informações de versão do jackson-databind no GitHub e links de referência como o bugzilla da RedHat. Se houver algum erro, por favor, não hesite em me apontar ou entrar em contato.

2017-04

  • A correção inicial avançou em https://github.com/FasterXML/jackson-databind/issues/1599. Devido a questões de gerenciamento de versão, as seguintes versões foram lançadas como hot-fix.
    • 2.7.9.1: hot-fix para 2.7.9
    • 2.8.8.1: hot-fix para 2.8.8
    • Além disso, 2.9.0.pr3 também foi lançado.

2017-06

  • A versão 2.8.9, incluindo outras correções, foi lançada.
  • O tratamento nos produtos RedHat avançou no seguinte bugzilla.
    • https://bugzilla.redhat.com/show_bug.cgi?id=1462702

2017-07

  • Para a versão 2.6.7, que já não tinha suporte, foi lançada a versão 2.6.7.1 como hot-fix para este problema.
  • A RedHat divulgou informações sobre o CVE-2017-7525.
    • https://access.redhat.com/security/cve/CVE-2017-7525

A lista de black-list neste momento era a seguinte.```java s.add("org.apache.commons.collections.functors.InvokerTransformer"); s.add("org.apache.commons.collections.functors.InstantiateTransformer"); s.add("org.apache.commons.collections4.functors.InvokerTransformer"); s.add("org.apache.commons.collections4.functors.InstantiateTransformer"); s.add("org.codehaus.groovy.runtime.ConvertedClosure"); s.add("org.codehaus.groovy.runtime.MethodClosure"); s.add("org.springframework.beans.factory.ObjectFactory"); s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); s.add("org.apache.xalan.xsltc.trax.TemplatesImpl");

root@kitploit:~
ここで、同月中にblack-list対策の追加修正として 2.9.0 がリリース。
* https://github.com/FasterXML/jackson-databind/issues/1680

これが追加された:```java
s.add("com.sun.rowset.JdbcRowSetImpl");

Ainda no mesmo mês, a seguinte Issue é aberta.

  • https://github.com/FasterXML/jackson-databind/issues/1737

→O seguinte é adicionado à black-list, e isso é incorporado nas versões 2.8.10 / 2.9.1.```java // [databind#1737]; JDK provided s.add("java.util.logging.FileHandler"); s.add("java.rmi.server.UnicastRemoteObject"); // [databind#1737]; 3rd party s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean"); s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource");

root@kitploit:~
### 2017-08

* Lançado 2.8.10 com suporte para #1680, #1737.
* Também em agosto, a seguinte issue foi aberta, e a resposta abrangente como CVE-2017-7525 está sendo discutida.
  * https://github.com/FasterXML/jackson-databind/issues/1723
* No blog de Adam Caudill, uma explicação do exploit para CVE-2017-7525 foi publicada.
  * https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

### 2017-09

* Lançado 2.9.1 com suporte para #1737.

### 2017-10

No bugzilla a seguir, a correção do CVE-2017-7525 nas versões 2.8.9 / 2.9.0 foi considerada insuficiente, e o trabalho para aplicar a blacklist mais recente do 2.8.10 / 2.9.1 como novo CVE-2017-15095 começou.
* https://bugzilla.redhat.com/show_bug.cgi?id=1506612

### 2017-11

* Informações sobre CVE-2017-15095 foram divulgadas pela RedHat.
  * https://access.redhat.com/security/cve/cve-2017-15095

* Na issue do jackson-databind, houve uma troca de perguntas e respostas sobre o status da resposta ao CVE-2017-15095.
  * https://github.com/FasterXML/jackson-databind/issues/1847
  * Foi respondido que o suporte foi feito nas versões 2.8.10 / 2.9.1.

### 2017-12

* Um artigo explicativo foi publicado no blog do desenvolvedor do WAF Scutum na nuvem.
  * https://www.scutum.jp/information/waf_tech_blog/2017/12/waf-blog-052.html
  * Neste artigo, é mencionado que na blacklist do 2.9.3 há uma deficiência na classe do Spring, o que não é um problema emergencial, mas pode haver uma atualização futura.
  * Também é discutido se a responsabilidade por essa vulnerabilidade era realmente da biblioteca ou da aplicação.

## Sobre as tendências futuras de vulnerabilidades relacionadas a serialize/deserialize em Java

Tenho a impressão de que as informações sobre vulnerabilidades relacionadas a serialize/deserialize em Java aumentaram desde o ano retrasado até o ano passado.
Como exemplo, as informações de vulnerabilidade dos produtos Pivotal, incluindo Spring, são divulgadas em https://pivotal.io/security/, e de fato, em 2017, além do CVE-2017-4995, as seguintes informações de vulnerabilidade foram divulgadas.

* https://pivotal.io/security/cve-2017-8045
  * RCE devido a problema de desserialização de `org.springframework.amqp.core.Message` no Spring AMQP
* https://pivotal.io/security/cve-2017-8046
  * RCE devido a falha no tratamento de JSON no método PATCH do Spring Data REST

Por ser uma vulnerabilidade que facilmente leva a RCE, acredita-se que tanto atacantes quanto pesquisadores de vulnerabilidades estejam prestando atenção ao serialize/deserialize em Java.
Acredito que nos próximos anos continuarão a surgir relatos de vulnerabilidades relacionadas ao processo de serialize/deserialize.
No entanto, embora o Jackson também seja assim, na realidade, em muitos ambientes de desenvolvimento atuais, onde a eficiência do desenvolvimento é aumentada e a troca de dados via APIs remotas se tornou comum, é praticamente impossível não usar serialize/deserialize ou criá-los do zero.
O importante, na minha opinião pessoal, é criar uma cultura e um ambiente de desenvolvimento ágeis, que permitam atualizar as bibliotecas o mais rápido possível quando uma vulnerabilidade for divulgada.

Como tenho sentimentos sobre como lidar com vulnerabilidades em middleware, bibliotecas e frameworks dos quais dependemos, escrevi o seguinte como reflexão.

## Reflexão

Quando vi as informações de que S2-054, 055 foram divulgadas e que a vulnerabilidade do Jackson as afetava, fiquei bastante chocado.
Isso porque, alguns dias antes, um colega me perguntou: "Qual biblioteca você recomenda para parsear JSON em Java?" e eu respondi com ar de sabedoria: "O Jackson é amplamente usado em OSS e tem um histórico comprovado; se você pesquisar, encontrará muitos artigos e Q&As, então recomendo."

Eu mesmo usava o Jackson em ferramentas internas da empresa e o achava prático.
No entanto, naquela época, eu não tinha conhecimento do CVE-2017-7525 e estava confiante de que o Jackson, por ser amplamente usado em OSS e por muitos usuários, era seguro.

Foi então que outro colega encontrou o blog de Adam Caudill e me informou sobre a existência do CVE-2017-7525. Poucos dias depois de eu ter recomendado o Jackson com ar de sabedoria, uma vulnerabilidade do Jackson levou a uma atualização do Struts2, e a vulnerabilidade do Jackson em si já havia sido tratada meses antes. Como engenheiro na área de segurança, não teria como negar que negligenciei a coleta de informações sobre vulnerabilidades da biblioteca que eu mesmo usava (na verdade, só posso dizer que foi exatamente isso).

Portanto, meu estado mental nos últimos dias estava péssimo (aumento de pressão arterial e pulso, mãos trêmulas, lágrimas querendo sair mesmo sem tristeza, palpitações incessantes, etc.). Para lidar com isso, decidi primeiro entender o que era o CVE-2017-7525 e qual era a situação do Jackson, e dediquei o fim de semana para pesquisar e escrever este artigo.

Refletindo sobre isso, sinto profundamente que, quando se está focado no desenvolvimento, é realmente difícil prestar atenção às informações de atualização das bibliotecas dependentes.
Em meio a tarefas de desenvolvimento que surgem uma após a outra, é praticamente impossível investigar completamente todas as funcionalidades e aspectos de qualidade, como vulnerabilidades, de todas as bibliotecas usadas.
Por outro lado, as funcionalidades exigidas no desenvolvimento são cada vez maiores, e criar tudo do zero também é praticamente impossível.
Em algum momento, é preciso "confiar" nas bibliotecas usadas para tornar o desenvolvimento mais eficiente.
No entanto, monitorar todas as informações de atualização das ferramentas e bibliotecas usadas no desenvolvimento diário e verificar se há correções de segurança também é extremamente difícil.
Claro, reconheço que atualmente existem serviços que, ao cadastrar as ferramentas e bibliotecas utilizadas, distribuem informações de atualização para resolver esse problema.

O que percebi com a piora do meu estado mental foi que tenho um forte "sentimento de autocobrança e culpa por não ter feito algo".
Eu estava me rotulando negativamente: "Sou engenheiro de segurança e não estava ciente das informações de vulnerabilidade da biblioteca que eu mesmo usava..."
Mesmo para desenvolvedores comuns que não estão envolvidos na indústria de segurança,
muitos podem estar carregando arrependimentos e ansiedades como "Se eu não tivesse sugerido o Struts2 naquela época..." ou "Preciso gerenciar melhor o ciclo de vida das bibliotecas/frameworks (= estou preocupado comigo mesmo/a situação atual em que não consigo fazer isso)".

Se tentássemos "resolver" esses problemas de frente, teríamos que coletar informações de vulnerabilidade uma a uma, verificar o código-fonte e as funcionalidades de cada biblioteca ou framework que pretendemos usar, investigar minuciosamente se são padrões de fato e, após o início da operação, gerenciar rigorosamente o ciclo de vida.

No entanto, será que essa abordagem de "bater na pedra antes de atravessar a ponte" é realmente possível nos diversos ambientes de desenvolvimento atuais?

Ao escrever este artigo, pensei que a era de tratar "o que não foi feito / o que não foi possível fazer / o que não foi percebido" como causa ou culpado, e eliminá-lo = "torná-lo possível" como a única "solução do problema" já acabou.
Nessa cultura, a menos que se seja uma pessoa perfeita, o desenvolvedor terá que lidar eternamente com seu "não feito, não possível, não percebido".
Como não existem pessoas perfeitas, acho que só pessoas com uma mente muito forte conseguiriam suportar isso.

Em problemas de segurança de software, o verdadeiro causador do dano é o atacante. Quem torna a situação negativa é o atacante que explora a vulnerabilidade.

A grande maioria dos desenvolvedores, em princípio, trabalha com boa vontade e seriedade no desenvolvimento. Já nesse ponto, a situação é positiva.
"Não gerenciar o ciclo de vida das bibliotecas/frameworks" ou "não coletar/monitorar informações de vulnerabilidade das bibliotecas usadas" é apenas algo que não foi feito, nem positivo nem negativo.
No entanto, com a existência de atacantes, transformar "o que não foi feito" em "o que não foi possível/não foi percebido" como algo negativo, não é uma situação muito triste?

Não se pode negar que a visão de "bater na pedra antes de atravessar a ponte" é influenciada pela sociedade e cultura empresarial japonesa moderna.
Casos em que vulnerabilidades como injeção SQL foram introduzidas e causaram danos por atacantes continuam ocorrendo, e há casos em que a responsabilidade da empresa desenvolvedora é questionada em tribunal.
Também há casos em que a falta de cuidado no trabalho leva a grandes acidentes.

No entanto, se todos esses problemas forem tratados como "problemas da empresa desenvolvedora/desenvolvedor", acredito que o desenvolvimento de TI como um todo se encolherá.
Quem realmente é mau é o atacante que explora as vulnerabilidades.
Pensando assim, o desenvolvedor ou empresa desenvolvedora que "não fez / não foi possível / não percebeu" não seria mais uma vítima do que um agressor?
Se for assim, em vez de apontar "você é culpado por não ter feito / não ter sido possível / não ter percebido", acho importante estender uma mão amigável com o objetivo de caminharmos juntos, dizendo "assim fica mais seguro, podemos melhorar, vamos nos esforçar juntos", e mutualmente aprimorarmos e aproveitarmos nossas respectivas áreas de especialização.
Dessa forma, a empresa desenvolvedora/desenvolvedor pode lidar com as vulnerabilidades com tranquilidade e, depois disso, desenvolver ativamente com base na confiança.
Com ambientes de desenvolvimento seguros, alegres e cada vez mais proativos, acredito que resultados inovadores aumentarão e a sociedade japonesa se tornará mais rica.

Pessoalmente, sinto fortemente que seria bom se as seguintes ideias se difundissem no futuro.

* Desenvolvedores de campo
  * "Ter usado uma biblioteca com vulnerabilidade" não é negativo por si só.
  * Quem torna negativo é o atacante que explora a vulnerabilidade, e a própria cultura que avalia isso como negativo.
  * O fato de trabalhar seriamente no desenvolvimento todos os dias já é suficientemente positivo.
  * Lidar com vulnerabilidades não é uma tarefa de trazer algo negativo de volta a zero, mas sim um trabalho positivo para melhorar os resultados diários do desenvolvimento, tornando-os mais seguros.
* Gerentes, líderes e executivos que coordenam desenvolvedores
  * Não avaliar negativamente "o que não foi feito / não foi possível / não foi percebido". Esse tipo de visão irá desaparecendo gradualmente.
  * Parar de tratar membros que "não fizeram / não foram capazes / não perceberam" como culpados. Eles, e todos nós, somos vítimas dos atacantes que exploram as vulnerabilidades; nesse aspecto, estamos na mesma posição.
  * Parar de tentar resolver com "medidas perfeitas".

Acaba sendo um tema de "mudar a forma de ver e interpretar as coisas", envolvendo desenvolvedores, gerentes, líderes e até a alta administração, mas é claro que isso é extremamente difícil.
Afinal, como mudar?
Eu mesmo não tenho capacidade para dar a resposta correta, mas acho que há uma dica nisso.
Ou seja, talvez tenhamos que desistir de procurar a resposta correta em si.
Todo desenvolvimento de software tem algum propósito. Será que o mundo do software não se tornou tão complexo que agora é praticamente impossível buscar a "resposta correta" para realizá-lo de forma segura?
Provavelmente, sinto que o que existe é um paradigma de desenvolvimento que pressupõe "mudança", onde vários jogadores tentam, erram, obtêm feedback, trocam informações entre si e, a partir disso, se ramificam e mudam livremente.

No desenvolvimento de sistemas, os ativos de software criados uma vez são usados por vários anos, às vezes décadas.
No entanto, softwares conectados à internet, como o desenvolvimento web, ficam expostos a ambientes que mudam em meses ou anos.
Bibliotecas e frameworks usados no desenvolvimento de 5 anos atrás podem não ser mais utilizáveis.
Nesse caso, considerar a biblioteca/framework criado inicialmente como "correto" e "fixar" a versão em um paradigma de desenvolvimento traz mais desvantagens.
O mundo exterior está mudando constantemente, então é normal encontrar vulnerabilidades nas bibliotecas/frameworks que usamos.
Fixar a versão impede acompanhar essas mudanças, resultando em altos custos mentais e físicos para lidar com vulnerabilidades.
Portanto, sinto fortemente que mudar para um paradigma de desenvolvimento que pressupõe "mudar e ser capaz de acompanhar as mudanças" levará a melhores resultados a longo prazo.

Ficou longo, mas é isso.

----
Responsável: Masahiko Sakamoto (Pesquisa e Desenvolvimento, envolvido no desenvolvimento de ferramentas de diagnóstico para aplicações web internas)
* E-mail: [email protected]
* Twitter: https://twitter.com/msakamoto_sf
* Facebook: https://www.facebook.com/masahiko.sakamoto.75
* GitHub: https://github.com/msakamoto-sf

Comentários e perguntas sobre este artigo devem ser enviados ao Sakamoto.
Baixar ferramenta