FlawOpen

flawopen.com/Incidents/bricksforge-pro-forms-upload-metadata-october-2026

● Bricksforge WordPress plugin · CVE-2026-85097 · 2026-10-07 · CVSS 9.8 · Критический
Исследования · FlawOpen

CVE-2026-85097 в Bricksforge: ошибка загрузки в Pro Forms

CVE-2026-85097 позволяла запросам без аутентификации использовать расхождение между проверенным содержимым временного файла и метаданными назначения, которыми управлял клиент, в Bricksforge Pro Forms. Patchstack сообщает о попытках эксплуатации; обновите плагин и проверьте открытые сайты.[1], [2], [3], [4], [5]

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

Представьте почтовую комнату: сотрудник проверяет, что в посылке безобидная картинка, а затем позволяет отправителю заменить ярлык перед доставкой в офис, где некоторые ярлыки запускают программы. Bricksforge проверял временную загрузку, но при последующей отправке формы можно было указать другое имя назначения. Защита — сохранять идентификатор и место хранения файла под контролем сервера на всём пути обработки.[3], [2]

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

Временная загрузка
Файл, временно сохранённый до завершения отправки формы. Проверка на этом этапе не делает доверенными метаданные, позднее переданные клиентом.[2], [3]
CWE-434
Неограниченная загрузка файла опасного типа: система принимает файл, который может быть опасно интерпретирован или исполнен.[1], [2]
Граница доверия метаданным
Точка, в которой приложение определяет, получены ли имя, URL, MIME-тип или путь из надёжной серверной записи либо от недоверенного клиента.[2], [3]
Оценка CVE и эксплуатация
Запись CVE от CNA Wordfence указывает CVSS 3.1 9.8, а обогащение CISA сообщает, что эксплуатация не отмечена. Patchstack указывает 10.0 и сообщает телеметрию с 7 октября 2026 года. Эти сведения имеют разных авторов; ни одно не подтверждает включение в CISA KEV.[1], [2], [3], [4]
Иллюстративный код
Пример PHP ниже обобщённо показывает границу проверки. Это не исходный код Bricksforge и не реконструкция патча; цитируемый журнал версий таких деталей не публикует.[2], [3], [5]

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

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

Сведения о версиях и действия для операторов

Источник сведенийЧто в нём сказаноДействие защиты
Запись CNA Wordfence / CVEОписывает неаутентифицированную загрузку произвольных файлов; указанный диапазон затронутых версий заканчивается на 3.1.8.9.Считайте это областью, указанной CNA, а не доказательством безопасности установленного сайта.
Patchstack (8 октября 2026)Сообщает о попытках эксплуатации, впервые замеченных 7 октября, и указывает 3.1.8.10 как исправленную версию.Считайте это границей исправления по данным Patchstack; проверьте фактически установленную версию плагина на каждом сайте.
Публичный журнал изменений BricksforgeВ версии 4.0.1 указано исправление безопасности загрузки в Pro Forms, но не подтверждена граница 3.1.8.10.По одному журналу изменений не делайте вывод, что 4.0.1 — первая исправленная версия или что конкретная версия 3.x безопасна.
Открытый сайт или подозрение на компрометациюИсточники описывают попытки эксплуатации, но не подтверждают компрометацию каждого атакованного сайта.Обновите до поддерживаемой версии; проверьте журналы загрузок и веб-сервера, расследуйте появление неожиданных файлов до завершения восстановления.

Хронология инцидента

2026-10-07

Wordfence указывает 7 октября как дату публичной публикации уведомления. По данным Patchstack, телеметрия впервые зафиксировала попытки в этот день в 21:47 UTC; публикация уведомления и наблюдение телеметрии — разные события.[2], [3]

2026-10-08

В записи CVE указано datePublished — 8 октября, на день позже даты публичной публикации Wordfence (7 октября). В отчёте Patchstack о кампании также указана дата публикации 8 октября; это даты разных записей и публикаций.[1], [2], [3]

2026-10-08

В анализе от 8 октября Patchstack описывает несоответствие проверки и наблюдавшиеся попытки, а версию 3.1.8.10 называет исправленной. В журнале Bricksforge отдельно указано исправление безопасности загрузки Pro Forms в версии 4.0.1, но точная исправленная версия ветки 3.x не установлена.[3], [4], [5]

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

Шаг 1

Временный файл проходит первичную проверку

CNA описывает предварительную временную загрузку, прошедшую проверку MIME. Это не разрешает произвольно менять имя или место назначения файла позже.[2], [1]

Шаг 2

Форма передаёт отдельные метаданные

По данным Patchstack, последующая обработка доверяла метаданным temporaryFileUploads от клиента, включая URL, который мог не соответствовать уже проверенному файлу. Ошибка возникла из-за разного уровня доверия к проверенному содержимому и непроверенному назначению.[2], [3]

Шаг 3

Файл сохраняется под опасным именем

Если сервер использует заданное клиентом назначение при завершении загрузки, опасное расширение может привести к серверной интерпретации, если там разрешено исполнение. Здесь механизм описан на высоком уровне; форматы запросов и полезные нагрузки не нужны.[2], [3]

Шаг 4

Уязвимый сайт может быть скомпрометирован

CNA указывает, что проблема может дать произвольное исполнение PHP. Patchstack сообщает о попытках и рекомендует обновление. Эти наблюдения не доказывают компрометацию каждого сайта и не устанавливают личность злоумышленника.[2], [3]

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

Этот общий пример показывает серверный идентификатор загрузки, поиск по пользователю, повторную проверку типа содержимого, случайные имена и приватное хранение. Это не код Bricksforge и не его реальный патч. В рабочей системе также нужны ограничения размера, безопасные права доступа, атомарные переходы состояния и подходящая выдача файла; затронутые сайты следует обновить до поддерживаемой исправленной версии Bricksforge.[2], [3]

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
function finalize_upload( array $item, string $stagedPath, string $uploadDir ): string {
    // Метаданные клиента задают итоговое имя после предварительной проверки MIME-типа.
    $name = basename( (string) parse_url( $item['file']['url'], PHP_URL_PATH ) );
    $destination = $uploadDir . DIRECTORY_SEPARATOR . $name;
    if ( ! rename( $stagedPath, $destination ) ) {
        throw new RuntimeException( 'Could not finalize upload' );
    }
    return $destination;
}
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
function finalize_upload( string $uploadId, UploadRegistry $registry, string $privateDir ): string {
    // Определяйте владельца и путь по серверной записи, а не по URL клиента.
    $upload = $registry->findPendingForCurrentUser( $uploadId );
    if ( $upload === null || ! is_file( $upload->path ) ) {
        throw new RuntimeException( 'Unknown pending upload' );
    }
    $types = [ 'image/jpeg' => 'jpg', 'image/png' => 'png' ];
    $mime = ( new finfo( FILEINFO_MIME_TYPE ) )->file( $upload->path );
    if ( ! isset( $types[ $mime ] ) ) {
        throw new RuntimeException( 'Unsupported file type' );
    }
    $destination = $privateDir . DIRECTORY_SEPARATOR . bin2hex( random_bytes( 16 ) ) . '.' . $types[ $mime ];
    if ( ! rename( $upload->path, $destination ) ) {
        throw new RuntimeException( 'Could not finalize upload' );
    }
    $registry->markConsumed( $uploadId );
    return $destination;
}

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

Источники