TGViewer
Make. Build. Break. Reflect. Make. Build. Break. Reflect. @makebreakreflect · 1.37K subscribers
Post #367 1.35K
#security #docker #devops и немного #всратость

Заметка носит скорее исследовательский и развлекательный характер.
Никакого поиска правды, настаивании на этом мнении или призыва к действию.


Однажды приходит алерт от инфобеза: критическая уязвимость, CVE-666lupa666pupa в zlib, надо фиксить.

Смотрю: zlib - это какая-то неизвестная мне хрень.
Возможно и инфобезе, может и никому.
Дебиан букворм держит zlib1g 1.2.13, в которой этот CVE есть.
Триви его видит, алерт красный, белки-истерички кричат и бегают по кругу.

Говорю инфобезу: это нас не касается, камон.
Во-первых, статус в самом триви - will not fix.
Во-вторых, есть флаг --ignore-unfixed, который именно для этого и придуман.
Мы в тот момент работали без этого флага - по какой-то причине, уже не помню.
Поэтому жалобка и прилетела. Поставили флаг + игнор файл для другой неэксплуатируемой штуки и вроде отстали от нас.
В-третьих, сканер это опционально у нас, ну чо ты, какие блокеры, иди чай попей.

Пока я пытался всё это объяснить, у меня в голове крутился вопрос:
а насколько вообще можно доверять тому, что триви находит или не находит?
Решил потом проверить.

- - -
Тест первый.
Пересобрал образ, вручную скомпилировал из сорсов прямо в имадж:
RUN apt-get update && apt-get install -y build-essential wget \
&& wget https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz \
&& tar -xf zlib-1.3.1.tar.gz \
&& cd zlib-1.3.1 \
&& ./configure \
&& make \
&& make install \
&& ldconfig \
&& cd .. \
&& rm -rf zlib-1.3.1 zlib-1.3.1.tar.gz \
&& apt-get purge -y build-essential wget \
&& apt-get autoremove -y

Проверяю внутри контейнера - 1.3.1 там:
$ ls -la /usr/local/lib/libz*
lrwxrwxrwx /usr/local/lib/libz.so -> libz.so.1.3.1
lrwxrwxrwx /usr/local/lib/libz.so.1 -> libz.so.1.3.1
-rwxr-xr-x /usr/local/lib/libz.so.1.3.1

$ ldconfig -p | grep libz
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 <- dpkg-пакет, 1.2.13
libz.so.1 => /usr/local/lib/libz.so.1 <- скомпилированная 1.3.1


Запускаю триви - снова цве критикал 😬

Вероятно триви читает /var/lib/dpkg/status - базу пакетного менеджера.
Что реально лежит в /usr/local/lib его не интересует.
Скомпилированная версия для него невидима. Безопасность)

Наверняка это не баг - это архитектурное решение, бинарный анализ каждой библиотеки был бы на порядки дороже. Но это означает, что сканер сообщает о CVE на основе базы пакетного менеджера, а не того, что реально резолвит линкер в рантайме - а это, вообще-то, отдельный вопрос, который одним ldconfig -p не закрыть. Ну не глупость ли, а?
Сканер говорит "уязвимость есть" - а есть ли она реально в работающем процессе, это уже совсем другая история, и я её тут не проверял.

Тест второй.
Раз уж проверяем, проверим до конца.
Берём образ с реальной уязвимостью - log4shell
FROM alpine:3.18
WORKDIR /app
RUN apk add --no-cache openjdk8-jre-base wget
RUN wget https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.jar && \
wget https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.jar
CMD ["/usr/bin/java", "-version"]

Триви весело находит три CVE:
log4shell, CVE-biba, CVE-boba. Всё верно.

Теперь берём тот же JAR с уязвимым байткодом и просто меняем строку версии в метаданных внутри архива:
RUN mkdir temp && \
unzip log4j-core-2.14.1.jar -d temp && \
sed -i 's/version=2.14.1/version=2.17.1/g' \
temp/META-INF/maven/org.apache.logging.log4j/log4j-core/pom.properties && \
cd temp && \
zip -r ../mylog4j-core.jar . && \
cd .. && \
rm -rf temp log4j-core-2.14.1.jar
RUN mv log4j-api-2.14.1.jar mylog4j-api.jar

Байткод не тронут, язвимый код на месте.
Только pom.properties теперь говорит версию 2.17.1.
trivy image test:latest --severity HIGH,CRITICAL
Total: 0 (HIGH: 0, CRITICAL: 0)

Триви для джавы читает мета pom.properties внутри JAR.
Не байткод, не хэши классов - метаданные, так что поменял строку и тут же сканер доволен 😀.
Сканер говорит "всё чисто" - а уязвимость есть 🤣.

Тест третий.
Проверим ещё - го бинари.
Триви умеет читать зависимости прямо из скомпилированного го бинаря. В каком-то файле есть секция .go.buildinfo, куда компилятор записывает все модули с версиями.
Это реально удобная фича - никаких go.sum в образе не нужно, сканер находит всё сам.
Берём минимальное приложение с намеренно старой версией:
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4

Триви после сборки находит 20 CVE только в го депенденси.

Теперь удаляем секцию билдинфо из бинаря с помощью objcopy:
RUN go build -o myapp . \
&& apt-get update && apt-get install -y --no-install-recommends binutils \
&& objcopy --remove-section=.go.buildinfo myapp myapp-stripped \
&& apt-get purge -y binutils && apt-get autoremove -y


Бинарь работает и функционально идентичен, проверяю:
$ objdump -s -j .go.buildinfo /myapp-stripped
objdump: section '.go.buildinfo' mentioned in a -j option, but not found in any input file

скан:
trivy image test-go-stripped:latest --severity HIGH,CRITICAL
Total: 9 (HIGH: 6, CRITICAL: 3) только пакеты операционки

Все 20 гошные CVE исчезли, остались только 9 от Дебиан, которые will not fix. Безопасность 😎

На мультистейдже с финальным FROM scratch это тоже легко обходится - например, через upx, который пакует бинарь в свой формат и триви перестаёт читать билдинфо.
Суть та же: все варианты работают, сканер молчит. Безопасность 😁


Так что с итогом:
Да ничо, это просто было увлекательно. Изначальная проблема была решена чисто флагом вообще то.
А вопросы остались.
Я не говорю, что CVE сканеры имаджей бесполезны, наоборот - они полезны в штатных сиуациях.
Они находят реальные проблемы, они дают точку отсчёта, они вполне работают как первый фильтр.
Но некоторые сканеры, такие как триви, дают лишь аппроксимацию на основе сигнатур и метаданных.
И в целом они не гарантируют ничего - ни того, что уязвимость есть, ни того, что её нет.

Финальное решение - применимо ли эта CVE к вашей системе, надо ли бежать чинить прямо сейчас или игнорировать месяцами - пока принимает человек.
Это не игнорирование безопасности - как по мне это и есть работа с безопасностью.

- - -
Эта заметка - аккуратно переработанный текст моих старых сообщений в чате куберентис ру, но без обсценной лексики 😬.
  • 👍 18
  • ❤ 1
  • 🥰 1
More from @makebreakreflect
  1. Sep 22, 2026#aws #elasticache #redis #kubernetes #troubleshooting #devops #sre #longread Ничего не пре…
  2. Sep 18, 2026Вся эта неделя была очень странной. Опус отупел до уровня 3 модели. Фейбл сжигает токены б…
  3. Sep 16, 2026Post #382
  4. Sep 15, 2026Apple наконец слила beta и release в один продукт и избавились от лишнего шага в релизном…
  5. Sep 14, 2026#мысли #devops #aws Куча людей перешли на искусственный интеллект, так и не освоив собстве…
  6. Sep 4, 2026#aws и немного #всратость Честно говоря я немного разочарован последними UI изменениями, п…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →