Последние пару дней (и ночей) я изучал новую (чрезвычайно опасную) уязвимость в log4j2 под названием Log4Shell.
Это касается всех версий log4j-core от 2.0-beta9 до 2.14.1, и это очень серьезная проблема.
Эта уязвимость позволяет злоумышленнику удаленно выполнить код в вашей системе с возможностью получить полный контроль над базовыми серверами.
Log4J долгое время был наиболее часто используемым фреймворком для ведения журналов в среде Java. Он чрезвычайно широко используется, и у этой атаки есть самый широкий триггер, который вы можете себе представить: ей нужно что-то зарегистрировать.
Вредоносный код может быть доставлен МНОГИМИ способами, если они попадают в оператор логирования. Через управляемые пользователем поля, HTTP-запросы, URL-адреса, ВСЕ что угодно.
Атака
После написания некоторого кода (вредоносный встроенный сервер LDAP) я смог воспроизвести атаку RCE («Удаленное выполнение кода») даже на самый простой проект.
Вот пример: простая конечная точка REST в стартовом проекте Spring Boot с единственной строкой регистрации.
Как видите, код загружает и выполняет файл классов, распечатывающего сообщение, который я загружаю с вредоносного сервера LDAP (работающего удаленно).
Я не буду делиться вредоносным кодом, он слишком прост в настройке и злоупотреблении. Есть лучшие и более простые способы проверить, уязвимо ли ваше программное обеспечение. Например, с помощью этого инструмента от Trend Micro.
Возможные риски
Риски этой уязвимости:
Потеря ВСЕХ данных
Программы-вымогатели
Бэкдоры
Ботнет
Потеря ключей / секретов AWS / Kubernetes
И этот список можно продолжать, продолжать и продолжать ...
Исправление
Вариант 1. Если вы еще этого не сделали: обновите log4j-core до версии> = 2.16.0.
Используйте версию 2.16.0 вместо 2.15.0, это решает проблему более строго.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.16.0</version>
</dependency>
Сделайте то же самое для всех транзитивных зависимостей (!).
Вариант 2. Другой вариант - запустить JRE с помощью.
-Dlog4j2.formatMsgNoLookups=true
Но будьте ВНИМАТЕЛЬНЫ: этот флаг был реализован в log4j2, начиная с версии 2.10.0. Если у вас более старая версия, это не сработает.
Вариант 3. удалить JndiLookup.class
Также можно удалить org.apache.logging.log4j.core.lookup.JndiLookup
из файлов JAR log4j. Я не рекомендую делать это, если вы хотите пойти по этому пути. Вероятно, проще просто перейти на>=2.16.0.
Не вариант:
Более новая версия Java
Свойство: com.sun.jndi.ldap.object.trustURLCodebase
Я видел в Интернете предложения, что «новые» версии Java не затронуты, но это не так. Даже с последними версиями Java и с установленным значением trustURLCodebase
=false
все равно можно украсть данные (например, переменные среды) и десериализовать объекты, уже известные загрузчику классов. Это упрощает запуск других десериализационных RCE.
Это может быть немного сложнее/безопаснее в более новой версии Java, но это определенно НЕ исправление.
Чтобы показать это, я взял последнюю версию Java 8 (1.8.311) и использую десериализацию log4j2 для создания чего-то, что открывает калькулятор на моем MacBook с использованием других классов, известных уязвимой цели:
Опять же: загружаемый объект все еще десериализуется в последней версии Java.
Вы были скомпрометированы
Отлично, вы обновили и устранили проблему. Однако: не останавливайтесь на достигнутом, это всего лишь первый шаг.
Эта утечка была известна и использовалась в течение долгого времени, вероятно, за несколько недель до того, как стала достоянием общественности. И если даже я смогу использовать его за пару минут с помощью собственного вредоносного кода: любой сможет.
Итак, вот что еще вам нужно сделать:
Шаг 1. Обновите и устраните утечку
Шаг 2: Предполагая, что все украдено: замените все ключи
Шаг 3: Войдите в вашу систему и проанализируйте записи в лог файлах
Шаг 4: Если вы настроили инфраструктуру как код: восстановите вашу среду
Шаг 4. Повторно разверните все свои приложения
Мы ДОЛЖНЫ отнестись к этому серьезно. Мне не хотелось бы услышать или прочитать через пару месяцев, что какая-то компания забыла исправить свое программное обеспечение.
Присоединяйтесь к нашей встрече
«Понимание Log4Shell: уязвимости, атаки и способы их устранения (прямая трансляция)»
Среда, 15 декабря 2021 г., 20:00 CET
https://www.meetup.com/OpenValue/events/282682468/
Примечание переводчика. К сожалению встреча уже прошла. Но есть презентация ее организаторов и вероятно будет выложена запись.
Дальнейшее чтение:
Вот несколько ссылок для получения дополнительной информации:
Комментарии (28)
ufoton
16.12.2021 12:25+21) -Dlog4j2.formatMsgNoLookups=true уже не работает.
2) Не для всех проектов можно использовать 2.16.0 поэтому есть 2.12.2sshikov
16.12.2021 17:56Не для всех проектов можно использовать вообще какую-либо другую версию, потому что вы далеко не всегда можете легко пересобрать код из исходников, а классы log4j вполне могут лежать запакованными в jar какого-то другого проекта. Т.е. только полное сканирование одним из доступных уже сканеров покажет, уязвима ли ваша система.
Скажем, в моем случае уязвимыми являются классы из hive-common версии 3.*. А они входят в состав большого продукта под названием Hadoop, и даже если он собственной сборки, собрать его не так просто и быстро, и я это сделать не могу. Поэтому на сегодня -Dlog4j2.formatMsgNoLookups=true чуть ли не единственный возможный вариант, не считая более экзотических пока решений. Ну благо, у нас интранет, и внешние атаки не имеют места.ufoton
16.12.2021 19:52Тем хуже. Откуда данный попадают в hadoop. есть ли гарантия, что не прилетит сообщение, которое сработает? По мне основная проблема этой уязвимости, что непонятно где и как это может аукнутся.
Как пример в одном стороннем компоненте индексатор почты сделан с помощью эластика с проблемной версией log4j.sshikov
16.12.2021 20:06Да, в целом все непонятно, если у вас не тупо веб приложение. Т.е. я например не знаю (ну, на самом деле это я просто исходники пока не смотрел), в каком месте и что Hive (где используется log4j2) вообще логирует. Но я гляжу в логи, и судя по ним — ничего такого, где были бы внешние данные. Оно практически вообще ничего не логирует. Т.е. я могу, например, подсунуть Hive запрос, где в комментариях или константах будет ${jndi}, только запросы не логируются.
Кроме того, чтобы оно «сработало», это должен быть атакующий внутри. А у атакующего внутри, как правило, есть более простые методы достать то, что можно достать такими способами атаки. Кроме того, внутри у него гораздо меньше шансов уйти незамеченным. Так что разница таки есть.
Но таки да, атака изнутри на что-то типа инфраструктуры, керберос там какой-нибудь, может быть не менее опасной. Она просто не такая простая.ufoton
16.12.2021 20:53-1Ну так и кипиш такой только от того, что ни кто не знает где стрельнет и надо выбирать тратить время на анализ или на обновление.
Ну атаки изнутри это гораздо опастнее и не факт, что легче ловится.
sshikov
16.12.2021 21:01>и кто не знает где стрельнет
Конечно. С этим никто не спорит. Яж и не говорил, что внутренние атаки например невозможны, или что они потенциально безопаснее. Ни в коей мере. В этом случае просто одним вектором атак меньше. Но как раз изнутри, если у вас украдут данные из кербероса, или иной похожей инфраструктурной системы, то дальше уже украдут вообще все.
> не факт, что легче ловится.
в случае известного IP внутри интранета — конечно же легче. Не вот так чтобы прям совсем легко — но вычислить откуда что пришло, вполне вычислят. Для внешнего атакующего как — ну узнали вы, что он скажем из Бангладеш к вам зашел, и что? А тут вы будете знать как минимум машину, а как максимум — логин. То есть следы нужно будет заметать намного тщательнее.
grossws
17.12.2021 05:11Кроме того, чтобы оно «сработало», это должен быть атакующий внутри.
Строго говоря, нет. Вполне достаточно чтобы логирующиеся данные смогли просочиться. См. https://habr.com/ru/company/bizone/blog/595473/comments/#comment_23821537
Как пример in the wild: web server access log -> ELK/EFK + ошибка (несовпадение типа поля, слишком большое поле или ещё что-нибудь) и вы получили rce где-то в глубине своей инфраструктуры.
sshikov
17.12.2021 07:24-2Мы про интранет говорили. Ну просочились, и чо будет-то? JNDI Lookup на внешний хост в интернете? Ну пусть попробует, чо.
ufoton
17.12.2021 10:28-1Вы слишком самоуверены
sshikov
17.12.2021 10:30-1Ну, если вы нет — огласите сценарий атаки, посмотрим вместе? Из моего интранета описанные публично сценарии невозможны — это просто физически изолированная сеть.
ufoton
17.12.2021 10:41Физически от чего изолирована ваша сеть? Если вы работаете со сферическим конём в вакууме то да вам ничего бояться. Но мне что то не верится
sshikov
17.12.2021 10:44От интернета, естественно. Более того, у нас все порты и лишние IP по умолчанию закрыты.
sshikov
17.12.2021 10:50>Но мне что то не верится
У нас PCI DSS :) Можно конечно не верить, но внешний аудит проходили.ufoton
17.12.2021 10:57-1не надо мне рассказывать про аудиты.
Я предпочитаю верить что моя система уязвима и патчить её чем наоборот
sshikov
17.12.2021 10:58Я с этим даже спорить не буду. Я знаю что моя система уязвима. Но одно дело — реальные сценарии атаки, а другое — научная фантастика. Патчить лучше от реальных.
Вот у вас есть реальный сценарий? У меня пока нет. Я просмотрел доступные логи, и понял, что ничего из внешних данных у меня не логируется. И разумеется, каждый может ошибаться — но на сегодня я скорее считаю, что для нашего проекта реальной опасности нет.
sshikov
16.12.2021 17:26-2Вот я честно не понимаю одной простой вещи: в моей практике java никогда не торчала голой ж., пардон, tomcat-ом в интернет. То есть, снаружи всегда был apache htpd (раньше) или nginx (сегодня), а порой и специальные железные балансировщики от IBM, где внутри возможно тоже nginx, но это не точно. И они, блин, никогда не были уязвимы для log4shell, потому что в них нету log4j. И не будут никогда. Все что будет — это будет в их логах, без каких либо утечек.
А tomcat, или там Spring Boot, или что угодно, уже стоит внутри, так же точно, как и СУБД, или скажем Кафка, или что там у нас еще есть в нашей инфраструктуре. При этом стоит он на другом хосте, и закрыт файрволом, и правила этого файрвола говорят, что нечего этому Spring Boot делать за пределами нашей интрасети. Т.е. можно сто раз ему подсунуть ${jndi:...}, дальше этого же хоста оно не уйдет — пакеты по сети туда не будут ходить. Да до него собственно и не дойдет это все уже — потому что внешние данные из дикой природы скорее всего будут уже санированы до попадания сюда, а даже если не будут — см. п.1
Вот для меня это настолько обычно и привычно, что прямо удивляет — а что, кто-то делает не так? А зачем? Из лени, по дурости, или есть еще какие-то причины?zaiats_2k
16.12.2021 19:01+1По неопытности ещё может быть. Но и лень с дуростью тоже весьма распространены.
silentz
17.12.2021 07:39Зловреду нет необходимости выходить в интернет. Если он может все что угодно на твоём хосте - это большая проблема, например зашифровать твои данные.
sshikov
17.12.2021 10:26Имеющиеся способы эксплуатации (этой конкретной дырки) предполагают, что код зловреда будет взят с внешнего хоста. Поэтому там как раз JNDI — в нем и лежит код. Внедрить во внутренней сети такого — ну, конечно можно, просто в интернете если кто-то такое сделал — его сложно взять за жабры. А в интранете это намного проще — понятно где искать, все IP записаны, логи в эластике и т.д. Более того, часто по умолчанию все физические доступы на уровне сети закрыты, а не открыты — то есть, вариантов куда можно внедрить зловред, не так много. И человек, которые это сможет сделать, скорее всего найдет способы нагадить и попроще.
Ну то есть, в общем случае вы правы конечно. Просто это уже другая история.silentz
17.12.2021 11:01Просто вы говорите про джава вэб. Но эта уязвимость отлично работает и для стандалоун джава - например, было продемонстрировано, как выполняется код машине пользователя, у которого запущен Майнкрафт. Я как человек, который пострадал от ransomware - скажу, что это не очень приятно. А так вы правы - если в сети нет доступов наружу, то нет и проблемы.
sshikov
17.12.2021 11:04>Просто вы говорите про джава вэб.
Я так говорю просто потому что это самый типовой и понятный сценарий, описанные атаки. Там ясно, откуда могут появиться данные, которые запишутся в лог. Но там же и понятно, как закрыть дырку. Файрволом, например — потому что нашему веб приложению нечего делать на каком-то там IP адресе в интернете.
В случае же прочих вариантов пока все достаточно мутно.
sshikov
16.12.2021 17:30Есть еще неплохой на мой взгляд вариант исправления. Написать (или скачать в интернете готовый) javaagent, который прицепится к JVM (статически при старте, или даже динамически), и модифицирует байт код нужных классов log4j, чтобы они ничего не делали. Если вы не используете сами эти подстановки log4j, типа jndi, вам этого хватит.
Причем, этот вариант работает для всех версий log4j, по крайней мере теоретически.grossws
17.12.2021 05:13+1А потом вы натыкаетесь на проект где какой-то добрый человек сделал shade+relocate для
org.apache.logging
..sshikov
17.12.2021 07:21+1habr.com/ru/post/595935/?reply_to=23832635#comment_23830405
Против лома нет приема. Хотя в целом агент — это пожалуй единственный вариант, который хотя бы может такое поискать.
Dr_No
Я понимаю, что ваш блог это сплошные переводы и не считаю это чем-то плохим. Но настолько явный гуглтранслейт с переводом устоявшихся терминов, которые переводить не надо - откровенное издевательство.
Soorin
Но будите внимательны :)
val6852 Автор
Спасибо!
Уже исправлено.