
Уязвимости в PHP и Ubuntu в последнее время выходят чуть ли не каждый день, и на серверах их обычно закрывает unattended-upgrades. На четырех наших серверах он был установлен и включен, таймеры apt срабатывали по расписанию. При этом с июля он не поставил ни одного пакета.
Нашлось это 2 ноября, когда наша панель начала сверять установленные пакеты с базой уязвимостей Canonical. На каждом из четырех серверов оказалось от 53 до 58 пакетов, для которых исправление уже вышло, а установлено не было. openssl стоял в версии 3.0.13-0ubuntu3.11 при исправленной 3.0.13-0ubuntu3.16, рядом glibc, openssh, mysql-8.0 и brotli

Что было в источниках
Вот весь /etc/apt/sources.list.d/ubuntu.sources на этих серверах:
Types: debURIs: http://ru.archive.ubuntu.com/ubuntuSuites: noble noble-updates noble-backportsComponents: main restricted universe multiverseSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Карманов три, noble-security среди них нет. Серверы созданы 20 июля из образа хостера, называть его не буду. Рядом с этим файлом лежит ubuntu.sources.curtin.orig от установщика Ubuntu, и в нем вторая строфа с security.ubuntu.com и noble-security на месте. Похоже, при сборке образа источники перевели на российское зеркало, а строфу с безопасностью потеряли. Файл в образе датирован 20 июня 2025 года, тем же днем, что и настройки cloud-init.
Почему unattended-upgrades молчал
Исправления безопасности Ubuntu кладет в noble-security, и многие из них потом попадают и в noble-updates. А unattended-upgrades по умолчанию берет пакеты только из самого релиза и из -security, строка с -updates в его конфиге закомментирована:
Unattended-Upgrade::Allowed-Origins {"${distro_id}:${distro_codename}";"${distro_id}:${distro_codename}-security";"${distro_id}ESMApps:${distro_codename}-apps-security";"${distro_id}ESM:${distro_codename}-infra-security";//"${distro_id}:${distro_codename}-updates";//"${distro_id}:${distro_codename}-proposed";//"${distro_id}:${distro_codename}-backports";};
Без noble-security выходит так. Исправления, которые уже есть в noble-updates, apt видит, и apt upgrade их поставит. unattended-upgrades их пропускает, потому что этого кармана нет в его списке. А те, что пока лежат только в noble-security, на сервере не видны вовсе.
Стенд
Повторить можно в Docker на чистом ubuntu:24.04. Из ubuntu.sources убирается строфа с noble-security, дальше apt update:
$ apt list --upgradablezlib1g/noble-updates 1:1.3.dfsg-3.1ubuntu2.3 arm64 [upgradable from: 1:1.3.dfsg-3.1ubuntu2.2]$ unattended-upgrade --dry-run -d | tail -n 1No packages found that can be upgraded unattended and no pending auto-removals
Обновление есть, а ставить нечего. Строфа возвращается на место:
$ unattended-upgrade --dry-run -d | grep upgradedPackages that will be upgraded: libpcre2-8-0 zlib1g
Исправление libpcre2-8-0 в тот момент было только в noble-security, без него сервер о нем даже не знал. Образ свежий, поэтому пакетов всего два. На наших серверах после исправления источников встало от 182 до 197 пакетов на сервер.
Почему ноль в счетчиках ничего не значит
apt помечает обновление безопасности по карману, из которого оно приходит, в apt list это строка вида openssl/noble-updates,noble-security. Без подключенного noble-security этой пометки нет ни у одного пакета. Наша панель считала обновления безопасности именно так и показывала ноль при 197 доступных обновлениях. Любой мониторинг, который смотрит на этот суффикс, на таком сервере покажет то же самое.
Еще две ловушки
На серверах одного из проектов, тоже созданных из готового образа, таймеры apt не срабатывали ни разу. Службы apt-daily и apt-daily-upgrade в образе замаскированы, симлинки на /dev/null датированы днем его сборки в ноябре 2024 года. Таймер замаскированную службу запустить не может, так что unattended-upgrades стоял и ни разу не запускался. К моменту проверки на четырех серверах накопилось 118, 19, 14 и 14 обновлений безопасности.
Снимать маску стоит только с этих двух служб. В том же образе намеренно заглушен systemd-networkd, сеть на нем не держится.

Третья касается PHP из PPA ondrej/php. Его пакеты приходят с origin LP-PPA-ondrej-php, которого в списке выше нет, поэтому патч-релизы PHP сами не ставятся. Мы разрешаем их отдельным файлом. Метапакеты без версии в нем запрещены, иначе php-fpm из PPA подтянет новую ветку PHP:
// /etc/apt/apt.conf.d/52php-patchesUnattended-Upgrade::Origins-Pattern { "origin=LP-PPA-ondrej-php,codename=${distro_codename}"; "origin=deb.sury.org,codename=${distro_codename}";};Unattended-Upgrade::Package-Blacklist { "^php$"; "^php-(?!common$)[a-z0-9]+$";};
Второй origin нужен, если PHP ставится с packages.sury.org. На стенде с Ubuntu 24.04 так PHP 8.3 обновился с 8.3.6 до 8.3.35, а ветка 8.4 не появилась.
Что сделали
На четырех серверах в ubuntu.sources вернули стандартную строфу из образа Ubuntu:
Types: debURIs: http://security.ubuntu.com/ubuntu/Suites: noble-securityComponents: main universe restricted multiverseSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
После apt update и обновления встало новое ядро 6.8.0-147, серверы перезагрузили по одному. Дольше всех поднимался сервер приложения, около 3 минут.
Как проверить у себя
apt-cache policy | grep -c -- '-security'systemctl is-enabled apt-daily.service apt-daily-upgrade.servicesudo unattended-upgrade --dry-run -d 2>&1 | tail -n 1
Первая команда должна вернуть не ноль, на стенде с подключенным карманом это 8 строк. Вторая не должна писать masked. Третья показывает, что unattended-upgrades поставил бы прямо сейчас. Если на сервере есть доступные обновления, а он пишет No packages found, стоит посмотреть, откуда они приходят, командой apt list --upgradable

Мы наткнулись на это случайно, когда панель начала сверять пакеты с базой уязвимостей Canonical. Без этой сверки серверы так и жили бы без исправлений, а unattended-upgrades каждый день записывал бы в лог, что ставить нечего. Поэтому и решили поделиться. Если ваши серверы созданы из готового образа хостера, стоит потратить минуту на три команды выше и убедиться, что все в порядке
Источник: habr.com