
Struts2の脆弱性S2-045, S2-055 および Jackson の脆弱性 CVE-2017-7525, CVE-2017-15095 の調査報告
Un article de synthèse résumant les points essentiels et facile à lire a été publié. Recommandé à ceux qui veulent un aperçu ou qui manquent de temps.
Le 1er décembre 2017, une mise à jour de sécurité pour Struts2 a été publiée. Avant la publication, des discussions circulaient sur la liste de diffusion concernant le lien avec une vulnérabilité de Jackson (une bibliothèque JSON populaire en Java). L'auteur, qui utilise Jackson dans des systèmes et outils internes, s'intéressait également au contenu précis.
En réalité, les deux problèmes de sécurité suivants ont été corrigés dans la publication. Seule la vulnérabilité S2-055 est affectée par la vulnérabilité de jackson-databind, un composant de Jackson.
Dans le plugin REST, il semble que les gestionnaires utilisant JSON-lib et ceux utilisant Jackson étaient déjà intégrés, permettant à l'utilisateur de choisir. La correction dans son ensemble semble être : dans S2-054, le gestionnaire par défaut a été changé pour Jackson, et dans S2-055, la version obsolète de Jackson a été mise à jour vers la dernière.
Alors, quelle est exactement la vulnérabilité CVE-2017-7525 ? L'auteur, qui utilise habituellement Jackson pour le traitement JSON en Java, a passé le week-end des 2 et 3 décembre à étudier ce problème, ce qui fait l'objet de cet article.
Environnement de l'auteur utilisé pour la vérification du code d'exemple :
Une explication de CVE-2017-7525 a été publiée sur le blog d'Adam Caudill.
En résumé avec mes propres mots : jackson-databind fournit une fonctionnalité (classe ObjectMapper) pour mapper du JSON vers des objets Java.
En appelant ObjectMapper.enableDefaultTyping(), il devient possible de mapper en utilisant un nom de classe intégré arbitrairement dans le JSON.
Certains d'entre vous ont peut-être eu un mauvais pressentiment en lisant « possibilité de spécifier un nom de classe depuis le JSON d'entrée », et c'est exactement ce mauvais pressentiment qui s'est réalisé avec CVE-2017-7525.
Avant d'entrer dans l'explication de la vulnérabilité, je vais d'abord expliquer pourquoi une telle fonctionnalité a été implémentée.
ObjectMapper.enableDefaultTyping()Veuillez consulter le code d'exemple suivant pour l'utilisation de base de la désérialisation par jackson-databind. (Dans cet article, j'utilise Groovy pour les exemples de code Jackson. @Grab permet de changer facilement la version de jackson-databind.)
Dans le code d'exemple ci-dessus, la clé "animal" peut simplement être mappée directement à la classe Animal. Que se passe-t-il dans le cas suivant ?```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() { } }
Dans cette configuration, il y a deux cas : le contenu de la clé "animal" fait référence à la classe Dog ou à la classe Cat. Par conséquent, des informations supplémentaires sont nécessaires pour savoir avec quelle classe mapper.
Pour résoudre ce problème, jackson-databind a intégré un traitement personnalisé permettant d'incorporer le nom de la classe à mapper dans le JSON.
Par exemple, comme ci-dessous, le contenu de la clé "animal" est transformé en tableau, et le premier élément spécifie le nom de la classe.```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}
Cela permet à ObjectMapper.readValue() de reconnaître que le contenu de la clé "animal" est de la classe Dog et d'effectuer le mappage en conséquence.
Bien sûr, il n'est pas possible de distinguer si le contenu de la clé "animal" était à l'origine un tableau ou s'il contient des informations de nom de classe propres à jackson-databind.
C'est la méthode ObjectMapper.enableDefaultTyping() qui permet de basculer entre ces deux cas.
Il existe également une autre méthode consistant à définir l'annotation @JsonTypeInfo sur la classe. Pour plus de détails, consultez la documentation Jackson suivante :
Voici un exemple de code utilisant réellement la méthode ObjectMapper.enableDefaultTyping().
Comme nous l'avons vu ci-dessus, en donnant un nom de classe suivi de ses propriétés en JSON, il est possible, bien qu'avec certaines limitations, de créer une instance de n'importe quelle classe avec des propriétés arbitraires.
C'est cette exploitation qui est à l'origine de la vulnérabilité CVE-2017-7525, et le rapport suivant en est probablement à l'origine :
Un rapport a signalé que des bibliothèques de sérialisation/désérialisation Java couramment utilisées, telles que Jackson, présentent un risque d'exécution de code arbitraire par manipulation des noms de classe, et une liste de noms de classes spécifiques potentiellement dangereuses a été dressée.
On ne sait pas si c'est en réaction à cela, mais peu de temps après le premier commit du dépôt ci-dessus, le problème suivant a été soumis sur jackson-databind et la correction a commencé :
À quoi ressemblent concrètement les données JSON et le code Java exploitant cette vulnérabilité ?
Le code de test de jackson-databind 2.8.9, qui corrige ce problème, fournit un indice :
Basé sur ce code de test, voici un exemple de code ajusté pour permettre une vérification fonctionnelle :
Si vous exécutez avec @Grab en spécifiant la version 2.8.9, le message your jackson version IS SAFE to CVE-2017-7525 s'affiche. Cela est dû à l'ajout d'une inspection de liste noire sur les noms de classe instanciés, introduite par la correction de la version 2.8.9.
En spécifiant la version 2.8.8 avec @Grab, la sortie est la suivante :```
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
Dans la sortie, il y a une ligne `at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)`.
Dans cet exemple de code, une NullPointerException est levée, mais d'après le nom de la méthode, on peut deviner qu'un traitement avec des effets secondaires se produit.
Pour construire un JSON qui permette réellement l'exécution de code, des recherches supplémentaires sont nécessaires.
Cet article se limite à cette présentation pour l'instant, mais si d'autres articles de recherche sont publiés sur d'autres sites, je souhaiterais les ajouter ici.
D'ailleurs, où est implémentée la liste noire tant attendue ? C'est dans la classe suivante :
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L51
En fait, il semble que la version 2.8.9 présentait des lacunes dans cette liste noire. Ce problème est référencé sous CVE-2017-15095.
### Correction de CVE-2017-15095 améliorant la liste noire
L'amélioration des lacunes de la liste noire a d'abord consisté à ajouter `s.add("com.sun.rowset.JdbcRowSetImpl");` dans https://github.com/FasterXML/jackson-databind/issues/1680.
Après la sortie de la version 2.9.0 avec ce correctif, une vérification supplémentaire de la liste noire a été ajoutée dans https://github.com/FasterXML/jackson-databind/issues/1737.```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");
Ainsi, les versions 2.8.10 / 2.9.1 ont été publiées et le correctif pour CVE-2017-15095 est terminé.
Code de test pour vérifier le fonctionnement de la liste noire dans 2.8.10 :
Sur la base de ce code de test, voici un exemple de code adapté pour vérifier le fonctionnement :
Si vous exécutez la version 2.8.10, qui est censée avoir le correctif, en la spécifiant avec @Grab, le message your jackson version IS SAFE to CVE-2017-15095 s'affiche.
Ensuite, en exécutant la version 2.8.9, avant l'amélioration de la liste noire, avec @Grab, on obtient la sortie suivante :```
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
Dans la version antérieure au correctif, le nom de classe `java.util.logging.FileHandler` contourne la vérification de la liste noire, et en étant instancié, on voit qu'il tente effectivement d'ouvrir un fichier.
Dans la version corrigée, il est attrapé par la vérification de la liste noire et une exception `JsonMappingException` est levée.
La liste noire au moment de la version 2.8.10 est la suivante. Ce qui commence par le commentaire `[databind#1737]` correspond à la liste noire supplémentaire pour 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
### Conditions d'exposition à la vulnérabilité, degré de réalisation de l'attaque, et mesures côté application
En résumé, pour être affecté par la vulnérabilité de jackson-databind, les conditions suivantes sont nécessaires :
1. Utiliser jackson-databind 2.8.9 / 2.9.0 ou inférieur.
2. Pour du JSON provenant d'une source non fiable, effectuer l'un des traitements suivants :
* Appeler `ObjectMapper.enableDefaultTyping()` avant de désérialiser.
* Ne pas appeler `ObjectMapper.enableDefaultTyping()` mais utiliser l'annotation `@JsonTypeInfo` dans la déclaration de classe pour permettre le mapping, puis désérialiser.
* Même si le code de l'application ne l'utilise pas, le framework peut automatiquement désérialiser en fonction de l'en‑tête `Accept` de la requête ou de l'extension de l'URL.
3. Inclure dans le classpath une classe ("Gadget") potentiellement exploitable par des vulnérabilités de sérialisation/désérialisation Java.
4. Utiliser dans les champs membres de la classe Java de mappage un type qui peut accepter une classe Gadget, comme `Object`.
* Si le type est une classe Bean spécifique à l'application incompatible avec les classes utilisées pour les Gadget, il est possible de bloquer avant la création d'instance par une erreur de vérification de type. (sauf si la classe Bean elle-même recèle une vulnérabilité de désérialisation)
La question de savoir si l'on est réellement affecté dépend fortement du code de l'application : utilisation/configuration de `ObjectMapper`, combinaisons avec l'annotation `@JsonTypeInfo`, champs membres de la classe de mappage, etc.
De plus, si une clé dans le JSON n'existe pas dans la classe Java de destination, Jackson l'ignore simplement.
Par conséquent, pour qu'une attaque réussisse, il faut une adaptation au JSON de chaque application, ce qui rend très difficile la création d'un code d'attaque réutilisable sur plusieurs applications.
En ce qui concerne la condition 4, dans une écriture normale, on ne définit généralement pas un champ de classe Java en tant que `Object`.
Les classes permettant l'exécution de code arbitraire sont aussi, dans la grande majorité des cas, incompatibles avec les classes Bean créées par l'application.
Ainsi, la probabilité qu'une attaque de grande ampleur se produise ou que la vulnérabilité soit effectivement exploitée pour causer des dommages (c'est-à-dire que l'attaque réussisse) semble faible.
Côté application, pour la condition 3, les classes incluses dans le JDK peuvent également être exploitées, il est donc pratiquement impossible d'y remédier.
Par conséquent, la mesure de base consiste à mettre à jour jackson-databind vers la version la plus récente.
Si la mise à jour de jackson-databind n'est pas possible, il faudra supprimer l'appel à `ObjectMapper.enableDefaultTyping()` et/ou l'annotation `@JsonTypeInfo`, et modifier la conception pour ne plus en dépendre. Par exemple, créer un sérialiseur personnalisé.
Cependant, si l'on a déjà commencé à l'utiliser comme API appelable à distance, on ne peut pas modifier le format JSON aisément.
Concernant l'annotation `@JsonTypeInfo`, il semble que selon la configuration, on puisse limiter les sous-classes et n'accepter que les noms de classes prévus par le programmeur.
Veuillez consulter la documentation suivante pour plus de détails.
* JacksonPolymorphicDeserialization
* https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
#### À propos de la pertinence de la contre-mesure par liste noire et de la création d'un désérialiseur personnalisé
jackson-databind 2.8.10 / 2.9.1 a corrigé CVE-2017-7525 et CVE-2017-15095 via une liste noire.
Cependant, comme le montrent les problèmes liés à OGNL dans Struts2, la contre-mesure par liste noire n'est pas infaillible.
(À titre personnel, je pense que c'est une mesure relativement efficace contre les "script kiddies" qui se contentent d'utiliser des outils de scan.)
Par conséquent, pour une véritable mesure radicale, l'auteur estime qu'il est important de désactiver/ne pas utiliser les fonctionnalités qui intègrent des informations de classe dans le JSON, comme `ObjectMapper.enableDefaultTyping()`.
Mais alors, comment résoudre le problème que `ObjectMapper.enableDefaultTyping()` était censé résoudre ?
L'auteur n'a pas lui-même de solution qu'il puisse qualifier de bonne.
Pour l'essentiel, le problème est de pouvoir mapper sans se fier à un JSON non fiable lorsque la classe Java de mappage est ambiguë.
L'auteur pense que l'approche pour y parvenir pourrait être de créer un désérialiseur personnalisé.
Un désérialiseur personnalisé permet de recevoir le JSON pendant la désérialisation et de contrôler l'objet généré via le code.
Par exemple, si l'on reçoit `{"animal":{"name":"dog1","barkVolume":1.2}}`, on peut faire en sorte que le programme décide : « il y a la clé `barkVolume`, donc on instancie la classe Dog ».
Si l'on reçoit `{"animal":{"name":"cat1","likesCream":true,"lives":10}}`, on peut décider : « il y a les clés `likesCream` et `lives`, donc on instancie la classe Cat ».
Cela évite d'avoir à intégrer le nom de classe dans le JSON.
Personnellement, j'ai eu l'impression que le format JSON intégrant le nom de classe nuit à l'interopérabilité avec d'autres langages/bibliothèques (si quelqu'un connaît des extensions similaires dans d'autres langages ou bibliothèques, merci de me le dire).
Dans l'hypothèse d'une interopérabilité avec d'autres systèmes, il me semble plus judicieux de créer un désérialiseur personnalisé côté Jackson plutôt que d'obliger les autres à intégrer un nom de classe propre à Jackson.
Il existe probablement d'autres solutions ; si les lecteurs ont des idées de solutions alternatives, je serais ravi de les recevoir.
(Un exemple extrême serait de ne pas mapper vers des classes spécifiques mais de tout désérialiser sous forme de `Map<String, Object>` ou `List<String, Object>`.)
J'ai trouvé quelques articles de référence pour créer un désérialiseur personnalisé ; ce sont des articles en anglais, je mets les liens.
* 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 de jackson-databind (séries 2.8 et 2.9) :
* https://fasterxml.github.io/jackson-databind/javadoc/2.8/
* https://fasterxml.github.io/jackson-databind/javadoc/2.9/
L'auteur a également créé un exemple de code pour un désérialiseur personnalisé ; j'espère que cela pourra vous donner des pistes.
* [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)
## À propos de S2-055
Jusqu'ici, nous avons examiné les vulnérabilités de Jackson lui-même. Comment cela affecte-t-il concrètement le plugin REST de Struts2 ? Nous avons vérifié en utilisant struts2-rest-showcase fourni avec Struts2.
Les instructions d'utilisation du plugin REST Struts se trouvent ici :
* http://struts.apache.org/plugins/rest/
### Le plugin REST Struts2 n'appelle pas ObjectMapper.enableDefaultTyping()
Par ailleurs, les conditions pour être vulnérable à CVE-2017-7525 étaient les suivantes :
* Pour du JSON provenant d'une source non fiable, effectuer l'un des traitements suivants :
* Appeler `ObjectMapper.enableDefaultTyping()` avant de désérialiser.
* Ne pas appeler `ObjectMapper.enableDefaultTyping()` mais utiliser l'annotation `@JsonTypeInfo` dans la déclaration de classe pour permettre le mapping, puis désérialiser.
Après avoir vérifié si le plugin REST Struts2 contenait du code satisfaisant ces conditions, nous avons confirmé qu'aucun des deux n'était présent.
En réalité, même dans la version 2.5.14 avant correctif, ni `ObjectMapper.enableDefaultTyping()` ni `@JsonTypeInfo` n'étaient utilisés, ni dans le plugin REST lui-même, ni dans l'ensemble de l'arborescence source de Struts2 après une recherche grep.
* https://github.com/apache/struts/tree/STRUTS_2_5_14
Dans toute l'arborescence source de Struts2, la seule classe qui utilise ObjectMapper de Jackson est `org.apache.struts2.rest.handler.JacksonLibHandler`. En vérifiant le code source, on constate qu'à la version 2.5.14, `ObjectMapper.enableDefaultTyping()` n'est effectivement pas utilisé.
* https://github.com/apache/struts/blob/STRUTS_2_5_14/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonLibHandler.java
* Ce fichier Java n'a pas changé non plus dans la version 2.5.14.1.
Par conséquent, le plugin REST lui-même n'était pas vulnérable à CVE-2017-7525 même à la version 2.5.14.
Il devient vulnérable uniquement lorsque l'application côté client définit l'annotation `@JsonTypeInfo` sur les champs de la classe de mappage JSON.
Ainsi, dans les tests suivants avec struts2-rest-showcase, nous avons défini `@JsonTypeInfo` sur les champs de mappage ajoutés du côté de l'application pour les tests.
Accessoirement, Struts2 dispose également d'un plugin JSON.
* http://struts.apache.org/plugins/json/
* En regardant le source du plugin JSON, on voit que le `pom.xml` n'inclut aucune dépendance vers d'autres bibliothèques JSON.
* Il semble que l'implémentation JSON soit faite en interne.
* https://github.com/apache/struts/tree/STRUTS_2_5_14/plugins/json
* Par conséquent, la vulnérabilité de jackson-databind n'affecte pas le plugin JSON.
### Adaptation de struts2-rest-showcase à Jackson
struts2-rest-showcase est un exemple implémentant le CRUD de la classe Order à l'aide du plugin REST. Nous y avons ajouté les classes Zoo / Animal / Cat / Dog utilisées dans le code d'exemple de la vulnérabilité Jackson, ainsi que ZooController pour traiter leur CRUD en JSON.
Le code source complet se trouve ici : (la construction et l'exécution ont été vérifiées avec JDK8 dans cet article)
* [rest-showcase](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/tree/master/rest-showcase)
Principales modifications :
* Changement du port d'écoute du plugin jetty-maven-plugin à 18088. (`mvn jetty:run`)
* Ajout des dépendances jackson-core et jackson-databind.
* Ajout des classes Zoo, Animal (abstraite), Dog, Cat. Ajout de la classe ZooService comme couche de service.
* Ajout de ZooController avec le CRUD minimal. (les JSP de vue sont omises)
* Modification du gestionnaire JSON dans struts.xml pour utiliser JacksonLibHandler.
* Intégration de maven-wrapper pour que la construction et l'exécution puissent se faire directement avec `mvnw` / `mvnw.bat` à condition que JDK soit installé.
Construction et exécution :
1. Après avoir cloné le dépôt, placez-vous dans le répertoire rest-showcase et exécutez `mvnw jetty:run`. (Attention : lors de la première exécution, le téléchargement de Maven peut prendre quelques minutes, voire plus de 10 minutes dans certains cas.)
1. Accédez à http://localhost:18088/struts2-rest-showcase/ ; si la liste des Orders s'affiche, c'est réussi.
1. Pour arrêter l'exécution, utilisez Ctrl-C.
1. Si vous modifiez un fichier Java, arrêtez avec Ctrl-C puis relancez `mvnw jetty:run`.
Vérification avec la commande curl : (en supposant que localhost:8080 sert de proxy HTTP local)```
一覧取得:
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
Dans le fichier Zoo.java du dépôt, le champ animal est de type Animal (classe abstraite) avec @JsonTypeInfo commenté, comme ci-dessous :```java
//@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
public Animal animal;
//public Object animal;
Ici, essayons d'envoyer une requête JSON avec la méthode POST et d'appeler la méthode 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}}'
Alors une exception contenant le message d'erreur suivant s'est produite. La classe Animal étant abstraite, une instance n'a pas pu être créée.``` 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
そこで `animal` フィールドの `@JsonTypeInfo` のコメントアウトを外して有効化します。Webアプリケーションは Ctrl-C で中止し、もう一度 `mvnw jetty:run` を実行します。```java
// 次のimportを忘れずに追加
import com.fasterxml.jackson.annotation.JsonTypeInfo;
//...
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
public Animal animal;
//public Object animal;
Cela permet d'incorporer le nom de la classe dans le JSON. Essayez de POSTer le JSON avec le nom de la classe incorporé en utilisant la commande curl suivante.``` 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}]}'
→ `HTTP/1.1 201 Created` est retourné. En effectuant une requête de liste, on peut confirmer que l'élément a bien été ajouté.
### Vérification de CVE-2017-7525 avec Struts2 REST plugin 2.5.14
Dans le pom.xml du dépôt, comme le parent utilise l'artifact struts avec la version 2.5.14, il est vulnérable à CVE-2017-7525 tel quel. Pour le vérifier, exécutez la commande curl suivante. Les noms de classe et leur contenu sont basés sur cve-2017-7525-check.groovy ; donc si la même réponse que pour jackson-databind 2.8.8 est obtenue, on considère qu'il est vulnérable.```
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":{}}]}'
→ Une exception a été levée contenant le message d'erreur suivant :``` java.lang.IllegalArgumentException: Class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl not subtype of [simple type, class org.demo.rest.example.Animal]
Il semble que l'`IllegalArgumentException` se soit produite parce que le type du champ `animal` est la classe `Animal`, qui n'est pas un sous-type de la classe `com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl`.
Alors, modifions le champ `animal` dans `Zoo.java` pour qu'il soit de type `Object` et exécutons à nouveau avec `mvnw jetty:run`.```java
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
//public Animal animal;
public Object animal;
Ainsi, en exécutant à nouveau la commande curl précédente, une exception contenant la trace de pile suivante s'est produite.``` Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) ~[?:1.8.0_92]
Ceci est la même exception que lors de la vérification avec cve-2017-7525-check.groovy, indiquant une vulnérabilité.
De ce qui précède, nous avons pu confirmer la présence de la vulnérabilité CVE-2017-7525 de jackson-databind dans le plugin REST Struts2 2.5.14.
Nous avons également constaté qu'il est nécessaire d'utiliser le type Object en plus de `@JsonTypeInfo`.
Voici un avis personnel de l'auteur : dans les classes de données pour la création d'API REST, il ne semble pas courant de spécifier délibérément comme type de champ la classe Object ou une classe compatible avec les classes pouvant être utilisées comme gadgets dans les vulnérabilités de désérialisation Java. Par conséquent, je pense qu'il est difficile de réussir réellement une attaque.
### Vérification de la correction dans le plugin REST Struts2 2.5.14.1
Voyons donc si la vulnérabilité a été corrigée dans la version 2.5.14.1.
Modifions la version de l'artefact `<parent>` dans pom.xml en 2.5.14.1, redémarrons avec `mvnw jetty:run`, puis exécutons la même commande curl que précédemment.```
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":{}}]}'
→ Une exception contenant le message d'erreur suivant a été levée.```
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
C'est la même exception après la correction de la vulnérabilité, comme lors de la vérification avec cve-2017-7525-check.groovy.
Si vous ouvrez le projet dans un IDE compatible Maven comme Eclipse et que vous regardez la version de jackson-databind après résolution des dépendances, vous devriez confirmer qu'elle est bien 2.9.2. Si vous n'avez pas d'IDE, vous pouvez exécuter `mvnw help:effective-pom` pour afficher le pom final, puis y chercher jackson-databind pour confirmer que la version 2.9.2 est utilisée.
Je passe sur CVE-2017-15095, mais à partir de ce qui précède, j'ai confirmé que la vulnérabilité de jackson-databind a pu être corrigée avec la version 2.5.14.1.
### PoC pour S2-055
※ Ajout le 2017-12-08
Des articles d'enquête et des rapports de PoC sur S2-055 ont été publiés.
* S2-055漏洞环境搭建与分析 | 绿盟科技博客
* http://blog.nsfocus.net/s2-055/
En lisant à l'aide de Google Traduction, il semble que les avis soient les mêmes concernant les conditions d'occurrence et la faisabilité de l'attaque.
Un PoC modifiant réellement rest-showcase et démarrant la calculatrice via une communication HTTP a également été présenté.
J'ai emprunté uniquement la partie JSON et l'ai testée d'abord avec Jackson seul, ce qui donne l'exemple de code suivant.
* [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)
En exécutant avec la version 2.8.8 spécifiée, voici ce qui s'est affiché dans l'environnement de l'auteur :```
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)
(...)
Comme pour cve-2017-7525-check.groovy, la méthode run() s'est exécutée et une NullPointerException a été déclenchée. Cependant, la calculatrice n'a pas démarré.
C'est une supposition, mais comme TemplatesImpl de xalan est une classe incluse dans Java, il est possible que des correctifs aient été apportés du côté de Java. Ou peut-être que des conditions plus naïves sont nécessaires pour que l'attaque réussisse réellement.
L'article PoC n'indiquait pas la version de Java utilisée pour la validation, et je n'ai pas pu aller jusqu'à faire fonctionner la calculatrice. Si des informations supplémentaires sont publiées, je souhaiterais revalider.
Jusqu'à présent, à partir de S2-055, j'ai surtout présenté les vulnérabilités Jackson CVE-2017-7525 et CVE-2017-15095. Maintenant, je résume brièvement les résultats de mes recherches sur l'autre, S2-054.
Pour conclure, à la date de rédaction de cet article (2017-12-03), je n'ai trouvé aucune information concrète. Je n'ai pas non plus trouvé de PoC permettant de vérifier la présence ou non de la vulnérabilité.
La page de divulgation publique de S2-054 explique que le plugin REST utilise une ancienne bibliothèque JSON-lib et qu'une attaque DoS est possible via un JSON falsifié.
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.
Sur la page de la version 2.5.14.1 publiée pour répondre à ce problème, le ticket JIRA correspondant WW-4892 est lié.
J'ai vérifié WW-4892, mais il n'y a aucune mention de DoS ou de vulnérabilité JSON-lib nulle part. Même en lisant la "Description", on dirait qu'il est seulement écrit que JSON-lib est ancien et non maintenu, donc on change le handler par défaut pour Jackson.
La pull request côté GitHub est la suivante, mais elle non plus ne mentionne pas de problème spécifique avec JSON-lib.
J'ai donc décidé de regarder du côté de JSON-lib. Le site officiel est le suivant :
De plus, en 2017, il semble être géré sur GitHub.
Lequel est le plus récent ? Au moment de la rédaction de cet article, il n'y a pas de release côté GitHub. Je vais donc vérifier l'état d'enregistrement dans le dépôt Maven Central. En recherchant 'json-lib', plusieurs groupId sont trouvés.
Pour savoir quel groupId est correct, je vérifie le pom.xml du plugin REST de Struts2 2.5.14.1.
En regardant les versions de release de groupId = net.sf.json-lib, artifactId = json-lib, la version 2.4 de décembre 2010 est la dernière release.
En vérifiant la page sourceforge, là aussi la version 2.4 de décembre 2012 est la dernière release.
En fait, côté GitHub, il n'y a pas de tag de release, mais en suivant le journal des commits, il y a un commit de release de la version 2.4 en décembre 2010. Après cela, les pull requests sont fusionnées, mais il n'y a pas eu de mouvement de release.
En regardant les issues côté GitHub, y compris les fermées, aucun titre ne semble lié à un DoS.
En regardant les tickets côté sourceforge, j'ai enfin rencontré des tickets sur le problème de memory leak. Aucun ne semble encore corrigé.
J'ai finalement pu arriver jusqu'au point où il semble que le problème de memory leak subsiste, mais je n'ai pas pu enquêter plus loin par manque de compétence et de temps de l'auteur. Si vous avez des informations concrètes indiquant qu'un memory leak ou un DoS s'est produit avec ce modèle de JSON, je vous serais très reconnaissant de bien vouloir me les communiquer.
Comme il existe de nombreux OSS utilisant Jackson, d'autres bibliothèques et frameworks ont été affectés par cette vulnérabilité. Par exemple, Spring Security des produits Pivotal a été impacté et des informations ont été divulguées en juin 2017.
En ce qui concerne d'autres, par exemple le framework Spring lui-même, au moins sur https://pivotal.io/security/, aucune information de mise à jour due à Jackson n'a été publiée.
Cela ne signifie pas pour autant qu'on peut être tranquille. À l'origine, Jackson dans Spring Framework est conçu pour être assez facilement personnalisable, et il est possible de générer un ObjectMapper propre à l'application. Il est préférable de vérifier, par précaution, si les paramètres/fonctionnalités de Jackson ne sont pas personnalisés côté application ? Si @JsonTypeInfo n'est pas utilisé ? etc.
J'ai organisé chronologiquement les informations sur les issues/versions GitHub de jackson-databind et les liens de référence comme bugzilla de RedHat. Si vous trouvez des erreurs, n'hésitez pas à me les signaler.
La liste noire à ce moment était la suivante :```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");
ここで、同月中にblack-list対策の追加修正として 2.9.0 がリリース。
* https://github.com/FasterXML/jackson-databind/issues/1680
これが追加された:```java
s.add("com.sun.rowset.JdbcRowSetImpl");
De plus, au cours du même mois, l'issue suivante est ouverte :
→ Ce qui suit est ajouté à la black-list, et ceci est intégré dans 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");
### 2017-08
* Version 2.8.10 publiée avec les correctifs pour #1680, #1737.
* En août, les problèmes suivants ont été ouverts et des discussions globales sur la gestion en tant que CVE-2017-7525 ont eu lieu.
* https://github.com/FasterXML/jackson-databind/issues/1723
* Le blog d'Adam Caudill a publié une explication de l'exploit pour CVE-2017-7525.
* https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/
### 2017-09
* Version 2.9.1 publiée avec le correctif pour #1737.
### 2017-10
Dans le bugzilla suivant, il a été constaté que les versions 2.8.9 / 2.9.0 au moment du correctif pour CVE-2017-7525 étaient insuffisantes, et le travail a commencé pour appliquer la nouvelle liste noire des versions 2.8.10 / 2.9.1 sous CVE-2017-15095.
* https://bugzilla.redhat.com/show_bug.cgi?id=1506612
### 2017-11
* RedHat a publié les informations sur CVE-2017-15095.
* https://access.redhat.com/security/cve/cve-2017-15095
* Dans le ticket jackson-databind, des questions et réponses sur le statut de la gestion de CVE-2017-15095 ont été échangées.
* https://github.com/FasterXML/jackson-databind/issues/1847
* Il a été répondu que les versions 2.8.10 / 2.9.1 contiennent le correctif.
### 2017-12
* Un article explicatif a été publié sur le blog du développeur du WAF cloud Scutum.
* https://www.scutum.jp/information/waf_tech_blog/2017/12/waf-blog-052.html
* Selon cet article, la liste noire de la version 2.9.3 présente une lacune concernant les classes de Spring, ce qui ne pose pas de problème urgent, mais pourrait éventuellement nécessiter une nouvelle mise à jour.
* L'article aborde également la question de savoir si la responsabilité de cette vulnérabilité incombe à la bibliothèque elle-même ou à l'application.
## Tendances futures des vulnérabilités liées à la sérialisation/désérialisation Java
J'ai l'impression que le nombre d'informations sur les vulnérabilités liées à la sérialisation/désérialisation Java a augmenté depuis l'année dernière ou l'année précédente.
Par exemple, les informations sur les vulnérabilités des produits Pivotal, y compris Spring, sont publiées sur https://pivotal.io/security/ ; en 2017, en plus de CVE-2017-4995, les vulnérabilités suivantes ont été publiées.
* https://pivotal.io/security/cve-2017-8045
* RCE via un problème de désérialisation de `org.springframework.amqp.core.Message` dans Spring AMQP
* https://pivotal.io/security/cve-2017-8046
* RCE dans Spring Data REST via un défaut de gestion du JSON dans la méthode PATCH
Il s'agit de vulnérabilités facilement exploitables pour des RCE, ce qui explique pourquoi les attaquants et les chercheurs en vulnérabilités se concentrent actuellement sur la sérialisation/désérialisation Java.
On peut s'attendre à ce que les rapports de vulnérabilités liés aux processus de sérialisation/désérialisation se poursuivent au cours des prochaines années.
Cela dit, Jackson n'est pas le seul ; dans le développement actuel où les données sont échangées via des API à distance et où l'efficacité du développement est cruciale, ne pas utiliser du tout la sérialisation/désérialisation ou la créer entièrement soi-même est irréaliste pour la plupart des équipes.
L'important, selon l'auteur, est de créer une culture et un environnement de développement légers, capables de mettre à jour rapidement les bibliothèques dès qu'une vulnérabilité est publiée.
Voici quelques réflexions personnelles sur la manière d'aborder les vulnérabilités des intergiciels, bibliothèques et frameworks dont nous dépendons.
## Réflexions personnelles
Lorsque j'ai vu les informations sur S2-054 et 055, et l'impact de la vulnérabilité Jackson, j'ai été assez choqué.
Quelques jours auparavant, un collègue m'avait demandé quelle bibliothèque je recommandais pour analyser du JSON en Java, et j'avais répondu avec confiance : « Jackson est largement utilisé dans l'open source, il a fait ses preuves, et on trouve de nombreux articles et Q&A dessus, donc je le recommande. »
J'utilisais moi-même Jackson pour le développement d'outils internes et j'appréciais sa commodité.
Cependant, à ce moment-là, je n'étais pas au courant de CVE-2017-7525 ; je me sentais rassuré par le fait que Jackson était largement utilisé dans l'open source.
Un autre collègue a trouvé le blog d'Adam Caudill et m'a informé de l'existence de CVE-2017-7525. Quelques jours après avoir recommandé Jackson avec confiance, une mise à jour de Struts2 a été publiée à cause d'une vulnérabilité Jackson, et cette vulnérabilité Jackson était connue depuis plusieurs mois. En tant qu'ingénieur en sécurité, je ne pouvais pas nier avoir négligé la collecte d'informations sur les vulnérabilités des bibliothèques que j'utilisais (et c'était effectivement le cas).
Mon état mental ces derniers jours était donc au plus bas (tension artérielle et pouls élevés, mains tremblantes, larmes aux yeux sans raison, palpitations persistantes). Pour m'en sortir, j'ai passé le week-end à enquêter et à rédiger cet article, en commençant par comprendre ce qu'était CVE-2017-7525 et la situation exacte de Jackson.
En y réfléchissant, je réalise qu'il est très difficile, lorsqu'on est concentré sur le développement, de prêter attention aux informations de mise à jour des bibliothèques dépendantes.
Dans le flux constant des tâches de développement, il est irréaliste d'examiner complètement toutes les fonctionnalités et les aspects qualitatifs (comme les vulnérabilités) de toutes les bibliothèques utilisées.
D'un autre côté, les fonctionnalités demandées aux développeurs ne cessent d'augmenter, et il est tout aussi irréaliste de tout créer soi-même.
Il est nécessaire de « faire confiance » aux bibliothèques utilisées pour optimiser le développement.
Cependant, suivre les mises à jour de tous les outils et bibliothèques utilisés au quotidien et surveiller les correctifs de sécurité est également très difficile.
Bien sûr, je suis conscient qu'il existe aujourd'hui des services qui, après enregistrement des outils et bibliothèques utilisés, diffusent les informations de mise à jour pour résoudre ce problème.
Ce que j'ai ressenti avec la dégradation de mon état mental, c'est que mes sentiments de « repentir et culpabilité pour ce que je n'avais pas fait » étaient très forts.
Je me suis auto-étiqueté négativement : « Malgré mon métier d'ingénieur en sécurité, je n'étais pas au courant des vulnérabilités d'une bibliothèque que j'utilisais... »
Même les développeurs ordinaires, sans lien avec le secteur de la sécurité, peuvent ressentir des regrets ou de l'anxiété : « Si je n'avais pas proposé Struts2 à ce moment-là... » ou « Je dois mieux gérer le cycle de vie des bibliothèques/frameworks (= je suis anxieux face à ma situation actuelle d'incapacité). »
Si on essaie de résoudre ces problèmes de front, cela impliquerait de collecter une par une les informations sur les vulnérabilités, de vérifier le code source et les fonctionnalités de chaque bibliothèque et framework prévus, d'examiner minutieusement s'ils sont dignes d'être des standards de fait, et de gérer rigoureusement le cycle de vie après le déploiement.
Mais une telle approche de « prudence extrême » est-elle vraiment possible dans les divers environnements de développement actuels ?
En écrivant cet article, je me suis dit que l'époque où l'on considérait « ce qui n'a pas été fait, ce qui n'a pas pu être fait, ce qui n'a pas été remarqué » comme une cause ou un coupable, et où résoudre le problème revenait à « éliminer cela en le rendant possible », est peut-être révolue.
Dans une telle culture, à moins d'être parfait, les développeurs seront éternellement confrontés à ce qu'ils n'ont pas fait, n'ont pas pu faire ou n'ont pas remarqué.
Comme personne n'est parfait, seules des personnes mentalement très solides pourraient tenir.
Dans les problèmes de sécurité logicielle, les véritables responsables des dommages sont les attaquants. Ce sont les attaquants qui exploitent les vulnérabilités et rendent la situation négative.
La grande majorité des développeurs travaillent sérieusement et de bonne foi. À ce stade, ils sont déjà dans un état positif.
« Ne pas gérer le cycle de vie des bibliothèques/frameworks » ou « ne pas collecter ni surveiller les informations sur les vulnérabilités des bibliothèques utilisées » n'est simplement pas fait ; ce n'est ni positif ni négatif.
Pourtant, à cause de l'existence des attaquants, ces « choses non faites » deviennent des « choses non accomplies/non remarquées » et deviennent négatives. N'est-ce pas une situation bien triste ?
On ne peut nier que les valeurs de « prudence extrême » sont influencées par la société et la culture d'entreprise japonaises modernes.
Des cas où des vulnérabilités comme les injections SQL ont été introduites et ont causé des dommages par des attaquants sont encore fréquents, et il y a des exemples où la responsabilité de l'entreprise de développement a été engagée en justice.
Il arrive aussi que des négligences professionnelles entraînent des accidents graves.
Cependant, si on attribue tout cela aux « entreprises de développement/développeurs », cela risque de paralyser l'ensemble du développement informatique.
Les véritables responsables sont les attaquants qui exploitent les vulnérabilités.
De ce point de vue, les développeurs ou entreprises qui « n'ont pas fait, n'ont pas pu faire, n'ont pas remarqué » ne sont-ils pas davantage des victimes que des auteurs ?
Si c'est le cas, au lieu de leur dire « c'est de ta faute si tu n'as pas fait/pu faire/remarqué », ne serait-il pas plus important de leur tendre une main chaleureuse en disant « travaillons ensemble pour améliorer les choses, cela rendra plus sûr », et de stimuler mutuellement nos expertises respectives pour en tirer parti ?
Ainsi, les entreprises de développement/développeurs pourraient gérer les vulnérabilités plus sereinement, et ensuite développer activement sur une base de confiance.
Un environnement de développement serein et positif, avec plus de dynamisme, pourrait conduire à des résultats innovants et enrichir la société japonaise.
Personnellement, je souhaite que la mentalité suivante se répande à l'avenir :
* Développeurs de terrain
* « Avoir utilisé une bibliothèque avec une vulnérabilité » en soi n'est pas négatif.
* Ce qui rend négatif, ce sont les attaquants qui exploitent la vulnérabilité, ainsi que la culture qui évalue cela comme négatif.
* Travailler sérieusement chaque jour au développement est déjà suffisamment positif.
* La gestion des vulnérabilités n'est pas un travail pour revenir à zéro après un négatif, mais un travail positif pour améliorer la sécurité des résultats quotidiens du développement.
* Managers, leaders et dirigeants qui encadrent les développeurs
* Ne pas évaluer négativement « ce qui n'a pas été fait, ce qui n'a pas pu être fait, ce qui n'a pas été remarqué ». De telles valeurs devraient progressivement disparaître.
* Cesser de traiter les membres qui « n'ont pas fait, n'ont pas pu faire, n'ont pas remarqué » comme des coupables. Ils sont, et nous tous sommes, des victimes des attaquants qui exploitent les vulnérabilités ; à cet égard, notre position est la même.
* Abandonner les approches visant à résoudre par des « mesures parfaites ».
Cela implique de changer la façon de voir et de percevoir les choses, en impliquant développeurs, managers et dirigeants. Il est évident que c'est très difficile.
Alors, comment changer ?
Je n'ai pas la capacité de donner une réponse correcte, mais je pense qu'il y a un indice.
Il s'agit peut-être d'abandonner la recherche d'une réponse correcte.
Tout développement logiciel a un objectif. Chercher la « bonne réponse » pour l'atteindre de manière sûre et sécurisée est peut-être devenu impossible tant le monde du logiciel est complexe.
Je pense qu'il existe plutôt un paradigme de développement qui repose sur le « changement », où de nombreux acteurs essaient, échouent, reçoivent des retours, échangent des informations, puis bifurquent et évoluent librement.
Dans le développement de systèmes, les actifs logiciels créés une fois sont utilisés pendant plusieurs années, voire plusieurs décennies.
Cependant, les logiciels connectés à Internet, notamment les développements Web, sont exposés à un environnement qui change en quelques mois ou quelques années.
Les bibliothèques et frameworks utilisés il y a cinq ans peuvent ne plus être utilisables.
Dans ce cas, considérer les bibliothèques/frameworks créés initialement comme la « bonne réponse » et « figer » les versions présente plus d'inconvénients.
Le monde extérieur change constamment, il est donc normal que des vulnérabilités soient découvertes dans les bibliothèques/frameworks utilisés.
Figer les versions empêche de suivre ces changements, ce qui entraîne des coûts mentaux et physiques très élevés pour gérer les vulnérabilités.
Je crois donc fermement qu'à l'avenir, un paradigme de développement axé sur le « changement et la capacité à suivre le changement » conduira à de meilleurs résultats à long terme.
C'est tout, bien que long.
----
Rédacteur : Masahiko Sakamoto (département R&D, développement d'outils de diagnostic d'applications Web internes)
* Mail : [email protected]
* Twitter : https://twitter.com/msakamoto_sf
* Facebook: https://www.facebook.com/masahiko.sakamoto.75
* GitHub : https://github.com/msakamoto-sf
Pour toute question ou commentaire sur cet article, veuillez contacter Sakamoto.