Preskočiť na obsah
Elementor Pro opravil kritickú chybu nahrávania súborov
Zuzana Horváthová
Zuzana Horváthová 20. August 2026 · 9 min čítania

Elementor Pro opravil kritickú chybu nahrávania súborov

V plugine Elementor Pro sa našla kritická zraniteľnosť, ktorá útočníkovi bez účtu umožňuje nahrať ľubovoľný súbor vrátane spustiteľného PHP. Chyba zasahuje všetky verzie po 4.2.1 vrátane a môže viesť k vzdialenému spusteniu kódu aj úplnému ovládnutiu webovej stránky.

Aktualizuj Elementor Pro

Nainštaluj Elementor Pro 4.2.2 alebo novšiu verziu čo najskôr. Zraniteľnosť má skóre CVSS 9,8 z 10 a eviduje sa ako CVE-2026-32475.

Kedy je web zraniteľný

Chyba sa prejaví len pri konkrétnej konfigurácii. Web musí mať publikovanú stránku s Form widgetom z Elementor Pro a aspoň jedno pole File Upload, ktoré nemáš označené ako povinné. Elementor Pro má odhadom 6 000 000 aktívnych inštalácií, preto sa oplatí skontrolovať všetky webové stránky, ktoré spravuješ.

  1. V nástenke WordPressu otvor zoznam pluginov a over verziu Elementor Pro.
  2. Ak používaš verziu 4.2.1 alebo staršiu, aktualizuj plugin na 4.2.2 alebo novší dostupný release.
  3. Prejdi publikované formuláre Elementor Pro a identifikuj polia File Upload, ktoré nie sú povinné.
  4. Kým aktualizáciu nenasadíš, obmedz prístup k dotknutým formulárom alebo ich dočasne zruš z publikovaných stránok.

Chyba prerušila validáciu po prvom prázdnom súbore

Formulár spracúva odoslanie cez metódu ajax_send_form() v triede Ajax_Handler, ktorú môže zavolať aj návštevník bez prihlásenia. Plugin vloží dáta formulára a nahrané súbory do objektu Form_Record, potom ich pri poli File Upload odovzdá metódam validation() a process_field() v triede ElementorProModulesFormsFieldsUpload.

Metóda validation() najprv upraví indexy súborov, načíta $_FILES['form_fields'] a pri nastavenom limite kontroluje maximálny počet súborov. Vo validačnom cykle však pri nepovinnom poli ukončila celú metódu príkazom return, ak prvá položka poľa obsahovala chybu UPLOAD_ERR_NO_FILE. Namiesto toho mala použiť continue, ktorý by preskočil iba prázdnu položku a pokračoval kontrolou ďalšej.

public function validation( $field, ClassesForm_Record $record, ClassesAjax_Handler $ajax_handler ) {
    static $upload_errors = false;

    if ( ! $upload_errors ) {
        $upload_errors = [
            UPLOAD_ERR_OK => esc_html__( 'There is no error, the file uploaded with success.', 'elementor-pro' ),
            UPLOAD_ERR_INI_SIZE => sprintf( esc_html__( 'The uploaded file exceeds the %1$s directive in %2$s.', 'elementor-pro' ), 'upload_max_filesize', 'php.ini' ),
            UPLOAD_ERR_FORM_SIZE => sprintf( esc_html__( 'The uploaded file exceeds the %s directive that was specified in the HTML form.', 'elementor-pro' ), 'MAX_FILE_SIZE' ),
            UPLOAD_ERR_PARTIAL => esc_html__( 'The uploaded file was only partially uploaded.', 'elementor-pro' ),
            UPLOAD_ERR_NO_FILE => esc_html__( 'No file was uploaded.', 'elementor-pro' ),
            UPLOAD_ERR_NO_TMP_DIR => esc_html__( 'Missing a temporary folder.', 'elementor-pro' ),
            UPLOAD_ERR_CANT_WRITE => esc_html__( 'Failed to write file to disk.', 'elementor-pro' ),
            UPLOAD_ERR_EXTENSION => sprintf( esc_html__( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with %s may help.', 'elementor-pro' ), 'phpinfo()' ),
        ];
    }

    $this->fix_file_indices();
    $id = $field['id'];
    $files = Utils::_unstable_get_super_global_value( $_FILES, 'form_fields' );

    if ( ! empty( $field['max_files'] ) ) {
        if ( count( $files[$id] ) > $field['max_files'] ) {
            $error_message = sprintf(
                _n( 'You can upload only %d file.', 'You can upload up to %d files.', intval( $field['max_files'] ), 'elementor-pro' ),
                intval( $field['max_files'] )
            );
            $ajax_handler->add_error( $id, $error_message );
            return;
        }
    }

    foreach ( $files[$id] as $index => $file ) {
        // Pri nepovinnom poli táto vetva nesprávne ukončila celú validáciu.
        if ( ! $field['required'] && UPLOAD_ERR_NO_FILE === $file['error'] ) {
            return;
        }

        if ( $field['required'] && UPLOAD_ERR_NO_FILE === $file['error'] ) {
            $ajax_handler->add_error( $id, $upload_errors[$file['error']] );
            return;
        }

        if ( $file['error'] > UPLOAD_ERR_OK ) {
            $ajax_handler->add_error( $id, $upload_errors[$file['error']] );
            return;
        }

        if ( ! $this->is_file_type_valid( $field, $file ) ) {
            $ajax_handler->add_error( $id, esc_html__( 'This file type is not allowed.', 'elementor-pro' ) );
        }

        if ( ! $this->is_file_size_valid( $field, $file ) ) {
            $ajax_handler->add_error( $id, esc_html__( 'This file exceeds the maximum allowed size.', 'elementor-pro' ) );
        }
    }
}

Útočník mohol pole odoslať ako pole s dvoma položkami: prvá ostala prázdna a vyvolala UPLOAD_ERR_NO_FILE, druhá obsahovala súbor so zvolenou príponou. Predčasný return tak preskočil overenie prípony cez is_file_type_valid() aj kontrolu veľkosti cez is_file_size_valid() pri každom zostávajúcom súbore v rovnakom poli.

Spracovanie potom neoverený súbor uložilo

Metóda process_field() pracovala inak: prázdnu položku korektne preskočila cez continue a pokračovala druhou položkou. Príponu prevzala priamo z názvu súboru, ktorý poslal klient, vytvorila jedinečný názov cez uniqid(), upravila ho pomocou wp_unique_filename() a súbor presunula na disk.

public function process_field( $field, ClassesForm_Record $record, ClassesAjax_Handler $ajax_handler ) {
    $id = $field['id'];
    $files = Utils::_unstable_get_super_global_value( $_FILES, 'form_fields' );

    foreach ( $files[$id] as $index => $file ) {
        if ( UPLOAD_ERR_NO_FILE === $file['error'] ) {
            continue;
        }

        $uploads_dir = $this->get_ensure_upload_dir();
        $file_extension = pathinfo( $file['name'], PATHINFO_EXTENSION );
        $filename = uniqid() . '.' . $file_extension;
        $filename = wp_unique_filename( $uploads_dir, $filename );
        $new_file = trailingslashit( $uploads_dir ) . $filename;

        if ( is_dir( $uploads_dir ) && is_writable( $uploads_dir ) ) {
            $move_new_file = Plugin::instance()->php_api->move_uploaded_file( $file['tmp_name'], $new_file );

            if ( false !== $move_new_file ) {
                $perms = 0644;
                @chmod( $new_file, $perms );

                $record->add_file( $id, $index, [
                    'path' => $new_file,
                    'url' => $this->get_file_url( $filename ),
                ] );
            } else {
                $ajax_handler->add_error( $id, esc_html__( 'There was an error while trying to upload your file.', 'elementor-pro' ) );
            }
        } else {
            $ajax_handler->add_admin_error_message( esc_html__( 'Upload directory is not writable or does not exist.', 'elementor-pro' ) );
        }
    }
}

Pri zachovanej príponě .php sa súbor zapísal do adresára /wp-content/uploads/elementor/forms/. Útočník potom mohol nahraný súbor vyžiadať cez web a spustiť jeho PHP kód na serveri. Takýto ľubovoľný upload často otvorí cestu k webshellu a následnému úplnému kompromitovaniu webovej stránky.

Oprava vyšla 19. augusta 2026

Wordfence prijal hlásenie zraniteľnosti 24. júla 2026. Po overení proof-of-conceptu ju 27. júla oznámil tímu Elementor; 2. augusta Elementor potvrdil, že rovnakú chybu nahlásil aj ďalší výskumník a že pripravuje opravu.

Elementor Pro vydal úplnú opravu vo verzii 4.2.2 dňa 19. augusta 2026. Pôvodne pridelené CVE sa nepoužíva, keďže zraniteľnosť eviduje CVE pridelené pri druhom nahlásení: CVE-2026-32475.

Čo urob teraz

Over verziu Elementor Pro na každej svojej webovej stránke a bez odkladu nasadzuj 4.2.2 alebo novšiu verziu. Ak na niektorej stránke nájdeš publikovaný Form widget s nepovinným nahrávaním súborov, prioritne skontroluj aj možné neoprávnené súbory v /wp-content/uploads/elementor/forms/.

Pridajte sa ku komunite HelloWP!

Chatujte s nami o WordPresse, webovom vývoji a zdieľajte skúsenosti s ostatnými vývojármi.

- členovia
- online
Pridať sa

Používame súbory cookie na zlepšenie vášho zážitku. Pokračovaním súhlasíte s našimi Zásadami používania súborov cookie.