Joomla su LiteSpeed: CSS e JavaScript in 403 con query string Migrazione da Joomla 3 a Joomla 6 con T3 e Purity III: caso reale Sito Joomla non aggiornato: quali controlli fare prima di intervenire Sito hackerato: cosa fare subito e quali errori evitare Action Scheduler di WooCommerce bloccato: diagnosticare code e operazioni fallite Admin-ajax.php consuma troppe risorse: trovare plugin e richieste responsabili Audit delle estensioni prima di migrare da Joomla 3 a Joomla 5 o 6 Cache Redis in WordPress mostra dati vecchi: diagnosi dell'object cache Come gestire SEO e hreflang in un sito multilingua Hugo Login loop in WordPress Multisite: cookie, dominio e HTTPS da controllare Plugin WordPress lento: il problema è nel database o nelle query? WP-Cron non funziona in WordPress: attività e pubblicazioni bloccate Come aggiornare WordPress da Excel senza creare duplicati Importare Excel in WordPress con un plugin personalizzato Migrazione WordPress: come gestire DNS, SSL ed email senza interruzioni Joomla su LiteSpeed: CSS e JavaScript in 403 con query string Migrazione da Joomla 3 a Joomla 6 con T3 e Purity III: caso reale Sito Joomla non aggiornato: quali controlli fare prima di intervenire Sito hackerato: cosa fare subito e quali errori evitare Action Scheduler di WooCommerce bloccato: diagnosticare code e operazioni fallite Admin-ajax.php consuma troppe risorse: trovare plugin e richieste responsabili Audit delle estensioni prima di migrare da Joomla 3 a Joomla 5 o 6 Cache Redis in WordPress mostra dati vecchi: diagnosi dell'object cache Come gestire SEO e hreflang in un sito multilingua Hugo Login loop in WordPress Multisite: cookie, dominio e HTTPS da controllare Plugin WordPress lento: il problema è nel database o nelle query? WP-Cron non funziona in WordPress: attività e pubblicazioni bloccate Come aggiornare WordPress da Excel senza creare duplicati Importare Excel in WordPress con un plugin personalizzato Migrazione WordPress: come gestire DNS, SSL ed email senza interruzioni
Joomla su LiteSpeed: CSS e JavaScript in 403 con query string

Joomla su LiteSpeed: CSS e JavaScript in 403 con query string

Autore Graziano De Maio - Gdmtech
Ti auguro buona lettura e mi raccomando, se dopo aver letto questo articolo hai bisogno di aiuto non esitare a contattarmi.
Autore: Graziano De Maio | Titolare di Gdmtech
Indice dei contenuti

Il backend Joomla si apre, ma appare quasi privo di CSS. I menu non rispondono e diverse funzionalità JavaScript smettono di funzionare. Nel frattempo, il frontend continua a essere normalmente utilizzabile.

In questo caso reale, il problema è stato isolato confrontando due richieste allo stesso file: senza query string il server rispondeva HTTP 200; con il token completo del media versioning Joomla restituiva HTTP 403.

Il comportamento indicava un blocco legato al trattamento della richiesta lato server. Cambiare temporaneamente il valore di versioning ha consentito di recuperare l’operatività del backend, ma non ha risolto la causa del blocco.

Il ticket presso il provider è ancora aperto: non è stato confermato quale regola o componente di sicurezza generi il 403.

Joomla backend senza CSS: i sintomi osservati

L’ambiente interessato utilizzava:

ComponenteConfigurazione
CMSJoomla 3.8.5
PHP5.6
Web serverLiteSpeed
Template amministrativoIsis

Il frontend continuava a funzionare, mentre l’amministrazione presentava due problemi evidenti: mancavano buona parte degli stili e diverse interazioni non erano operative.

Questa combinazione suggeriva di controllare il caricamento degli asset prima di intervenire sul template. Un backend senza CSS può dipendere da risorse non raggiungibili; menu e pulsanti inattivi possono essere la conseguenza del mancato caricamento delle librerie JavaScript.

La differenza tra frontend e backend, da sola, non identificava la causa: le due aree possono richiedere risorse e URL diversi. Il passaggio successivo era verificare quali richieste fallissero realmente.

Analizzare CSS e JavaScript nella scheda Network

Aprendo gli strumenti sviluppatore del browser e ricaricando l’amministrazione, nella scheda Network comparivano risposte HTTP 403 per alcuni file CSS e JavaScript.

Per ripetere una verifica simile:

  1. Aprire DevTools prima di ricaricare la pagina.
  2. Selezionare Network e disabilitare temporaneamente la cache del browser.
  3. Filtrare le richieste per CSS e JavaScript.
  4. Controllare stato HTTP, URL completo, header e corpo della risposta.
  5. Confrontare una richiesta fallita con una variante funzionante.

L’URL completo è decisivo: limitarsi al nome template.css nasconde proprio il dettaglio che, in questo caso, cambiava il risultato.

Anche la Console può aiutare, ma gli errori JavaScript possono essere conseguenze secondarie. Se jQuery non viene caricato, gli script che lo utilizzano possono fallire a cascata. Conviene quindi partire dalla richiesta di rete bloccata.

Il test decisivo: stesso file, HTTP 200 oppure 403

Il confronto più significativo riguardava il foglio di stile del template Isis.

Senza query string:

/administrator/templates/isis/css/template.css
→ HTTP 200

Con il token completo generato dal media versioning:

/administrator/templates/isis/css/template.css?76822fa6c99b0bedb5fe9d45ee7638a8
→ HTTP 403

Lo stesso comportamento interessava JavaScript come:

/media/jui/js/jquery.min.js?76822fa6c99b0bedb5fe9d45ee7638a8
→ HTTP 403

Il file JavaScript senza query string risultava accessibile.

Ulteriori prove hanno permesso di restringere il problema:

Variante della richiestaEsito osservato
File senza query stringFunzionante
Query string semplice ?x=1Funzionante
Query string corta derivata dal tokenFunzionante
Token completo del media versioningHTTP 403

Questi risultati non dimostrano che LiteSpeed rifiutasse tutte le query string o qualsiasi stringa lunga. Dimostrano che quel valore completo, nelle condizioni del test, era associato al blocco.

Per distinguere un controllo sulla lunghezza da uno sul contenuto sarebbero necessarie altre prove controllate e, soprattutto, i log del server.

Perché il sospetto riguarda il server e non un CSS corrotto

I file esistevano ed erano leggibili. Le directory avevano permessi 755 e i file 644. Inoltre, nel caso osservato, il 403 veniva restituito direttamente da LiteSpeed.

Il dato più forte restava però il confronto: mantenendo lo stesso percorso e cambiando soltanto la query string, la risposta passava da 200 a 403.

Questo rendeva poco plausibile un problema limitato al contenuto del CSS o del JavaScript. Un errore di sintassi può compromettere lo stile o l’esecuzione dopo il download; non spiega normalmente un rifiuto HTTP selettivo basato sull’URL richiesto.

I permessi numerici, da soli, non escludono ogni problema di accesso, perché possono intervenire proprietario, ACL e configurazione del server. Tuttavia, l’accessibilità dello stesso file senza token rendeva questa pista meno coerente con le osservazioni.

Non era emersa neppure una normale regola evidente nel .htaccess capace di spiegare il comportamento. Questo non escludeva configurazioni ereditate o regole non visibili dall’account hosting.

La conclusione diagnostica era quindi circoscritta: indagare il trattamento lato server delle richieste contenenti quello specifico token. Un filtro di sicurezza era un’ipotesi plausibile, ma il componente responsabile restava da identificare.

La documentazione LiteSpeed descrive diverse possibili cause di 403, comprese regole ModSecurity: la presenza di questo codice HTTP non basta ad attribuire automaticamente il problema a un WAF specifico. Documentazione LiteSpeed sui 403.

Come funziona il media versioning degli asset Joomla

Il media versioning aggiunge una versione all’URL degli asset per favorire il caricamento delle risorse aggiornate.

Il principio è il cache busting: se cambia l’URL, il browser può distinguere la nuova risorsa da quella già memorizzata. Il comportamento delle cache intermedie dipende anche dalla loro configurazione.

La documentazione della serie Joomla 3 descrive la media version come una stringa aggiunta agli asset del core per favorire il ricaricamento di CSS e JavaScript. API Joomla 3: media version.

Nel template amministrativo del caso analizzato erano presenti chiamate come:

JHtml::_('script', 'template.js', array(
    'version' => 'auto',
    'relative' => true
));

JHtml::_('stylesheet', 'template.css', array(
    'version' => 'auto',
    'relative' => true
));

L’opzione 'version' => 'auto' richiedeva il versioning automatico. Negli URL osservati, il risultato era un token dopo il punto interrogativo, senza un nome di parametro come ver=.

Quel token era un identificatore di versione, non un’indicazione che il file fosse danneggiato. Il problema emergeva quando la richiesta contenente il valore completo veniva trattata dal server.

I workaround temporanei applicati al template Isis

L’obiettivo immediato era recuperare l’accesso operativo all’amministrazione, mantenendo aperta l’indagine con l’hosting.

Gli interventi seguenti riguardano il caso Joomla 3.8.5 con Isis: non sono istruzioni universali da applicare a qualunque versione Joomla.

Disattivare il versioning per alcuni asset

Come primo intervento temporaneo, per alcune risorse l’opzione è stata modificata così:

JHtml::_('script', 'template.js', array(
    'version' => false,
    'relative' => true
));

JHtml::_('stylesheet', 'template.css', array(
    'version' => false,
    'relative' => true
));

Con 'version' => false si evita l’aggiunta della versione attraverso quelle chiamate.

Il limite è la copertura: intervenire sul CSS e sullo script del template non modifica necessariamente le risorse caricate da framework, componenti o plugin.

Impostare temporaneamente una media version diversa

Successivamente è stato applicato un workaround più generale nel template amministrativo, prima del caricamento del framework JavaScript:

// Workaround temporaneo, da rimuovere dopo la correzione lato hosting.
$this->setMediaVersion('1');

Nel contesto del template, il metodo imposta la media version del documento. La relativa API è documentata nella serie Joomla 3. API Joomla: Document::setMediaVersion.

Nel caso osservato, il valore '1' ha consentito di evitare il token che provocava il blocco. Non significa che sia un valore universalmente “sicuro” o che riscriva qualsiasi URL prodotto dalle estensioni.

Dopo la modifica:

  • i CSS del backend venivano caricati;
  • jQuery risultava nuovamente disponibile;
  • i menu amministrativi funzionavano;
  • le richieste principali erano tornate HTTP 200.

Prima di intervenire su un’installazione analoga, occorre conservare una copia del file e documentare la modifica: gli aggiornamenti possono sovrascrivere gli interventi diretti sul template.

Perché entrambi gli interventi devono restare temporanei

Disabilitare il versioning riduce l’efficacia del cache busting. Anche fissare stabilmente la versione a '1' interrompe il normale cambiamento dell’identificatore.

Dopo un aggiornamento, browser o cache intermedie potrebbero continuare a utilizzare risorse precedenti, secondo le rispettive politiche di cache. Il backend potrebbe quindi presentare nuovi malfunzionamenti dovuti a file non allineati.

Entrambi gli interventi aggirano il sintomo: non correggono la regola che genera il 403.

Il problema aggiuntivo riscontrato con JCE Editor

Durante il ripristino è emerso anche un problema con JCE Editor. Passando temporaneamente a TinyMCE, le funzioni di modifica e salvataggio degli articoli sono tornate operative.

Questo risultato va descritto senza estendere oltre le prove la diagnosi.

Il cambio di editor ha recuperato quelle funzioni, ma non dimostra che JCE fosse difettoso né che il suo problema dipendesse dalla stessa regola che bloccava CSS e JavaScript.

Per approfondire servirebbe verificare separatamente:

  • gli asset richiesti da JCE;
  • gli eventuali errori nella Console;
  • le richieste generate durante modifica e salvataggio;
  • la versione dell’estensione e la compatibilità con l’ambiente.

TinyMCE è stato quindi un ulteriore ripiego operativo temporaneo, non la prova della causa del malfunzionamento di JCE.

La soluzione definitiva da richiedere al provider hosting

La correzione definitiva richiede di individuare lato hosting la regola o il componente che rifiuta la richiesta legittima, quindi correggerne il comportamento.

Il provider dovrebbe correlare le prove con i log del web server e degli eventuali sistemi di sicurezza. LiteSpeed documenta anche l’integrazione ModSecurity/WAF e la registrazione dei relativi errori nei log del server. Documentazione LiteSpeed su ModSecurity/WAF.

Un ticket utile deve contenere:

  • data, ora e fuso orario delle prove;
  • URL completo funzionante e URL bloccato;
  • IP sorgente del test, comunicato privatamente;
  • codici HTTP, header e risposta ricevuta;
  • risultati con query string semplice, token corto e token completo;
  • descrizione dei workaround già applicati.

La richiesta tecnica può essere formulata così:

Lo stesso file statico restituisce HTTP 200 senza query string e HTTP 403 con il token completo allegato. Potete verificare nei log quale componente genera il rifiuto e, se presente, identificare regola e condizione che lo attivano?

Se viene confermato un falso positivo, l’intervento dovrebbe essere mirato. Disabilitare globalmente il WAF non è una correzione appropriata del singolo problema.

Dopo la modifica lato hosting, occorre riprovare l’URL originariamente bloccato, rimuovere i workaround, ripristinare il versioning automatico e verificare nuovamente le funzioni amministrative.

Al momento della stesura, il ticket è ancora aperto: non è disponibile una conferma del provider sulla causa precisa.

Checklist diagnostica per file statici in 403

Questo metodo è riutilizzabile anche su WordPress e su altre applicazioni che aggiungono versioni agli URL degli asset. Cambiano le API del CMS, ma resta valido il confronto tra richieste.

ControlloInformazione da ricavare
Individuare le richieste falliteQuali risorse sono realmente bloccate
Confrontare URL con e senza querySe il rifiuto dipende dalla query string
Provare varianti controllateQuali valori riproducono il problema
Mantenere uguali sessione e condizioniEvitare confronti falsati
Controllare corpo e headerDistinguere asset, errore e reindirizzamento
Verificare file e accessiEscludere problemi del percorso
Correlare richieste e logIdentificare il componente responsabile
Registrare le modifiche temporaneeConsentire il ripristino
Riprovare dopo la correzioneVerificare la rimozione della causa

Anche un HTTP 200 va controllato: deve contenere effettivamente il CSS o JavaScript atteso, non una pagina HTML di login o di errore.

Backend ripristinato, diagnosi lato hosting ancora aperta

Il passaggio risolutivo per la diagnosi è stato confrontare lo stesso asset con e senza media version. Questo ha spostato l’indagine dai file al trattamento della richiesta lato server.

I workaround hanno ripristinato le funzioni principali, ma la chiusura tecnica del problema richiede ancora l’identificazione e la correzione della regola responsabile. Il versioning automatico dovrà poi essere ripristinato.

FAQ tecniche

Per i test con curl è meglio usare GET oppure HEAD?

Conviene partire da GET, lo stesso metodo normalmente utilizzato dal browser per caricare gli asset. HEAD può essere gestito diversamente e non restituisce il corpo utile a riconoscere una pagina di blocco.

Come confrontare da terminale le due richieste?

Sostituendo example.com con il dominio da verificare:

curl -sS -D - -o /dev/null \
  'https://example.com/administrator/templates/isis/css/template.css'

curl -sS -D - -o /dev/null \
  'https://example.com/administrator/templates/isis/css/template.css?76822fa6c99b0bedb5fe9d45ee7638a8'

Questi comandi mostrano gli header senza scaricare il corpo sul terminale.

E se curl restituisce 200 mentre il browser riceve 403?

Le richieste potrebbero differire per cookie, header, IP sorgente o passaggio attraverso una cache. Occorre confrontarle mantenendo condizioni equivalenti, proteggendo eventuali credenziali presenti nelle richieste copiate.

L’header Server: LiteSpeed identifica la regola responsabile?

No. Può indicare il server che risponde, ma non identifica da solo il componente che ha deciso il blocco. Servono log correlati alla richiesta ed eventualmente l’identificativo della regola.

È utile allegare un file HAR al ticket hosting?

Sì, perché documenta le richieste di rete. Prima di condividerlo bisogna verificare che non contenga cookie, token di sessione, dati personali o altre informazioni riservate non necessarie alla diagnosi.

Se il tuo backend Joomla presenta CSS mancanti o JavaScript in 403, posso offrirti assistenza tecnica Joomla, analizzare le richieste bloccate e raccogliere le evidenze necessarie per un intervento mirato con il provider hosting.

Autore Graziano De Maio - Gdmtech
Ti auguro buona lettura e mi raccomando, se dopo aver letto questo articolo hai bisogno di aiuto non esitare a contattarmi.
Autore: Graziano De Maio | Titolare di Gdmtech
Graziano De Maio, Web designer, SEO specialist
Graziano De Maio
Web Developer, SEO Specialist
Gdmtech Web Agency
Via Stefanardo da Vimercate 28 - (Milano)
Via Spinedi 55 - Postalesio (Sondrio)
Info e contatti