Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095 — Отчёт об исследовании уязвимостей S2-045, S2-055 в Struts2 и уязвимостей CVE-2017-7525, CVE-2017-15095 в Jackson | Kitploit
Инструменты/GitHubGitHub/secureskytechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095
Анализ уязвимостейАнализ КодаЭксплуатация веб-приложенийСтатьи и ИсследованияОбучение и ОбразованиеArchived
GitHubsecureskytechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095

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

Отчёт об исследовании уязвимостей S2-045, S2-055 в Struts2 и уязвимостей CVE-2017-7525, CVE-2017-15095 в Jackson

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий
106218 лет назадПроверено Kitploit

Отчет об исследовании уязвимостей Struts2 S2-054, S2-055 и Jackson CVE-2017-7525, CVE-2017-15095

Мы опубликовали краткое резюме, которое легко читается. Рекомендуется тем, кто хочет сначала понять суть, или тем, у кого мало времени.

  • SSTtechlog 08 О S2-054, S2-055 и уязвимостях jackson-databind CVE-2017-7525, CVE-2017-15095 | SST SecureSky Technology
    • https://www.securesky-tech.com/column/techlog/08.html

1 декабря 2017 года было опубликовано обновление безопасности для Struts2. Ещё до публикации в списке рассылки ходили разговоры о том, что это связано с уязвимостью в Jackson (популярной JSON-библиотеке для Java), и автор, который использует Jackson в корпоративных системах и инструментах, также был заинтересован в конкретном содержании.

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

Фактически опубликованное содержание включало исправления следующих двух проблем безопасности. Только S2-055 затрагивает уязвимость jackson-databind, компонента Jackson.

  • S2-055 : https://cwiki.apache.org/confluence/display/WW/S2-055
    • Это исправление, соответствующее CVE-2017-7525 в jackson-databind.
    • В зависимостях Struts версия jackson-databind повышена до 2.9.2. Это также покрывает CVE-2017-15095, упомянутый ниже.
    • https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.14.1
  • S2-054 : https://cwiki.apache.org/confluence/display/WW/S2-054
    • Это исправление касается REST plugin, который использовал старую JSON-библиотеку JSON-lib ( http://json-lib.sourceforge.net/ ) – из-за выявленной проблемы DoS он был заменён на Jackson.

В REST plugin, по-видимому, ранее были встроены как обработчик на основе JSON-lib, так и обработчик на основе Jackson, и пользователь мог выбирать между ними. В S2-054 обработчик по умолчанию был переключён на Jackson, а в S2-055 версия Jackson, которая была старой, была обновлена до последней — такова, по-видимому, полная картина данного исправления.

Итак, что же такое уязвимость CVE-2017-7525? Поскольку сам автор часто использует Jackson при обработке JSON на Java, он решил исследовать эту проблему в выходные 2–3 декабря — эта статья является результатом.


Среда автора, использованная для проверки примеров кода:

  • ОС : Windows 10 Pro 64-bit
  • Java : Oracle JDK 1.8.0_92 64-bit
  • Groovy : 2.3.1

Об уязвимости jackson-databind CVE-2017-7525

В блоге Адама Кодила (Adam Caudill) опубликовано объяснение CVE-2017-7525.

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

Если кратко пересказать своими словами, jackson-databind предоставляет функцию (ObjectMapper class) для отображения JSON в объекты Java. Вызов ObjectMapper.enableDefaultTyping() позволяет выполнять отображение по именам классов, встроенным в JSON. Думаю, некоторые из вас уже почувствовали нехорошее предчувствие при мысли «можно задавать имена классов из входного JSON» — и именно это дурное предчувствие сбылось в CVE-2017-7525.

Прежде чем перейти к объяснению уязвимости, объясним, зачем вообще была реализована такая функция.

О функции ObjectMapper.enableDefaultTyping()

О базовом использовании десериализации с помощью jackson-databind смотрите следующий пример кода. (В этой статье для примеров кода Jackson используется Groovy. Удобно легко переключать версию jackson-databind с помощью @Grab.)

  • objectmapper-demo.groovy

В приведённом выше примере кода ключ "animal" просто может быть отображён на класс Animal. А как обстоит дело в следующем случае?```java class Zoo { Animal animal; }

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

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

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

root@kitploit:~
В этой конфигурации появляются два случая: когда содержимое ключа "animal" ссылается на класс Dog и когда на класс Cat. Следовательно, требуется дополнительная информация о том, какой класс использовать для маппинга.

Чтобы решить эту проблему, jackson-databind встроил собственную обработку, позволяющую встраивать имя класса для маппинга в JSON.
Например, как показано ниже, содержимое ключа "animal" помещается в массив, а в первом элементе указывается имя класса.```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}

Это позволяет ObjectMapper.readValue() распознавать содержимое ключа "animal" как класс Dog и выполнять маппинг.
Конечно, без дополнительных настроек невозможно определить, было ли содержимое ключа "animal" изначально массивом или содержало информацию об имени класса, специфичную для jackson-databind.
За переключение этого режима отвечает метод ObjectMapper.enableDefaultTyping().
Существует также способ определения с помощью аннотации @JsonTypeInfo в классе. Подробнее см. документацию Jackson по ссылке:

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

Ниже приведён пример кода с использованием метода ObjectMapper.enableDefaultTyping():

  • enable-default-type-demo.groovy

Обработка CVE-2017-7525 с помощью проверки чёрного списка имён классов

Как было показано выше, передача имени класса и его свойств в JSON позволяет, хотя и с определёнными ограничениями, создавать экземпляры произвольных классов с произвольными свойствами.
Именно эта уязвимость используется в CVE-2017-7525, и отправной точкой, вероятно, послужил следующий отчет:

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

В нём сообщается об опасности выполнения произвольного кода через манипуляции с именами классов в популярных библиотеках сериализации/десериализации Java, таких как Jackson, и перечислены конкретные опасные классы.

Неизвестно, связано ли это напрямую, но по датам вскоре после первого коммита в указанном репозитории был создан следующий Issue в jackson-databind, и началась работа над исправлением:

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

Как же выглядят данные JSON и код Java, эксплуатирующие эту уязвимость?
Подсказку можно найти в тестовом коде jackson-databind 2.8.9, в котором было выполнено исправление:

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

На основе этого тестового кода был подготовлен пример для проверки работы:

  • cve-2017-7525-check.groovy

При запуске с @Grab, указывающим версию 2.8.9, выводится your jackson version IS SAFE to CVE-2017-7525. Это связано с тем, что в версии 2.8.9 была добавлена проверка по чёрному списку для имён классов, экземпляры которых создаются.
Если же указать в @Grab версию 2.8.8, вывод будет следующим:``` your jackson version MAY NOT BE SAFE to CVE-2017-7525 com.fasterxml.jackson.databind.JsonMappingException: N/A at [Source: { "id" : 124, "obj" : [ "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", { "transletBytecodes" : [ "AAIAZQ==" ], "transletName" : "a.b", "outputProperties" : { } } ] } ; line: 9, column: 28] (through reference chain: Bean1599["obj"]->com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl["outputProperties"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277) (...) at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128) Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) at java.security.AccessController.doPrivileged(Native Method) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:399) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:451) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:116) ... 30 more null

root@kitploit:~
В выходных данных есть строка `at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)`.  
В этом примере кода выбрасывается исключение NullPointerException, но, судя по имени метода, можно предположить, что происходит какая-то обработка с побочными эффектами.

Чтобы собрать JSON, позволяющий успешно выполнить код, потребуется дополнительное исследование.  
В данной статье мы пока ограничимся этим введением, но если на других сайтах появятся дальнейшие исследовательские статьи, мы хотели бы добавить их сюда.

Кстати, где же реализован решающий чёрный список? Он находится в следующем классе:  
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L51

Оказывается, по состоянию на версию 2.8.9 в этом чёрном списке была утечка. Эта проблема обозначена как CVE-2017-15095.

### Исправление CVE-2017-15095, улучшающее чёрный список

Что касается устранения утечки в чёрном списке: сначала в https://github.com/FasterXML/jackson-databind/issues/1680 была добавлена строка `s.add("com.sun.rowset.JdbcRowSetImpl");`.  
После того как с этим изменением был выпущен релиз 2.9.0, в 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");

Таким образом, версии 2.8.10 / 2.9.1 были выпущены, и работа по устранению CVE-2017-15095 завершена.

Тестовый код для проверки работы черного списка в версии 2.8.10:

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

На основе этого тестового кода ниже представлен пример кода, адаптированный для проверки работы.

  • cve-2017-15095-check.groovy

Если запустить версию 2.8.10, которая считается исправленной, указав её в @Grab, то отобразится сообщение your jackson version IS SAFE to CVE-2017-15095. Затем, если запустить версию 2.8.9 до улучшения чёрного списка, указав её в @Grab, будет выведено следующее:``` your jackson version MAY NOT BE SAFE to CVE-2017-15095 com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.logging.FileHandler, problem: \tmp\foobar.txt.lck at [Source: { "v" : [ "java.util.logging.FileHandler", "/tmp/foobar.txt" ] } ; line: 5, column: 5] (through reference chain: PolyWrapper["v"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277) (...) Caused by: java.nio.file.NoSuchFileException: \tmp\foobar.txt.lck (...) at java.util.logging.FileHandler.openFiles(FileHandler.java:459) at java.util.logging.FileHandler.(FileHandler.java:292) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call1(AnnotatedConstructor.java:129) at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:318) ... 31 more null

root@kitploit:~
В предыдущих версиях имя класса `java.util.logging.FileHandler` обходило проверку в черном списке, и при создании экземпляра действительно предпринималась попытка открыть файл.  
В последующей версии черный список перехватывает его, и выбрасывается исключение `JsonMappingException`.

На данный момент черный список в версии 2.8.10 выглядит следующим образом. Строки, начинающиеся с комментария `[databind#1737]`, являются дополнительным черным списком для 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

### Об условиях подверженности уязвимости, реализуемости атаки и мерах защиты на стороне приложения

Если обобщить приведенные выше результаты, то для подверженности уязвимости jackson-databind необходимо выполнение следующих условий:
1. Используется jackson-databind 2.8.9 / 2.9.0 или ниже.
2. Для JSON, полученного из ненадёжного источника, выполняется одна из следующих операций:
   * Десериализация производится после вызова `ObjectMapper.enableDefaultTyping()`.
   * `ObjectMapper.enableDefaultTyping()` не вызывается, но в объявлении класса используется аннотация `@JsonTypeInfo`, позволяющая выполнять отображение, и производится десериализация.
   * Даже если приложение не использует это напрямую, фреймворк может автоматически выполнять десериализацию в зависимости от заголовка запроса `Accept` или расширения URL.
3. В classpath присутствуют классы ("Gadget"), которые могут быть использованы в уязвимостях Java-сериализации/десериализации.
4. В полях-членах целевого Java-класса для отображения используются такие типы, как `Object`, которые могут принимать классы-гаджеты.
   * Если в качестве типа используется несовместимый с классами-гаджетами специфичный для приложения bean-класс, то до фактического создания экземпляра произойдёт ошибка проверки типа, и он будет отброшен (за исключением случаев, когда сам bean-класс содержит уязвимость десериализации).

Действительная подверженность, по-видимому, сильно зависит от кода приложения: от способа использования / конфигурации `ObjectMapper`, от комбинаций аннотаций `@JsonTypeInfo`, а также от полей-членов целевого класса и т.д.

Кроме того, если имя ключа в JSON отсутствует в Java-классе, в который производится десериализация, Jackson просто игнорирует его.  
Поэтому для успешной атаки требуется адаптация к JSON конкретного приложения, и создать код атаки, который можно было бы использовать в нескольких приложениях, представляется очень сложным.

Далее, по поводу условия 4: при обычном стиле программирования поля Java-класса вряд ли будут специально объявлены как `Object`.  
Большинство классов, позволяющих выполнить произвольный код, скорее всего, несовместимы с создаваемыми в приложении bean-классами.

Исходя из вышесказанного, вероятность массовых атак или фактического нанесения ущерба (т.е. успешной атаки) с использованием этой уязвимости представляется низкой.

Что касается мер на стороне приложения: по условию 3, поскольку возможно использование классов, входящих в состав JDK, защита практически невозможна.  
Поэтому основная мера — обновление jackson-databind до последней версии.  
Если обновление jackson-databind невозможно, необходимо удалить вызовы `ObjectMapper.enableDefaultTyping()` и аннотации `@JsonTypeInfo`, переработав архитектуру так, чтобы не зависеть от них. Например, можно создать собственный сериализатор.

Однако если API уже используется как удалённо вызываемый, легко изменить JSON-формат не получится.  
Существуют настройки аннотации `@JsonTypeInfo`, позволяющие ограничить подклассы, то есть принимать только имена классов, ожидаемые программистом.  
Подробности см. в следующей документации:  
* JacksonPolymorphicDeserialization
  * https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

#### О целесообразности защиты с помощью черного списка и создании пользовательского десериализатора

jackson-databind 2.8.10 / 2.9.1 устраняют CVE-2017-7525 и CVE-2017-15095 с помощью черного списка.  
Однако, как ясно из проблем, связанных с OGNL в Struts2, защита с помощью черного списка не является абсолютной.  
(Лично автор считает, что для уровня так называемых «скрипткидди», которые просто используют инструменты сканирования, эта мера достаточно эффективна.)

Поэтому для действительно кардинальной защиты, по мнению автора, важно отключить или не использовать саму функцию встраивания информации о классе в JSON, такую как `ObjectMapper.enableDefaultTyping()`.

Но как же тогда решить проблему, которую изначально пытался решить `ObjectMapper.enableDefaultTyping()`?

У самого автора нет альтернативного решения, которое можно было бы назвать правильным.  
Суть проблемы, на мой взгляд, в том, чтобы иметь возможность выполнять отображение, когда целевой Java-класс неоднозначен, не полагаясь на ненадёжный JSON.  
Подходом, который может это обеспечить, вероятно, является создание пользовательского десериализатора.  
Пользовательский десериализатор позволяет программно управлять создаваемым объектом, получая JSON во время десериализации.

Например, при получении `{"animal":{"name":"dog1","barkVolume":1.2}}` можно определить: «есть ключ `barkVolume`, значит создаём экземпляр класса Dog».  
А при получении `{"animal":{"name":"cat1","likesCream":true,"lives":10}}` — «есть ключи `likesCream` и `lives`, значит создаём экземпляр класса Cat».  
Это избавляет от необходимости встраивать имя класса в JSON.

Лично автору формат JSON со встроенным именем класса кажется создающим проблемы для совместимости с другими языками / библиотеками (если кто-нибудь знает аналогичное расширение в других языках или библиотеках, сообщите).  
При условии взаимодействия с другими системами, вероятно, более правильным будет создание пользовательского десериализатора на стороне Jackson, а не просьба встраивать имя класса специально для Jackson.

Думаю, есть и другие решения, поэтому автор будет рад, если читатели предложат свои варианты.  
(Как крайний пример, существует подход — десериализовать всё в `Map<String, Object>` или `List<String, Object>` вместо отображения на отдельные классы.)

Нашёл несколько статей для справки по созданию пользовательского десериализатора (на английском), привожу ссылки:
* 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 jackson-databind (2.8.x, 2.9.x):
* https://fasterxml.github.io/jackson-databind/javadoc/2.8/
* https://fasterxml.github.io/jackson-databind/javadoc/2.9/

Автор также подготовил пример кода пользовательского десериализатора. Надеюсь, он послужит подсказкой.
* [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)

## Об S2-055

До сих пор мы рассматривали уязвимость самого Jackson. Теперь посмотрим, как она на самом деле влияет на REST plugin Struts2. Мы проверили это с помощью struts2-rest-showcase, входящего в Struts2.

По поводу использования Struts REST plugin см.:
* http://struts.apache.org/plugins/rest/

### В REST plugin Struts2 не вызывается ObjectMapper.enableDefaultTyping()

Между прочим, в CVE-2017-7525 к условиям фактической уязвимости относились:
* Для JSON, полученного из ненадёжного источника, выполняется одна из следующих операций:
  * Десериализация производится после вызова `ObjectMapper.enableDefaultTyping()`.
  * `ObjectMapper.enableDefaultTyping()` не вызывается, но в объявлении класса используется аннотация `@JsonTypeInfo`, позволяющая выполнять отображение, и производится десериализация.

Мы проверили, есть ли в REST plugin Struts2 код, соответствующий этим условиям, и обнаружили, что ни то, ни другое не присутствует.  
Фактически, в версии 2.5.14 (до исправления) ни `ObjectMapper.enableDefaultTyping()`, ни `@JsonTypeInfo` не используются ни в самом REST plugin, ни во всём дереве исходников Struts2 по результатам grep.
* https://github.com/apache/struts/tree/STRUTS_2_5_14

Во всём дереве исходников Struts2 Jackson ObjectMapper используется только в классе `org.apache.struts2.rest.handler.JacksonLibHandler`. Проверив исходный код, в версии 2.5.14 действительно не обнаружили вызова `ObjectMapper.enableDefaultTyping()`.
* https://github.com/apache/struts/blob/STRUTS_2_5_14/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonLibHandler.java
  * В версии 2.5.14.1 содержимое этого Java-файла не изменилось.

Таким образом, сам REST plugin в версии 2.5.14, по-видимому, не был подвержен CVE-2017-7525.  
Уязвимость возможна только в том случае, если в приложении в поле класса, отображаемого на JSON, установлена аннотация `@JsonTypeInfo`.  
Поэтому в последующей проверке с помощью struts2-rest-showcase мы установили `@JsonTypeInfo` в поле целевого класса, добавленного на стороне приложения.

Кстати, в Struts2 существует также JSON plugin.
* http://struts.apache.org/plugins/json/
* Если посмотреть исходники JSON plugin, в pom.xml нет зависимостей от других JSON-библиотек.
* Похоже, он реализует обработку JSON самостоятельно.
* https://github.com/apache/struts/tree/STRUTS_2_5_14/plugins/json
* Поэтому уязвимость jackson-databind, вероятно, не затрагивает JSON plugin.

### Адаптация struts2-rest-showcase для Jackson

struts2-rest-showcase — это пример реализации CRUD для класса Order с помощью REST plugin. Мы добавим в него классы Zoo / Animal / Cat / Dog, использовавшиеся в примере кода для уязвимости Jackson, а также ZooController для обработки CRUD этих классов в формате JSON.

Полный исходный код приведён ниже (сборка и запуск проверены на JDK8):
* [rest-showcase](https://github.com/SecureSkyTechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095/tree/master/rest-showcase)

Основные изменения:
* Порт прослушивания плагина jetty-maven-plugin изменён на 18088 (`mvn jetty:run`).
* Добавлены зависимости jackson-core, jackson-databind.
* Добавлены классы Zoo, Animal (абстрактный), Dog, Cat. В качестве сервисного слоя добавлен класс ZooService.
* Добавлен ZooController с минимальным CRUD (JSP для представления опущены).
* В struts.xml обработчик для JSON изменён на JacksonLibHandler.
* Встроен maven-wrapper, чтобы можно было собрать и запустить с помощью mvnw / mvnw.bat при наличии только JDK.

Сборка и запуск:
1. Клонируйте репозиторий, перейдите в каталог rest-showcase и выполните `mvnw jetty:run`. (При первом запуске будет загружаться Maven, поэтому может потребоваться несколько минут или даже более 10 минут, будьте внимательны.)
2. Откройте http://localhost:18088/struts2-rest-showcase/ — если отобразится список Order, всё успешно.
3. Для остановки выполнения нажмите Ctrl-C.
4. Если вы изменили Java-файлы, остановитесь с помощью Ctrl-C и снова выполните `mvnw jetty:run`.

Проверка с помощью команды curl (при условии использования localhost:8080 в качестве локального HTTP-прокси):```
一覧取得:
curl -v -x localhost:8080 -H "Accept: application/json" "http://localhost:18088/struts2-rest-showcase/zoo"

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

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

В Zoo.java репозитория поле animal, как показано ниже, @JsonTypeInfo закомментировано, и имеет тип абстрактного класса Animal.```java //@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public Animal animal; //public Object animal;

root@kitploit:~
Здесь мы попробуем отправить JSON-запрос методом POST и вызвать метод 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 является абстрактным, поэтому не удалось создать экземпляр.``` Can not construct instance of org.demo.rest.example.Animal: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

root@kitploit:~
Там убираем комментарий из поля `animal` и активируем `@JsonTypeInfo`. Останавливаем веб-приложение с помощью 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;

Теперь можно внедрить имя класса в JSON. Попробуем отправить POST-запрос с JSON, содержащим имя класса, с помощью следующей команды 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}]}'

root@kitploit:~
→ `HTTP/1.1 201 Created` が返されます。一覧取得をしてみると、たしかに追加されたことを確認できます。

### Struts2 REST plugin 2.5.14 で CVE-2017-7525 を確認

リポジトリの pom.xml では `<parent>` の struts のartifactで、バージョンを 2.5.14 を指定しているため、そのままではCVE-2017-7525に脆弱です。
それを確認するため、以下のcurlコマンドを実行してみます。クラス名とその中身は cve-2017-7525-check.groovy を参考にしていますので、jackson-databind 2.8.8 の時と同じ反応が返されれば、脆弱であると考えられます。```
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]

root@kitploit:~
Тип поля `animal` — это класс Animal, который не является подтипом класса com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl, поэтому, похоже, возникло исключение IllegalArgumentException.

Теперь изменим поле `animal` в Zoo.java на тип Object и снова запустим `mvnw jetty:run`.```java
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
    //public Animal animal;
    public Object animal;

Теперь при повторном выполнении команды curl возникло исключение, содержащее следующий стек вызовов.``` Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) ~[?:1.8.0_92]

root@kitploit:~
Это такое же исключение, как и при проверке с помощью cve-2017-7525-check.groovy, в уязвимом случае.

Таким образом, мы подтвердили наличие уязвимости CVE-2017-7525 в jackson-databind в Struts2 REST plugin 2.5.14.

Также мы выяснили, что помимо `@JsonTypeInfo` необходимо использовать тип Object.

Ниже приведено личное мнение автора: при создании REST API, в классах данных вряд ли является обычной практикой специально указывать в качестве типа поля класс Object или классы, совместимые с классами, используемыми в качестве гаджетов в уязвимостях десериализации Java. Поэтому я считаю, что на практике успешно провести атаку будет сложно.

### Проверка исправления в Struts2 REST plugin 2.5.14.1

Итак, проверим, была ли исправлена уязвимость в версии 2.5.14.1.

Изменим версию артефакта `<parent>` в pom.xml на 2.5.14.1, перезапустим с помощью `mvnw jetty:run` и выполним ту же команду 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":["com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",{"transletBytecodes":["AAIAZQ=="],"transletName":"a.b","outputProperties":{}}]}'

→ Произошло исключение, содержащее следующее сообщение об ошибке.``` com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl: Illegal type (com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl) to deserialize: prevented for security reasons

root@kitploit:~
Это то же самое исключение после исправления уязвимости, что и при проверке в `cve-2017-7525-check.groovy`.

Если открыть в IDE, поддерживающей Maven (например, Eclipse), и проверить версию jackson-databind после разрешения зависимостей, можно убедиться, что она действительно равна 2.9.2. Если IDE нет, можно выполнить `mvnw help:effective-pom`, чтобы вывести итоговый POM, и найти в нём `jackson-databind` — будет видно, что используется версия 2.9.2.

Описание CVE-2017-15095 опускаю, но из сказанного выше видно, что в версии 2.5.14.1 удалось устранить уязвимость jackson-databind.

### PoC для S2-055

※ Добавлено 2017-12-08

Опубликована статья с анализом S2-055 и отчёт о PoC.
* Среда для S2-055: построение и анализ | Блог NSFOCUS
  * http://blog.nsfocus.net/s2-055/

Если почитать с помощью Google Translate, кажется, что мнения совпадают относительно условий возникновения и реализуемости атаки.

Также показан PoC с HTTP-трафиком, запускающим калькулятор на модифицированном rest-showcase.

Заимствовав только часть 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)
(...)

Как и в случае с cve-2017-7525-check.groovy, метод run() сработал и вызвал NullPointerException. Однако калькулятор не запустился.

Хотя это лишь предположение, TemplatesImpl от xalan — это класс внутри Java, поэтому возможно, что в Java были внесены какие-то исправления. Или, возможно, для успешной атаки требуются более наивные условия.

В статье PoC не указана версия Java, использованная для проверки, и мы не смогли запустить калькулятор. Если появится дополнительная информация, я хотел бы проверить снова.

О S2-054

До этого момента, начиная с S2-055, были представлены в основном уязвимости Jackson CVE-2017-7525 и CVE-2017-15095. Теперь я кратко обобщу результаты исследования ситуации с другой уязвимостью S2-054.

Если говорить о заключении, на момент написания этой статьи (2017-12-03) конкретной информации найдено не было. PoC для проверки наличия уязвимости также не найдены.

На странице раскрытия информации о S2-054 поясняется, что в плагине REST используется устаревшая библиотека JSON-lib, которая уязвима и позволяет выполнить DoS-атаку с помощью злонамеренного запроса со специально сформированной полезной нагрузкой JSON.

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

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

На странице версии 2.5.14.1, выпущенной в ответ на эту проблему, в качестве соответствующего тикета JIRA указан WW-4892.

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

Я проверил WW-4892, но нигде не упоминается DoS или уязвимость JSON-lib. Даже в описании сказано только, что JSON-lib устарел и не поддерживается, поэтому дефолтный обработчик заменён на Jackson.

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

Pull request на GitHub выглядит следующим образом, но в нём также нет конкретных упоминаний о проблемах с JSON-lib.

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

Итак, я решил посмотреть на сторону JSON-lib. Официальный сайт:

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

Кроме того, по состоянию на 2017 год, похоже, что проект управляется на GitHub.

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

Какая из них новее? На момент написания этой статьи на GitHub релизов нет. Поэтому я проверил статус регистрации в репозитории Maven Central. Поиск по "json-lib" выдаёт несколько groupId.

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

Чтобы узнать, какой groupId правильный, я проверил pom.xml плагина REST в Struts2 2.5.14.1.

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

Посмотрев версии релизов groupId = net.sf.json-lib, artifactId = json-lib, видно, что последний релиз — версия 2.4 от декабря 2010 года.

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

Проверив страницу на sourceforge, также видно, что последний релиз — версия 2.4 от декабря 2012 года.

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

На самом деле, на GitHub нет тегов релизов, но если проследить историю коммитов, есть коммит релиза версии 2.4 от декабря 2010 года. После этого pull request'ы принимаются, но новых релизов не было.

Просмотрев issues на GitHub (включая закрытые), я не нашёл заголовков, связанных с DoS.

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

Наконец, посмотрев тикеты на sourceforge, я наткнулся на тикеты о проблеме утечки памяти. Похоже, ни один из них ещё не исправлен.

  • Json-lib / Bugs / #124 memory leak in 2.2.2, not fixed correctly in 2.4
    • https://sourceforge.net/p/json-lib/bugs/124/
  • Json-lib / Bugs / #118 Possible memory leak in Tomcat
    • https://sourceforge.net/p/json-lib/bugs/118/
  • → Я понял, что до версии 2.2 была проблема утечки памяти из-за использования ThreadLocal, а в версии 2.4 это было исправлено с помощью SoftReference, но это не было фундаментальным решением.

В итоге я смог добраться до того, что проблема утечки памяти, похоже, остаётся, но из-за ограничений моих навыков и времени я не смог провести дальнейшее исследование. Если у кого-то есть конкретная информация о том, что в этом шаблоне JSON произошла утечка памяти или DoS, буду очень благодарен за разъяснения.

Справочно: Пример реагирования Spring Security (июнь 2017)

Поскольку Jackson используется во многих открытых проектах, существуют и другие библиотеки и фреймворки, которые были затронуты этой уязвимостью. В качестве примера, Spring Security из продуктов Pivotal был затронут, и информация была опубликована в июне 2017 года.

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

Что касается других, например, самого Spring Framework, по крайней мере на https://pivotal.io/security/ не публиковалась информация об обновлениях, связанных с Jackson.

Однако это не значит, что можно расслабиться. Jackson в Spring Framework изначально спроектирован с высокой степенью настраиваемости, и можно создавать ObjectMapper, специфичный для приложения. Стоит на всякий случай проверить, не настроены ли в приложении какие-либо настройки/функции Jackson? Не используется ли @JsonTypeInfo?

Краткая хронология CVE-2017-7525, CVE-2017-15095

Я составил хронологию, используя информацию из GitHub Issue/релизов jackson-databind, bugzilla RedHat и других ссылок. Если есть ошибки, пожалуйста, не стесняйтесь указывать автору.

2017-04

  • В https://github.com/FasterXML/jackson-databind/issues/1599 продвигалась начальная доработка. По соображениям управления версиями были выпущены следующие версии как hot-fix:
    • 2.7.9.1: hot-fix для 2.7.9
    • 2.8.8.1: hot-fix для 2.8.8
    • Также был выпущен 2.9.0.pr3.

2017-06

  • Выпущена версия 2.8.9, включающая другие исправления.
  • В следующем bugzilla продвигается поддержка в продуктах RedHat.
    • https://bugzilla.redhat.com/show_bug.cgi?id=1462702

2017-07

  • Для уже неподдерживаемой ветки 2.6 (версия 2.6.7) выпущен hot-fix 2.6.7.1 по этой проблеме.
  • RedHat опубликовал информацию о CVE-2017-7525.
    • https://access.redhat.com/security/cve/CVE-2017-7525

На тот момент список black-list был следующим.```java s.add("org.apache.commons.collections.functors.InvokerTransformer"); s.add("org.apache.commons.collections.functors.InstantiateTransformer"); s.add("org.apache.commons.collections4.functors.InvokerTransformer"); s.add("org.apache.commons.collections4.functors.InstantiateTransformer"); s.add("org.codehaus.groovy.runtime.ConvertedClosure"); s.add("org.codehaus.groovy.runtime.MethodClosure"); s.add("org.springframework.beans.factory.ObjectFactory"); s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); s.add("org.apache.xalan.xsltc.trax.TemplatesImpl");

root@kitploit:~
Здесь, в том же месяце, был выпущен 2.9.0 как дополнительное исправление для борьбы с черным списком.
* https://github.com/FasterXML/jackson-databind/issues/1680

Это было добавлено:```java
s.add("com.sun.rowset.JdbcRowSetImpl");

Кроме того, в том же месяце открывается следующий Issue:

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

→ В black-list добавляется следующее, и это включается в версии 2.8.10 / 2.9.1.```java // [databind#1737]; JDK provided s.add("java.util.logging.FileHandler"); s.add("java.rmi.server.UnicastRemoteObject"); // [databind#1737]; 3rd party s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean"); s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource");

root@kitploit:~
### 2017-август

* Выпущена версия 2.8.10, соответствующая #1680, #1737.
* Также в августе был открыт следующий Issue, и ведется комплексная работа по CVE-2017-7525.
  * https://github.com/FasterXML/jackson-databind/issues/1723
* В блоге Адама Кауделла опубликовано описание эксплуатации CVE-2017-7525.
  * https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

### 2017-сентябрь

* Выпущена версия 2.9.1, соответствующая #1737.

### 2017-октябрь

В следующей bugzilla начинается работа над применением черного списка из последних версий 2.8.10 / 2.9.1 для CVE-2017-15095, поскольку исправления CVE-2017-7525 в версиях 2.8.9 / 2.9.0 оказались недостаточными.
* https://bugzilla.redhat.com/show_bug.cgi?id=1506612

### 2017-ноябрь

* RedHat опубликовала информацию о CVE-2017-15095.
  * https://access.redhat.com/security/cve/cve-2017-15095

* В Issue jackson-databind также ведется обсуждение статуса CVE-2017-15095.
  * https://github.com/FasterXML/jackson-databind/issues/1847
  * Ответ: исправлено в версиях 2.8.10 / 2.9.1.

### 2017-декабрь

* В блоге разработчиков облачного WAF Scutum опубликована статья с пояснениями.
  * https://www.scutum.jp/information/waf_tech_blog/2017/12/waf-blog-052.html
  * В этой статье отмечается, что в черном списке версии 2.9.3 есть недочеты, связанные с классами Spring, которые не являются критичными, но возможно, потребуется обновление.
  * Также обсуждается вопрос, лежит ли ответственность за эту уязвимость на библиотеке или на приложении.

## О будущих тенденциях уязвимостей, связанных с Java serialize/deserialize

Создается впечатление, что за последние два года количество информации об уязвимостях, связанных с Java serialize/deserialize, увеличилось.
В качестве примера, информация об уязвимостях продуктов Pivotal, включая Spring, публикуется на https://pivotal.io/security/, и в 2017 году, помимо CVE-2017-4995, были опубликованы следующие уязвимости:

* https://pivotal.io/security/cve-2017-8045
  * RCE из-за проблемы десериализации `org.springframework.amqp.core.Message` в Spring AMQP
* https://pivotal.io/security/cve-2017-8046
  * RCE из-за недостатков обработки JSON в методе PATCH в Spring Data REST

Поскольку это уязвимости, которые легко приводят к RCE, как атакующие, так и исследователи уязвимостей в настоящее время уделяют большое внимание Java serialize/deserialize.
В ближайшие несколько лет, вероятно, будут продолжаться сообщения об уязвимостях, связанных с обработкой serialize/deserialize.
Хотя Jackson не является исключением, в современной разработке, где обмен данными через удаленные API стал обычным делом, а библиотеки повышают эффективность, полный отказ от serialize/deserialize или их самостоятельная реализация с нуля на практике во многих случаях невозможны.
Лично я считаю, что ключевым моментом является создание гибкой среды разработки и культуры, позволяющей как можно быстрее обновлять библиотеки при обнаружении уязвимостей.

Поскольку у меня были мысли о том, как в будущем относиться к уязвимостям в зависимых промежуточных программных обеспечениях, библиотеках и фреймворках, я решил написать ниже свои впечатления.

## Впечатления

Когда я увидел информацию о публикации S2-054, 055 и о том, что на них влияет уязвимость Jackson, я был довольно шокирован.
Потому что несколькими днями ранее коллега спросил меня: «Какая библиотека рекомендуется для парсинга JSON на Java?», и я с гордым видом ответил: «Jackson широко используется в OSS, имеет хорошую репутацию, и в Google можно найти много статей и QA, поэтому я рекомендую его».
Я сам использовал Jackson при разработке внутренних инструментов компании и ощущал его удобство.
Однако на тот момент я не знал о CVE-2017-7525 и был полностью спокоен, потому что Jackson широко используется в OSS и имеет много пользователей.

Тут другой коллега нашел блог Адама Кауделла и рассказал мне о существовании CVE-2017-7525. Через несколько дней после того, как я с гордым видом рекомендовал Jackson, Struts2 выпустил обновление из-за уязвимости Jackson, и притом сама уязвимость Jackson была исправлена несколько месяцев назад. Как инженер, работающий в сфере безопасности, я не могу оправдаться, если меня упрекнут в том, что я пренебрег сбором информации об уязвимостях используемой мной библиотеки (хотя это действительно так).

Поэтому в последние несколько дней мое психическое состояние было ужасным (повышение артериального давления и пульса, дрожь в руках, слезы без причины, учащенное сердцебиение и т. д.). Чтобы как-то справиться, я решил для начала узнать, что такое CVE-2017-7525 и в какой ситуации находится Jackson, и провел выходные, занимаясь исследованием и написанием этой статьи.

Оглядываясь назад, я остро осознаю, что, сосредоточившись на разработке, трудно уделять внимание информации об обновлениях зависимых библиотек.
В непрерывном потоке задач разработки практически невозможно полностью изучить функциональность и качество, включая уязвимости, всех используемых библиотек.
С другой стороны, требования к разработке становятся все выше, и реализовать все самостоятельно также практически невозможно.
Где-то приходится «доверять» используемым библиотекам и повышать эффективность разработки.
Однако отслеживать информацию об обновлениях всех используемых инструментов и библиотек в повседневной разработке и следить за тем, не содержат ли они исправлений проблем безопасности, также очень сложно.
Конечно, я знаю, что для решения этой задачи существуют сервисы, которые регистрируют используемые инструменты и библиотеки и рассылают информацию об их обновлениях.

Из ухудшения своего психического состояния я понял, что у меня очень сильное «чувство вины и самообвинения за то, что не сделал».
Я навешивал на себя негативный ярлык: «Как инженер по безопасности, я не знал об уязвимости библиотеки, которую сам использовал...».
Даже обычные разработчики, не связанные с индустрией безопасности, вероятно, испытывают сожаление или беспокойство, например: «Если бы я тогда не предложил Struts2...» или «Нужно более тщательно управлять жизненным циклом библиотек/фреймворков (= я беспокоюсь о текущем положении дел, когда это не делается)».

Если попытаться «решить» эти «проблемы» в лоб, придется собирать информацию об уязвимостях по одной, проверять исходный код и функциональность планируемых к использованию библиотек и фреймворков, тщательно выяснять, можно ли их считать де-факто стандартом, а после начала эксплуатации строго управлять жизненным циклом.

Однако возможно ли в современных разнообразных условиях разработки вообще применять такой подход «перестраховщика»?

Прочитав эту статью, я подумал, что время, когда «то, что не было сделано / не было возможным сделать / не было замечено» рассматривалось как причина или виновник, а его устранение (= сделать возможным) считалось «решением проблемы», возможно, уже прошло.
В такой культуре, если только человек не идеален, разработчик будет бесконечно сталкиваться со своим «не сделанным, не сделанным, не замеченным».
Поскольку идеальных людей нет, я думаю, что без очень сильной психики это не выдержать.

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

Подавляющее большинство разработчиков, как правило, добросовестно и добросовестно занимаются разработкой. На этом этапе они уже находятся в положительном состоянии.
«Отсутствие управления жизненным циклом библиотек/фреймворков» или «отсутствие сбора и мониторинга информации об уязвимостях используемых библиотек» — это просто неделание, состояние ни плюс, ни минус.
Неужели не печально, что из-за существования атакующего «не сделанное» становится «не возможным / не замеченным» и превращается в минус?

Нельзя отрицать, что на ценности «перестраховки» влияет современное японское общество и корпоративная культура.
Действительно, есть случаи, когда из-за внедрения уязвимостей, таких как SQL-инъекции, происходят атаки, и в суде рассматриваются дела о привлечении к ответственности компании-разработчика.
Бывают случаи, когда невнимательность на работе приводит к серьезным авариям.

Однако, если сводить все это к проблеме «компании-разработчика / разработчика», мне кажется, что вся IT-разработка будет парализована.
Действительно плохи — это атакующие, использующие уязвимости.
С этой точки зрения, разве разработчики и компании-разработчики, которые «не сделали / не смогли / не заметили», скорее жертвы, чем преступники?
Если так, то я strongly believe, что важно не указывать жертве: «Ты плохой, потому что не сделал / не смог / не заметил», а протянуть теплую руку, чтобы идти вместе, с целью совместного движения: «Давай сделаем это безопаснее, давай улучшим, будем стараться вместе», соревнуясь и используя друг друга в своих областях экспертизы.
Тогда компании-разработчики и разработчики смогут спокойно заниматься устранением уязвимостей, и в дальнейшем им будет легче активно развиваться на основе спокойствия.
Если разработка будет спокойной, светлой и активной, в результате увеличится количество инновационных результатов, и японское общество станет богаче, не так ли?

Лично я strongly feel, что в будущем было бы хорошо, если бы распространились следующие взгляды:

* Разработчики на местах
  * «Использование библиотеки с уязвимостью» само по себе не является минусом.
  * Минус создают атакующие, использующие уязвимости, и сама культура, оценивающая это как минус.
  * Ежедневная добросовестная работа и разработка — это уже достаточный плюс.
  * Устранение уязвимостей — это не работа по возвращению минуса к нулю, а положительная работа по улучшению ежедневных результатов разработки, делая их более безопасными.
* Менеджеры, руководители и высшее руководство, объединяющие разработчиков
  * Не оценивайте «то, что не было сделано / не было возможным сделать / не было замечено» как минус. Такая ценность будет постепенно исчезать.
  * Перестаньте обращаться с членами команды, которые «не сделали / не смогли / не заметили», как с виновными. Они, и мы все, — жертвы атакующих, использующих уязвимости, и с этой точки зрения мы на одной стороне.
  * Прекратите подход к решению «полными мерами».

Это касается изменения «взгляда на вещи / способа восприятия», вовлекая разработчиков, менеджеров, руководителей и высшее руководство, что, очевидно, очень сложно.
Как же это изменить?
У меня недостаточно сил, чтобы дать правильный ответ, но я думаю, что в этом есть одна подсказка.
А именно: возможно, сам поиск правильного ответа уже нужно прекратить.
У любой разработки программного обеспечения есть какая-то цель. Поиск «правильного ответа» для ее безопасной и защищенной реализации стал настолько сложным, что мир программного обеспечения стал слишком сложным.
Возможно, там находится парадигма разработки, основанная на «изменении», где множество игроков по-своему пробуют и ошибаются, получают обратную связь, обмениваются информацией и свободно ветвятся и изменяются.

В системной разработке созданные однажды программные активы используются в течение нескольких лет, а иногда и десятилетий.
Однако программное обеспечение, подключенное к Интернету, особенно веб-разработка, сталкивается со средой, которая меняется за несколько месяцев или лет.
Библиотеки и фреймворки, использованные при разработке 5 лет назад, могут стать непригодными.
В таком случае парадигма разработки, при которой первоначально созданные библиотеки/фреймворки считаются «правильными» и их версии «фиксируются», имеет больше недостатков.
Внешний мир постоянно меняется, поэтому обнаружение уязвимостей в используемых библиотеках/фреймворках — это обычное дело.
Если зафиксировать версии, вы не сможете идти в ногу с этими изменениями, и в результате придется платить огромные умственные и физические затраты на устранение уязвимостей.
Поэтому я strongly believe, что переход к парадигме разработки, основанной на «изменении / способности следовать за изменениями», в долгосрочной перспективе приведет к лучшим результатам.

Статья получилась длинной, но это всё.

----
Автор: Масахико Сакамото (отдел исследований и разработок, занимается разработкой инструментов диагностики веб-приложений, используемых внутри компании)
* Почта: [email protected]
* Twitter: https://twitter.com/msakamoto_sf
* Facebook: https://www.facebook.com/masahiko.sakamoto.75
* GitHub: https://github.com/msakamoto-sf

По вопросам и предложениям по данной статье обращайтесь к Сакамото.
Скачать инструмент