
Rapporto di indagine sulle vulnerabilità Struts2 S2-045, S2-055 e le vulnerabilità Jackson CVE-2017-7525, CVE-2017-15095
Abbiamo pubblicato un riassunto conciso e facile da leggere. Consigliato a chi vuole una panoramica o ha poco tempo.
Il 1° dicembre 2017 è stato rilasciato un aggiornamento di sicurezza per Struts2. Prima del rilascio, si parlava su mailing list di una correlazione con le vulnerabilità di Jackson (una libreria JSON popolare in Java); anche l'autore, che utilizza Jackson in sistemi e strumenti interni, era curioso di sapere nel dettaglio di cosa si trattasse.
I contenuti effettivamente rilasciati risolvevano i seguenti due problemi di sicurezza. Solo S2-055 è interessato dalla vulnerabilità di jackson-databind, componente di Jackson.
Il plugin REST includeva già sia un handler basato su JSON-lib che uno basato su Jackson, consentendo all'utente di scegliere. Con S2-054 l'handler predefinito è stato cambiato in Jackson, e con S2-055 la versione di Jackson (che era obsoleta) è stata aggiornata all'ultima. Questo è il quadro completo della correzione.
Allora, di che vulnerabilità si tratta esattamente CVE-2017-7525? Poiché l'autore utilizza Jackson abitualmente quando elabora JSON in Java, questo articolo è il risultato di un'indagine condotta nel fine settimana del 2-3 dicembre.
Ambiente dell'autore utilizzato per la verifica del codice di esempio:
Sul blog di Adam Caudill è stata pubblicata una spiegazione di CVE-2017-7525.
Riassumendo con parole mie: jackson-databind fornisce la funzionalità di mappare JSON in oggetti Java (classe ObjectMapper).
Chiamando ObjectMapper.enableDefaultTyping(), è possibile effettuare la mappatura utilizzando un nome di classe incorporato arbitrariamente nel JSON.
Chi ha già avuto un brutto presentimento al pensiero di "poter specificare un nome di classe dall'input JSON" ha ragione: è proprio quel brutto presentimento a concretizzarsi con CVE-2017-7525.
Prima di descrivere la vulnerabilità, spieghiamo perché questa funzionalità è stata implementata.
Per un utilizzo base della deserializzazione con jackson-databind, fare riferimento al seguente codice di esempio. (In questo articolo usiamo Groovy per i codici di esempio Jackson. @Grab permette di cambiare facilmente la versione di jackson-databind.)
Nel codice di esempio sopra, la chiave "animal" viene semplicemente mappata direttamente alla classe Animal. E in casi come il seguente?```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() { } }
Con questa configurazione, il contenuto della chiave 'animal' può riferirsi alla classe Dog o alla classe Cat, generando due possibilità. Pertanto, sono necessarie informazioni aggiuntive per determinare con quale classe eseguire il mapping.
Per risolvere ciò, jackson-databind ha integrato un meccanismo personalizzato che consente di incorporare il nome della classe da mappare nel JSON.
Ad esempio, come segue, si trasforma il contenuto della chiave 'animal' in un array e si specifica il nome della classe nel primo elemento.```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}
In questo modo, ObjectMapper.readValue() riconosce che il contenuto della chiave "animal" è della classe Dog e procede al mapping.
Naturalmente, così com'è, non è possibile distinguere se il contenuto della chiave "animal" fosse originariamente un array o se contenesse le informazioni sul nome della classe proprie di jackson-databind.
Questo è controllato dal metodo ObjectMapper.enableDefaultTyping().
Esiste anche un altro metodo: definire l'annotazione @JsonTypeInfo nella classe. Per i dettagli, consultare la documentazione Jackson di seguito.
Di seguito viene mostrato un esempio di codice che utilizza effettivamente il metodo ObjectMapper.enableDefaultTyping().
Come abbiamo visto, fornendo il nome della classe seguito dalle sue proprietà in JSON, è possibile creare una classe arbitraria con proprietà arbitrarie, sebbene con alcune limitazioni. Questa è la vulnerabilità sfruttata da CVE-2017-7525, probabilmente innescata dal seguente report:
Per le librerie di serializzazione/deserializzazione comunemente usate in Java come Jackson, è stato segnalato il pericolo di portare all'esecuzione di codice arbitrario manipolando i nomi delle classi, e sono state elencate le classi specifiche ritenute pericolose. Non so se sia in risposta a ciò, ma dal punto di vista delle date, subito dopo il primo commit del repository sopra, è stato aperto il seguente Issue in jackson-databind e sono iniziati i lavori.
Com'è effettivamente un dato JSON e un codice Java che sfruttano questa vulnerabilità? Un suggerimento si trova nel codice di test di jackson-databind 2.8.9 che ha risolto questo Issue:
Basato su questo codice di test, di seguito viene mostrato un esempio di codice adattato per poter verificare il funzionamento.
Eseguendo con @Grab specificando la versione 2.8.9, viene visualizzato your jackson version IS SAFE to CVE-2017-7525. Questo perché nella correzione della 2.8.9 è stato aggiunto un controllo blacklist sui nomi delle classi da istanziare.
Se invece si specifica la versione 2.8.8 in @Grab, l'output sarà il seguente:```
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
Nell'output è presente una riga `at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)`.
In questo codice di esempio viene lanciata una NullPointerException, ma dal nome del metodo si intuisce che sta avvenendo un'elaborazione che probabilmente include qualche effetto collaterale.
Per costruire un JSON che permetta l'esecuzione effettiva del codice, sembra necessaria un'ulteriore indagine.
In questo articolo ci fermiamo per ora a questa introduzione, ma se in futuro verranno pubblicati articoli di approfondimento su altri siti, intendiamo aggiornare questa pagina.
A proposito, dove è implementata la vera black list? Si trova nella seguente classe:
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L51
In effetti, sembra che nella versione 2.8.9 ci fosse una lacuna in questa black list. Tale problema è CVE-2017-15095.
### Miglioramento della black list con CVE-2017-15095
Per quanto riguarda il miglioramento della black list, prima di tutto in https://github.com/FasterXML/jackson-databind/issues/1680 è stato aggiunto `s.add("com.sun.rowset.JdbcRowSetImpl");`.
Dopo il rilascio della versione 2.9.0 con questa modifica, successivamente in https://github.com/FasterXML/jackson-databind/issues/1737 è stato aggiunto il seguente controllo nella black list.```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");
Con ciò, sono state rilasciate le versioni 2.8.10 / 2.9.1, completando la gestione di CVE-2017-15095.
Codice di test per verificare il funzionamento della black list in 2.8.10:
Sulla base di questo codice di test, di seguito è riportato un codice di esempio adattato per la verifica del funzionamento.
Eseguendo la versione 2.8.10, che si dice abbia completato la gestione, specificandola con @Grab, viene visualizzato your jackson version IS SAFE to CVE-2017-15095.
Successivamente, eseguendo la versione 2.8.9 prima del miglioramento della black list specificandola con @Grab, viene prodotto il seguente output.```
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
Nelle versioni precedenti alla correzione, il nome della classe `java.util.logging.FileHandler` riusciva a bypassare il controllo della black list e veniva istanziato, tentando effettivamente di aprire un file.
Nella versione corretta, viene intercettato dal controllo della black list e viene lanciata un'eccezione `JsonMappingException`.
Nota che la black list al momento della versione 2.8.10 era la seguente. La parte che inizia con il commento `[databind#1737]` è l'aggiunta alla black list per la 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
### Condizioni di esposizione alla vulnerabilità, fattibilità dell'attacco e contromisure lato applicazione
Riassumendo i risultati di cui sopra, le condizioni necessarie per essere esposti alla vulnerabilità di jackson-databind sono le seguenti:
1. Utilizzo di jackson-databind 2.8.9 / 2.9.0 o precedenti.
2. Elaborazione di JSON proveniente da fonti non fidate in uno dei seguenti modi:
* Chiamata a `ObjectMapper.enableDefaultTyping()` prima della deserializzazione.
* Senza chiamare `ObjectMapper.enableDefaultTyping()`, ma utilizzando l'annotazione `@JsonTypeInfo` nella dichiarazione della classe per consentire il mapping e quindi deserializzando.
* Anche se non utilizzato nel codice applicativo, potrebbe verificarsi una deserializzazione automatica da parte del framework in base all'intestazione della richiesta `Accept` o all'estensione dell'URL.
3. Presenza nel classpath di classi ("Gadget") che potrebbero essere sfruttate per vulnerabilità di serializzazione/deserializzazione Java.
4. Utilizzo di tipi nei campi membri delle classi Java di destinazione del mapping che possono accettare classi Gadget, come il tipo Object.
* Se il tipo è una classe Bean specifica dell'applicazione incompatibile con una classe utilizzata come Gadget, è possibile bloccare la creazione effettiva dell'istanza con un errore di controllo del tipo. (Tranne nel caso in cui la stessa classe Bean specifica dell'applicazione abbia una vulnerabilità di deserializzazione nascosta.)
La reale esposizione sembra dipendere fortemente dal codice applicativo, dalle modalità/impostazioni di `ObjectMapper`, dalla combinazione dell'annotazione `@JsonTypeInfo`, dai campi membri della classe di destinazione del mapping, ecc.
Inoltre, se una chiave in JSON non esiste nella classe Java di destinazione della deserializzazione, Jackson la ignora semplicemente.
Pertanto, per avere successo, un attacco deve essere personalizzato in base al JSON specifico dell'applicazione, e si ritiene estremamente difficile creare codice d'attacco riutilizzabile su più applicazioni.
Inoltre, per quanto riguarda la condizione 4, in una scrittura tipica, difficilmente si imposta deliberatamente un campo di una classe Java come tipo Object.
Si ritiene inoltre che nella maggior parte dei casi le classi che consentono l'esecuzione di codice arbitrario siano incompatibili con le classi Bean create nell'applicazione.
Alla luce di quanto sopra, si ritiene improbabile che si verifichino attacchi su larga scala o che questa vulnerabilità venga effettivamente sfruttata per causare danni (cioè che l'attacco abbia successo).
Per quanto riguarda le contromisure lato applicazione, per la condizione 3, poiché anche le classi incluse nel JDK possono essere sfruttate, si ritiene che di fatto non sia possibile intervenire.
Pertanto, la contromisura di base è aggiornare jackson-databind all'ultima versione.
Se non è possibile aggiornare jackson-databind all'ultima versione, si deve rimuovere la chiamata a `ObjectMapper.enableDefaultTyping()` o l'annotazione `@JsonTypeInfo` e riprogettare il sistema per non dipenderne. Ad esempio, si potrebbe creare un serializzatore personalizzato.
Tuttavia, se si è già iniziato a utilizzarlo come API richiamabile da remoto, non è facile modificare il formato JSON.
Per quanto riguarda l'annotazione `@JsonTypeInfo`, a seconda della configurazione, sembra possibile limitare le sottoclassi, accettando solo i nomi di classe previsti dal programmatore.
Per i dettagli, consultare la seguente documentazione:
* JacksonPolymorphicDeserialization
* https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
#### Pro e contro della contromisura basata su black list e creazione di un deserializzatore personalizzato
jackson-databind 2.8.10 / 2.9.1 ha risolto le CVE-2017-7525 e CVE-2017-15095 con una contromisura basata su black list.
Tuttavia, come è evidente dai problemi relativi a OGNL in Struts2, la contromisura basata su black list non è infallibile.
(A parere personale dell'autore, ritiene che sia una contromisura abbastanza efficace almeno per il livello di cosiddetti "script kiddie" che si limitano a eseguire strumenti di scansione.)
Pertanto, se si vuole una contromisura veramente radicale, l'autore ritiene importante disabilitare/non utilizzare funzionalità come `ObjectMapper.enableDefaultTyping()` che incorporano informazioni sulle classi nel JSON.
Allora, come risolvere il problema che `ObjectMapper.enableDefaultTyping()` mirava a risolvere?
A questo proposito, l'autore stesso non ha un'alternativa che possa considerare una soluzione definitiva.
La radice del problema è, probabilmente, "poter eseguire il mapping senza fare affidamento su un JSON non fidato, quando la classe Java di mapping è ambigua".
L'autore ritiene che un possibile approccio per risolverlo sia la creazione di un deserializzatore personalizzato.
Un deserializzatore personalizzato può ricevere JSON durante la deserializzazione dal lato del codice del programma e controllare autonomamente l'oggetto generato.
Ad esempio, se arriva `{"animal":{"name":"dog1","barkVolume":1.2}}`, si può decidere che "c'è la chiave `barkVolume`, quindi istanzio come classe Dog", oppure
se arriva `{"animal":{"name":"cat1","likesCream":true,"lives":10}}`, si può decidere che "ci sono le chiavi `likesCream` e `lives`, quindi istanzio come classe Cat".
In questo modo, non è più necessario incorporare il nome della classe nel JSON.
Personalmente, ho l'impressione che il formato JSON con incorporamento del nome della classe possa causare problemi di interoperabilità con altri linguaggi/librerie (se qualcuno conosce estensioni simili in altri linguaggi o librerie, fatemelo sapere).
Se si presuppone l'interoperabilità con altri sistemi, piuttosto che far incorporare il nome della classe a proprio uso e consumo solo per Jackson, mi sembra più sensato creare un deserializzatore personalizzato lato Jackson per gestire la situazione.
Penso ci siano anche altre possibili soluzioni, quindi sarei lieto se i lettori potessero condividere le loro opinioni su eventuali altre soluzioni.
(Un esempio estremo potrebbe essere quello di non eseguire il mapping su classi specifiche, ma deserializzare tutto nel formato `Map<String, Object>` o `List<String, Object>`.)
Ho trovato alcuni articoli di riferimento per creare un deserializzatore personalizzato; anche se in inglese, allego i link.
* 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 di jackson-databind (serie 2.8, 2.9):
* https://fasterxml.github.io/jackson-databind/javadoc/2.8/
* https://fasterxml.github.io/jackson-databind/javadoc/2.9/
Ho anche creato un esempio di codice per un deserializzatore personalizzato; spero possa essere d'aiuto.
* [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)
## Informazioni su S2-055
Finora abbiamo esaminato la vulnerabilità di Jackson stesso. Ora, come influisce effettivamente sul plugin REST di Struts2? Abbiamo verificato utilizzando struts2-rest-showcase, che è incluso in Struts2.
L'utilizzo del plugin REST di Struts è stato consultato qui:
* http://struts.apache.org/plugins/rest/
### Il plugin REST di Struts2 non chiama ObjectMapper.enableDefaultTyping()
A proposito, tra le condizioni per essere effettivamente vulnerabili alla CVE-2017-7525 c'erano le seguenti:
* Elaborazione di JSON proveniente da fonti non fidate in uno dei seguenti modi:
* Chiamata a `ObjectMapper.enableDefaultTyping()` prima della deserializzazione.
* Senza chiamare `ObjectMapper.enableDefaultTyping()`, ma utilizzando l'annotazione `@JsonTypeInfo` nella dichiarazione della classe per consentire il mapping e quindi deserializzando.
Abbiamo verificato se il plugin REST di Struts2 contenesse codice corrispondente a queste condizioni e abbiamo confermato che nessuna delle due è presente.
In effetti, al momento della versione precedente alla correzione (2.5.14), né `ObjectMapper.enableDefaultTyping()` né `@JsonTypeInfo` erano presenti, né nel plugin REST né nell'intero albero dei sorgenti di Struts2, neppure dopo una ricerca grep.
* https://github.com/apache/struts/tree/STRUTS_2_5_14
In tutto l'albero dei sorgenti di Struts2, l'unica classe che utilizza ObjectMapper di Jackson è `org.apache.struts2.rest.handler.JacksonLibHandler`. Dopo aver controllato il codice sorgente, alla versione 2.5.14, effettivamente non viene utilizzato `ObjectMapper.enableDefaultTyping()`.
* https://github.com/apache/struts/blob/STRUTS_2_5_14/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonLibHandler.java
* Questo file Java è rimasto invariato anche nella versione 2.5.14.1.
Pertanto, si ritiene che il plugin REST stesso non fosse vulnerabile alla CVE-2017-7525 nemmeno alla versione 2.5.14.
La vulnerabilità si verifica quando l'applicazione imposta `@JsonTypeInfo` sul campo di una classe di mapping JSON.
Nei test effettuati con struts2-rest-showcase di seguito, abbiamo quindi impostato `@JsonTypeInfo` sul campo della classe di destinazione del mapping aggiunto dall'applicazione e abbiamo eseguito la verifica.
Tra l'altro, in Struts2 esiste anche un plugin JSON.
* http://struts.apache.org/plugins/json/
* Guardando il codice sorgente del plugin JSON, nel `pom.xml` non ha dipendenze da altre librerie JSON.
* Sembra che implementi l'elaborazione JSON in modo autonomo.
* https://github.com/apache/struts/tree/STRUTS_2_5_14/plugins/json
* Pertanto, la vulnerabilità di jackson-databind non dovrebbe interessare il plugin JSON.
### Adattamento di struts2-rest-showcase per Jackson
struts2-rest-showcase è un esempio che implementa il CRUD per la classe Order utilizzando il plugin REST. A questo abbiamo aggiunto le classi Zoo / Animal / Cat / Dog utilizzate nel codice di esempio per la vulnerabilità di Jackson, e un ZooController per gestirne il CRUD in JSON.
Il codice sorgente completo è disponibile qui: (la build e l'esecuzione sono state verificate con JDK8 in questo articolo)
* [rest-showcase](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/tree/master/rest-showcase)
Principali modifiche:
* Modifica della porta di ascolto del plugin jetty-maven-plugin a 18088. (`mvn jetty:run`)
* Aggiunta delle dipendenze jackson-core e jackson-databind.
* Aggiunta delle classi Zoo, Animal (astratta), Dog, Cat. Aggiunta della classe ZooService come livello di servizio.
* Aggiunta di un ZooController con CRUD minimo. (Le JSP per la vista sono omesse)
* Modifica del gestore JSON in `struts.xml` a JacksonLibHandler.
* Inclusione di maven-wrapper in modo che, con solo JDK installato, si possa eseguire `mvnw` / `mvnw.bat` per buildare ed eseguire direttamente.
Build ed esecuzione:
1. Dopo aver clonato il repository, spostarsi nella directory `rest-showcase` ed eseguire `mvnw jetty:run`. (Attenzione: alla prima esecuzione, il download di Maven può richiedere alcuni minuti o, in alcuni casi, più di 10 minuti.)
2. Accedere a http://localhost:18088/struts2-rest-showcase/; se viene visualizzato l'elenco degli Order, l'operazione è riuscita.
3. Per terminare l'esecuzione, premere Ctrl-C.
4. Se si modificano i file Java, terminare con Ctrl-C ed eseguire nuovamente `mvnw jetty:run`.
Verifica con comando curl: (presupponendo l'uso del proxy locale localhost:8080)```
一覧取得:
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
Nel repository, nel file Zoo.java, il campo animal è di tipo Animal (abstract class) con @JsonTypeInfo commentato come segue.```java
//@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
public Animal animal;
//public Object animal;
Qui, invia una richiesta JSON con il metodo POST e prova a chiamare il metodo 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}}'
すると以下のエラーメッセージを含む例外が発生しました。Animalクラスはabstractなため、インスタンスを生成できていません。``` 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
Quindi, rimuovi il commento da `@JsonTypeInfo` nel campo `animal` per abilitarlo. Interrompi l'applicazione web con Ctrl-C ed esegui di nuovo `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;
Così diventa possibile incorporare i nomi delle classi nel JSON. Proviamo a inviare un POST di un JSON con i nomi delle classi incorporati utilizzando il seguente comando curl.``` 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}]}'
→ Viene restituito `HTTP/1.1 201 Created`. Se si prova a recuperare l'elenco, si può confermare che è stato effettivamente aggiunto.
### Verifica di CVE-2017-7525 con Struts2 REST plugin 2.5.14
Nel pom.xml del repository, l'artefatto Struts in `<parent>` specifica la versione 2.5.14, quindi è vulnerabile a CVE-2017-7525 così com'è. Per verificarlo, esegui il seguente comando curl. I nomi delle classi e i loro contenuti si basano su cve-2017-7525-check.groovy, quindi se viene restituita la stessa risposta di jackson-databind 2.8.8, si ritiene che sia vulnerabile.```
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":{}}]}'
→ 以下のレラーメッセージを含む例外がthrowされました。``` java.lang.IllegalArgumentException: Class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl not subtype of [simple type, class org.demo.rest.example.Animal]
Sembra che si sia verificata un'eccezione `IllegalArgumentException` perché il tipo del campo `animal` è la classe `Animal`, che non è un sottotipo della classe `com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl`.
Allora, modifichiamo il campo `animal` in `Zoo.java` al tipo `Object` e proviamo a eseguirlo di nuovo con `mvnw jetty:run`.```java
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
//public Animal animal;
public Object animal;
Se esegui nuovamente il comando curl precedente, si verificherà un'eccezione contenente il seguente 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]
Questa è la stessa eccezione del caso vulnerabile verificata con cve-2017-7525-check.groovy.
Da quanto sopra, abbiamo confermato la presenza della vulnerabilità CVE-2017-7525 di jackson-databind in Struts2 REST plugin 2.5.14.
Inoltre, abbiamo scoperto che è necessario utilizzare il tipo Object in aggiunta a `@JsonTypeInfo`.
Quanto segue è un'opinione personale dell'autore: non sembra comune specificare intenzionalmente come tipo di campo in una classe di dati per la creazione di API REST il tipo Object o una classe compatibile con le classi utilizzabili come gadget nella vulnerabilità di deserializzazione Java. Pertanto, ritengo che sia difficile far riuscire un attacco nella pratica.
### Verifica della correzione in Struts2 REST plugin 2.5.14.1
Verifichiamo ora se la vulnerabilità è stata corretta nella versione 2.5.14.1.
Modifichiamo la versione dell'artifact `<parent>` in pom.xml a 2.5.14.1, riavviamo con `mvnw jetty:run` ed eseguiamo lo stesso comando curl di prima.```
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":{}}]}'
Si è verificata un'eccezione contenente il seguente messaggio di errore.```
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
これは cve-2017-7525-check.groovy で検証した時と同じ、脆弱性が修正された後の例外です。
Eclipse等のMavenに対応したIDEで開いて、依存性を解決した後のjackson-databindのバージョンを見てみると、たしかに 2.9.2 になっていることが確認できると思います。IDEがない場合は、 `mvnw help:effective-pom` で最終的なpomを出力できますので、そこで jackson-databind を検索すれば version 2.9.2 を使用していることを確認できると思います。
CVE-2017-15095 については省略しますが、以上より 2.5.14.1 で jackson-databind の脆弱性に対応できたことを確認できました。
### S2-055のPoC
※ 2017-12-08 追記
S2-055についての調査記事 & PoCレポートが公開されました。
* S2-055漏洞环境搭建与分析 | 绿盟科技博客
* http://blog.nsfocus.net/s2-055/
Google翻訳のお世話になりつつ読んでみますと、発生条件や攻撃の実現度について同じ見解のようです。
実際にrest-showcaseを修正し、電卓が起動したHTTP通信のPoCも示されています。
JSON部分だけ拝借し、まずはJackson単体で試してみたのが次のサンプルコードになります。
* [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)
ここで 2.8.8 を使うバージョン指定で実行してみると、筆者の環境では以下のように出力されました。```
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)
(...)
Come per il file cve-2017-7525-check.groovy, il metodo run() è stato eseguito e si è verificata una NullPointerException. Tuttavia, la calcolatrice non è stata avviata.
Presumo che, poiché TemplatesImpl di Xalan è una classe inclusa in Java, è possibile che Java abbia applicato qualche correzione.
Oppure è possibile che per un attacco effettivo siano necessarie condizioni più specifiche.
Nell'articolo del PoC non viene indicata la versione di Java utilizzata per la verifica, quindi non sono riuscito ad arrivare al punto di avviare la calcolatrice. Se emergeranno ulteriori informazioni, intendo verificare di nuovo.
Finora ho introdotto principalmente le vulnerabilità di Jackson CVE-2017-7525 e CVE-2017-15095 a partire da S2-055. Ora riassumo brevemente i risultati della ricerca sulla situazione di S2-054.
In conclusione, al momento della stesura di questo articolo (2017-12-03), non ho trovato informazioni specifiche. Non sono stati trovati nemmeno PoC in grado di verificare la presenza della vulnerabilità.
Nella pagina di divulgazione delle informazioni su S2-054 si spiega che nel plugin REST viene utilizzata una vecchia libreria JSON-lib, che consente un attacco DoS tramite una richiesta JSON manipolata.
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.
Nella pagina della versione 2.5.14.1 rilasciata per affrontare questo problema, è collegato il ticket JIRA WW-4892.
Ho controllato WW-4892, ma non viene menzionata alcuna vulnerabilità DoS o relativa a JSON-lib. Anche leggendo la "Descrizione", sembra che si dica solo che JSON-lib è vecchio e non più mantenuto, quindi si cambia il gestore predefinito con Jackson.
La pull request su GitHub è la seguente, ma nemmeno qui si fa riferimento a problemi specifici di JSON-lib.
Così ho deciso di esaminare JSON-lib. Il sito ufficiale è il seguente:
Inoltre, al 2017, sembra essere gestito su GitHub.
Quale è il più recente? Al momento della stesura di questo articolo, non ci sono release su GitHub. Quindi ho controllato lo stato del repository Maven Central. Cercando "json-lib", vengono restituiti diversi groupId.
Per vedere quale groupId è corretto, ho controllato il pom.xml del plugin REST di Struts2 2.5.14.1.
net.sf.json-lib, artifactId = json-lib.Guardando le versioni rilasciate di groupId = net.sf.json-lib, artifactId = json-lib, l'ultima release è la versione 2.4 del dicembre 2010.
Controllando la pagina di sourceforge, anche qui l'ultima release è la versione 2.4 del dicembre 2012.
In effetti, su GitHub non ci sono tag di release, ma seguendo i log dei commit, c'è un commit di release della versione 2.4 del dicembre 2010. Dopodiché, i merge delle pull request sono attivi, ma non ci sono state ulteriori release.
Guardando le Issue su GitHub, incluse quelle chiuse, non si vedono titoli che possano portare a DoS.
Esaminando i ticket su sourceforge, finalmente ho trovato dei ticket relativi a memory leak. Sembra che non siano ancora stati corretti.
ThreadLocal fino alla versione 2.2, che è stato affrontato con SoftReference nella versione 2.4, ma non è una soluzione definitiva.Alla fine sono riuscito a capire che probabilmente rimane ancora un problema di memory leak, ma per limiti di tempo e competenza non ho potuto proseguire l'indagine oltre. Se qualcuno ha informazioni concrete su memory leak o DoS causati da questo pattern JSON, sarei molto grato se potesse fornirle.
Poiché molti OSS utilizzano Jackson, anche altre librerie e framework sono stati colpiti da questa vulnerabilità. Ad esempio, i prodotti Pivotal come Spring Security sono stati colpiti, e l'informazione è stata divulgata nel giugno 2017.
Per quanto riguarda altri framework, come Spring Framework stesso, almeno su https://pivotal.io/security/ non sono state pubblicate informazioni di aggiornamento relative a Jackson.
Tuttavia, non ci si può fidare. Originariamente, Jackson in Spring Framework è progettato per essere facilmente personalizzabile, ed è possibile creare ObjectMapper specifici per l'applicazione. È opportuno verificare se le impostazioni/funzionalità di Jackson sono state personalizzate dall'applicazione, se viene utilizzato @JsonTypeInfo, ecc.
Ho organizzato in ordine cronologico i riferimenti come le Issue/Release di jackson-databind su GitHub e il bugzilla di RedHat. Se ci sono errori, non esitate a segnalarmeli.
La lista delle black-list a questo punto era la seguente:```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");
Qui, nel corso dello stesso mese, è stata rilasciata la versione 2.9.0 come ulteriore modifica per la contromisura black-list.
* https://github.com/FasterXML/jackson-databind/issues/1680
È stato aggiunto:```java
s.add("com.sun.rowset.JdbcRowSetImpl");
Inoltre, nello stesso mese, viene aperto il seguente issue:
→Alla black-list viene aggiunto quanto segue, e questo è integrato in 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
* Rilasciata la versione 2.8.10 che risolve #1680 e #1737.
* Sempre ad agosto, è stata aperta la seguente Issue e si è discusso in modo completo della risoluzione come CVE-2017-7525.
* https://github.com/FasterXML/jackson-databind/issues/1723
* Sul blog di Adam Caudill è stata pubblicata una spiegazione dell'exploit per CVE-2017-7525.
* https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/
### 2017-09
* Rilasciata la versione 2.9.1 che risolve #1737.
### 2017-10
Nel seguente bugzilla, si è iniziato il lavoro per applicare la black-list della versione più recente 2.8.10 / 2.9.1 come nuova CVE-2017-15095, poiché le versioni 2.8.9 / 2.9.0 al momento della correzione di CVE-2017-7525 erano insufficienti.
* https://bugzilla.redhat.com/show_bug.cgi?id=1506612
### 2017-11
* Le informazioni su CVE-2017-15095 sono state pubblicate da RedHat.
* https://access.redhat.com/security/cve/cve-2017-15095
* Anche nell'Issue di jackson-databind, sono stati scambiati domande e risposte sullo stato della gestione di CVE-2017-15095.
* https://github.com/FasterXML/jackson-databind/issues/1847
* È stato risposto che è stato affrontato nelle versioni 2.8.10 / 2.9.1.
### 2017-12
* Un articolo esplicativo è stato pubblicato sul blog degli sviluppatori di Scutum, un WAF cloud.
* https://www.scutum.jp/information/waf_tech_blog/2017/12/waf-blog-052.html
* In questo articolo si afferma che nella black list della versione 2.9.3 c'era un'inesattezza riguardante la classe Spring, che non costituiva un problema urgente, ma che forse avrebbe potuto portare a un ulteriore aggiornamento.
* Inoltre, si discute se la responsabilità di questa vulnerabilità fosse effettivamente della libreria o piuttosto dell'applicazione.
## Tendenze future delle vulnerabilità relative alla serializzazione/deserializzazione in Java
Dall'anno scorso all'anno precedente, ho l'impressione che le informazioni sulle vulnerabilità relative alla serializzazione/deserializzazione in Java siano aumentate.
Ad esempio, le informazioni sulle vulnerabilità dei prodotti Pivotal, inclusi Spring, sono pubblicate su https://pivotal.io/security/. Nel 2017, oltre a CVE-2017-4995, sono state pubblicate le seguenti vulnerabilità.
* https://pivotal.io/security/cve-2017-8045
* RCE dovuta a un problema di deserializzazione di `org.springframework.amqp.core.Message` in Spring AMQP
* https://pivotal.io/security/cve-2017-8046
* RCE a causa di una gestione inadeguata del JSON nel metodo PATCH di Spring Data REST
Trattandosi di vulnerabilità facilmente collegabili a RCE, sembra essere un periodo in cui sia gli attaccanti che i ricercatori di vulnerabilità stanno concentrando la loro attenzione sulla serializzazione/deserializzazione in Java.
Nei prossimi anni, credo che continueranno a essere segnalate vulnerabilità relative ai processi di serializzazione/deserializzazione.
Detto questo, come anche per Jackson, non pensate che nella maggior parte dei contesti di sviluppo odierni, dove lo sviluppo è reso efficiente e lo scambio di dati tramite API remote è diventato normale, sia irrealistico non usare affatto la serializzazione/deserializzazione o crearne una propria da zero?
Personalmente, ritengo che la cosa importante sia creare una cultura e un ambiente di sviluppo agile, in grado di aggiornare rapidamente le librerie non appena viene pubblicata una vulnerabilità.
Avevo delle riflessioni personali su come affrontare mentalmente le vulnerabilità delle dipendenze middleware, librerie e framework, quindi ho scritto le seguenti impressioni.
## Impressioni
Quando ho visto le informazioni sulla pubblicazione di S2-054 e S2-055, e che erano influenzate dalla vulnerabilità di Jackson, sono rimasto piuttosto scioccato.
Questo perché pochi giorni prima un collega mi aveva chiesto: "C'è una libreria consigliata per parsificare JSON in Java?" e io, con aria tronfia, avevo risposto: "Jackson è ampiamente utilizzato come OSS e ha una solida reputazione; cercando su Google si trovano molti articoli e Q&A, quindi lo consiglio".
Io stesso usavo Jackson nello sviluppo di strumenti interni e ne apprezzavo la comodità.
Tuttavia, a quel punto non ero a conoscenza di CVE-2017-7525 e mi ero completamente rassicurato dal fatto che Jackson fosse ampiamente utilizzato nell'OSS e avesse molti utenti.
Poi un altro collega ha trovato il blog di Adam Caudill e mi ha informato dell'esistenza di CVE-2017-7525. Ma pochi giorni dopo aver raccomandato con aria tronfia Jackson, è stato pubblicato un aggiornamento di Struts2 a causa di una vulnerabilità di Jackson, e per di più la vulnerabilità di Jackson era già stata affrontata mesi prima. Come ingegnere nel settore della sicurezza, non posso negare di aver trascurato la raccolta di informazioni sulle vulnerabilità delle librerie che uso (e in effetti è così).
Per questo motivo, la mia condizione mentale in quei giorni era pessima (aumento della pressione sanguigna e del battito cardiaco, tremori alle mani, voglia di piangere senza essere triste, palpitazioni continue, ecc.). Per cercare di rimediare, ho deciso di iniziare a capire cosa fosse esattamente CVE-2017-7525 e la situazione di Jackson, dedicando il fine settimana alla ricerca e alla stesura di questo articolo.
Ripensandoci, capisco profondamente quanto sia difficile prestare attenzione alle informazioni sugli aggiornamenti delle librerie dipendenti quando si è concentrati sullo sviluppo.
In mezzo a un flusso continuo di attività di sviluppo, è praticamente impossibile esaminare a fondo tutte le funzionalità e la qualità, comprese le vulnerabilità, di ogni libreria utilizzata.
D'altro canto, le funzionalità richieste per lo sviluppo diventano sempre più numerose, ed è altrettanto irrealistico crearle tutte da zero.
È necessario "fidarsi" in qualche punto delle librerie utilizzate per rendere lo sviluppo efficiente.
Tuttavia, anche tenere traccia di tutti gli aggiornamenti degli strumenti e delle librerie usate nel lavoro quotidiano e monitorare se includono correzioni di sicurezza è estremamente difficile.
Naturalmente, so che per affrontare questo problema, recentemente esistono servizi che, registrando gli strumenti e le librerie utilizzati, forniscono informazioni sui loro aggiornamenti.
Ciò che ho sentito a causa del peggioramento della mia condizione mentale è che dentro di me è molto forte il "senso di colpa e rimorso per ciò che non ho fatto".
Mi stavo auto-etichettando in modo negativo: "Nonostante sia un ingegnere della sicurezza, non conoscevo le informazioni sulle vulnerabilità di una libreria che uso personalmente...".
Anche tra gli sviluppatori generici non legati al settore della sicurezza,
molti probabilmente provano rimpianti e ansie come: "Se solo non avessi proposto Struts2 in quel momento..." o "Devo gestire meglio il ciclo di vita delle librerie/framework (= la situazione attuale in cui non lo faccio è preoccupante)".
Se si tentasse di affrontare e "risolvere" questi come "problemi" in modo diretto, si dovrebbe raccogliere ogni singola informazione sulle vulnerabilità, controllare una per una le funzionalità e il codice sorgente delle librerie e framework che si intendono usare, verificare attentamente se sono considerati standard de facto, e dopo l'inizio dell'operatività gestire meticolosamente il ciclo di vita.
Tuttavia, un approccio così "cauto", che cerca di eliminare ogni rischio, è davvero possibile nei diversi contesti di sviluppo odierni?
Scrivendo questo articolo, ho pensato che forse è finita l'epoca in cui si considerava "risolvere un problema" solo identificare come causa o colpevole "ciò che non si è fatto / non si è stato in grado di fare / non si è notato" e cancellarlo, cioè "renderlo possibile".
In una tale cultura, a meno di non essere perfetti, gli sviluppatori continuerebbero all'infinito a confrontarsi con le proprie "cose non fatte, non riuscite, non notate".
Poiché non esistono esseri umani perfetti, penso che solo persone con una forza mentale notevole possano resistere.
Nei problemi di sicurezza del software, il vero colpevole che causa i danni sono gli attaccanti. A rendere negativa la situazione sono gli attaccanti che sfruttano le vulnerabilità.
La stragrande maggioranza degli sviluppatori, in linea di principio, lavora con buona volontà e serietà. A quel punto, sono già in uno stato positivo.
"Non gestire il ciclo di vita di librerie/framework" o "non raccogliere e monitorare le informazioni sulle vulnerabilità delle librerie utilizzate" è semplicemente qualcosa che non si fa, è uno stato né positivo né negativo.
Eppure, a causa dell'esistenza degli attaccanti, il "non fare" diventa "non essere stato in grado di fare / non aver notato" e diventa negativo. Non è una situazione troppo triste?
Non si può negare che la società giapponese moderna e la cultura aziendale influenzino questi valori di "estrema prudenza".
Ci sono ancora casi in cui si creano vulnerabilità come SQL injection e si verificano danni da parte degli attaccanti, e ci sono esempi in cui le società di sviluppo vengono ritenute responsabili in tribunale.
Ci sono anche casi in cui la negligenza sul lavoro porta a incidenti gravi.
Tuttavia, se tutto questo viene considerato esclusivamente un problema delle "società di sviluppo/sviluppatori", temo che lo sviluppo IT nel suo complesso finisca per essere intimidito.
I veri colpevoli sono gli attaccanti che sfruttano le vulnerabilità.
Se la vediamo in questo modo, gli sviluppatori e le società di sviluppo che "non hanno fatto / non sono stati in grado di fare / non hanno notato" non sono forse più vittime che autori di reato?
Se è così, invece di rimproverare le vittime dicendo "è colpa tua perché non hai fatto / non sei stato in grado di fare / non hai notato", penso fermamente che sia importante tendere una mano calorosa con l'obiettivo di camminare insieme, dicendo "se fai così diventa più sicuro, possiamo migliorare, quindi impegniamoci insieme", e competere e valorizzarsi a vicenda nei rispettivi ambiti di specializzazione.
In questo modo, le società di sviluppo/gli sviluppatori potranno affrontare le vulnerabilità con tranquillità e sarà più facile sviluppare in modo proattivo basandosi su quella serenità.
Se i luoghi di sviluppo diventano sereni, luminosi e lo sviluppo proattivo aumenta, non è forse possibile che i risultati innovativi crescano e la società giapponese diventi più ricca?
Personalmente, sento fortemente che in futuro sarebbe bello se si diffondessero idee come le seguenti.
* Sviluppatori sul campo
* "Aver usato una libreria con vulnerabilità" di per sé non è negativo.
* A rendere negativo sono gli attaccanti che sfruttano le vulnerabilità e la cultura stessa che valuta ciò come negativo.
* Il fatto di impegnarsi seriamente ogni giorno nel lavoro di sviluppo è già di per sé un valore positivo.
* Gestire le vulnerabilità non è un'operazione per riportare a zero ciò che è diventato negativo, ma un'operazione positiva per migliorare i risultati dello sviluppo quotidiano rendendoli più sicuri.
* Manager, leader e dirigenti che coordinano gli sviluppatori
* Non valutare negativamente "ciò che non è stato fatto / non è stato possibile fare / non è stato notato". Tali valori svaniranno gradualmente in futuro.
* Smettere di trattare i membri che "non hanno fatto / non sono stati in grado di fare / non hanno notato" come colpevoli. Loro, e tutti noi, siamo vittime degli attaccanti che sfruttano le vulnerabilità, e da questo punto di vista siamo nella stessa posizione.
* Abbandonare l'approccio di risolvere con "misure perfette".
Il messaggio diventa quello di coinvolgere sviluppatori, manager, leader e persino i vertici aziendali per "cambiare il modo di vedere e interpretare le cose", ma è anche evidente quanto sia difficile.
Innanzitutto, come si dovrebbe cambiare?
Non ho la forza di indicare una risposta corretta, ma penso che ci sia un indizio proprio qui.
Cioè, forse dobbiamo rinunciare a cercare la risposta corretta in sé.
Ogni sviluppo software ha uno scopo. Il mondo del software non è forse diventato così complesso che cercare una "risposta corretta" per realizzarlo in modo sicuro e sicuro è ormai quasi impossibile?
Probabilmente ciò che c'è è un paradigma di sviluppo basato sul "cambiamento", in cui molti giocatori, ognuno a modo suo, provano e sbagliano, ricevono feedback, si scambiano informazioni e poi si ramificano e cambiano liberamente.
Nello sviluppo di sistemi, le risorse software create una volta vengono utilizzate per anni, a volte decenni.
Tuttavia, i software connessi a Internet, come lo sviluppo web, sono esposti a un ambiente che cambia in pochi mesi o anni.
Potrebbe accadere che le librerie o i framework utilizzati in uno sviluppo di 5 anni fa non siano più utilizzabili.
In questo caso, un paradigma di sviluppo che considera la libreria/framework inizialmente scelta come "risposta corretta" e "blocca" la versione ha più svantaggi.
Poiché il mondo esterno cambia continuamente, è normale che vengano scoperte vulnerabilità nelle librerie/framework che usiamo.
Se si blocca la versione, non si riesce a stare al passo con questi cambiamenti, e di conseguenza si pagano costi mentali e fisici enormi per gestire le vulnerabilità.
Pertanto, sento fortemente che spostarsi verso un paradigma di sviluppo che presuppone "cambiamento e capacità di adattarsi al cambiamento" porterà a risultati migliori a lungo termine.
Mi sono dilungato, ma è tutto.
----
Autore: Masahiko Sakamoto (appartiene al dipartimento di ricerca e sviluppo, si occupa dello sviluppo di strumenti diagnostici per applicazioni web utilizzati internamente)
* Mail : [email protected]
* Twitter : https://twitter.com/msakamoto_sf
* Facebook: https://www.facebook.com/masahiko.sakamoto.75
* GitHub : https://github.com/msakamoto-sf
Per opinioni o richieste riguardanti questo articolo, contattare Sakamoto.