FlawOpen

flawopen.com/Teardowns/cve-2023-2640-ubuntu-overlayfs-privilege-escalation

● CVE-2023-2640 · CVSS 7.8 · Высокий
Исследования · FlawOpen

CVE-2023-2640: LPE в Ubuntu OverlayFS

CVE-2023-2640 обходит проверки прав в некоторых ядрах Ubuntu с OverlayFS. Проверьте вариант ядра и установите исправление поставщика.

💡 Простыми словами (ELI5)

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

Ключевые понятия и термины

OverlayFS
OverlayFS — объединённая файловая система Linux, которая показывает файлы нижнего слоя и записывает изменения в верхний слой.
Extended attribute (xattr)
Расширенный атрибут (xattr) — метаданные объекта файловой системы. Модули безопасности Linux и файловые capabilities используют специальные пространства имён xattr.
ovl_do_setxattr()
Вспомогательная функция OverlayFS для записи xattr в объект верхнего слоя. Уязвимая обёртка слишком широко использовала функцию VFS без проверки прав.
Copy-up
Операция OverlayFS, создающая копию объекта нижнего слоя в верхнем слое, когда для записи нужна изменяемая копия.

Связи со стандартами

  • Ссылка CWE для слабого места, описанного в этом руководстве: CWE-863

Анализ первопричины

Согласно записи Ubuntu CVE, уязвимая конфигурация требует одновременно upstream-коммит c914c0e27eb0 и патч Ubuntu SAUCE «Skip permission checking for trusted.overlayfs.* xattrs». Этот патч изменил обёртки xattr OverlayFS, чтобы они использовали функции VFS _noperm; предполагалось пропускать проверки только для внутренних метаданных trusted.overlayfs.*. После изменения upstream обёртки helper стал применяться и к другим xattr. Поэтому локальный пользователь без привилегий мог устанавливать привилегированные расширенные атрибуты на смонтированных файлах и переносить их в верхний слой без необходимых проверок. Исправление Canonical отменяет широкий путь без проверки и вызывает vfs_setxattr() с user namespace верхнего монтирования. Это локальное повышение привилегий, специфичное для ядра Ubuntu; уязвимость зависит от релиза, варианта ядра, политик namespace и монтирования.

Пошаговый сценарий атаки

Шаг 1

Затронутая конфигурация ядра Ubuntu

Ядро должно содержать и c914c0e27eb0, и патч Ubuntu SAUCE о пропуске проверок для trusted.overlayfs.* xattr. Номер upstream-версии сам по себе не подтверждает уязвимость.

Шаг 2

Локальный пользователь достигает обработки xattr

Локальный пользователь без привилегий должен иметь возможность использовать затронутый путь OverlayFS согласно политикам namespace и монтирования хоста. Ubuntu описывает локальную атаку.

Шаг 3

Обход проверки затрагивает другие xattr

Изменённая обёртка направляла обновления xattr к helper _noperm, предназначенным для внутренних метаданных OverlayFS. Изменение upstream позволило другим xattr обходить необходимые проверки.

Шаг 4

Привилегированный атрибут попадает в верхний слой

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

Исходный код: Уязвимый vs Защищённый вариант

Затронутый путь SAUCE вызывал __vfs_setxattr_noperm() для всех xattr после того, как upstream-изменение расширило область применения. Исправление использует vfs_setxattr() с user namespace верхнего монтирования и восстанавливает обычные проверки VFS. Это целевой фрагмент патча Canonical; окружающие отладочные сообщения опущены.

Фрагмент исходного кода: fs/overlayfs/overlayfs.h

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
/* Контекст канонического патча Ubuntu до отмены изменения SAUCE. */
static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
                                  const char *name, const void *value,
                                  size_t size, int flags)
{
    struct inode *inode = dentry->d_inode;
    int err;

    inode_lock(inode);
    err = __vfs_setxattr_noperm(&init_user_ns, dentry, name,
                                value, size, flags);
    inode_unlock(inode);
    return err;
}
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
/* Каноническое исправление Ubuntu: восстановить VFS-обёртку с проверкой прав. */
static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
                                  const char *name, const void *value,
                                  size_t size, int flags)
{
    int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name,
                           value, size, flags);
    return err;
}

Чек-лист по защите системы для инженеров

Источники