È sicuro risolvere gli errori Access-Control-Allow-Origin (CORS origin) con una direttiva header PHP?
Sto cercando di mostrare un form di Formidable Pro da un sito WordPress ad un altro. Ho seguito l'API dello sviluppatore e la REST API, ma ho riscontrato un problema CORS.
Poi ho trovato un suggerimento in una discussione del forum che suggeriva di aggiungere questa riga di codice nel file functions.php
del sito dove si trova il form originale:
header("Access-Control-Allow-Origin: *");
Ho provato questo codice e ha funzionato perfettamente.
La mia domanda è: questo codice apre rischi di sicurezza o altre vulnerabilità?
La soluzione sembra troppo semplice per un problema che molte persone affrontano.
Il vostro contributo è molto apprezzato.

Sì, stai aprendo il tuo sito a richieste AJAX da qualsiasi altro script su tutto il web.
Sarebbe meglio se limitassi l'origine a un dominio remoto specifico da cui stai consumando l'API, come questo esempio:
header("Access-Control-Allow-Origin: http://mozilla.com");
Tuttavia, come afferma la documentazione di mozilla, un client può falsificare l'origine, ma limitare i siti a cui un utente casuale può connettersi è un deterrente per alcuni attacchi.
Ancora meglio, puoi limitare le tue richieste solo ai metodi che hai davvero bisogno di consentire, l'essenza è questo snippet, e funziona per diversi domini, se hai la variabile $_SERVER['HTTP_ORIGIN']
popolata:
add_action('rest_api_init', function() {
/* scollega la funzione predefinita */
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
/* poi aggiungi il tuo filtro personalizzato */
add_filter('rest_pre_serve_request', function( $value ) {
$origin = get_http_origin();
$my_sites = array( 'http://site1.org/', 'http://site2.net', );
if ( in_array( $origin, $my_sites ) ) {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
} else {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
}
header( 'Access-Control-Allow-Methods: GET' );
return $value;
});
}, 15);
Come puoi vedere, questo snippet utilizza la funzione get_http_origin fornita da WordPress, ma restituirà null o vuoto, se la chiave HTTP_ORIGIN
non è popolata nell'array $_SERVER
, quindi non è disponibile per lo script PHP, forse perché è bloccata dal proxy cloudflare che stai utilizzando. Controlleresti velocemente, con uno script contenente <?php phpinfo(); ?>
, se hai questa variabile popolata.
Forse l'origine del sito è popolata in un altro header da cloudflare, e potresti usarla in una funzione agganciata al filtro http_origin
. Se sei perso a questo punto, modifica la tua domanda originale inserendo i contenuti della variabile _SERVER, escludendo i percorsi del filesystem o le password.
Sarei felice di aiutare.

Grazie. La prima soluzione ha funzionato per me. Ma dato che ho 4 siti che voglio permettere di accedere al sito principale, devo ripetere la riga 4 volte cambiando l'URL del sito, oppure si può combinare in un unico comando? Grazie

Certo che puoi, io di solito permetto l'accesso all'API solo a pochi siti, ho aggiornato la mia risposta con il controllo per questo, se funziona, potresti votare positivamente la risposta?

la prima soluzione ha funzionato solo per 1 dominio. se ripeto la riga, non funziona. Ho provato il metodo in questo thread link, ma non funziona neanche.
Quando applico la soluzione 2, questo è quello che ottengo: XMLHttpRequest cannot load https://coptic-treasures.com/wp-json/frm/v2/forms/6?return=html. The 'Access-Control-Allow-Origin' header has a value 'https://coptic-treasures.com' that is not equal to the supplied origin. Origin 'https://audio.coptic-treasures.com' is therefore not allowed access.

Non puoi utilizzare l'header Allow Origin più di una volta. Ho aggiornato la mia risposta con ulteriori istruzioni per aiutarti a debuggare il problema, perché non dovrebbe sempre restituire lo stesso sito e dovrebbe riconoscere la lista dei tuoi domini che passi all'array. Per favore aggiorna la tua domanda con i dati della variabile $_SERVER, restituiti da phpinfo()
, escludendo password e percorsi del filesystem. Sarò felice di aiutarti.

Mi ci sono voluti circa 2 giorni per scoprire come rimuovere l'accesso CORS dall'API WP-JSON. Grazie per questo. Rimuovi la chiamata alla funzione rest_send_cors_headers
!

contesto - i browser limitano l'accesso remoto da script solo al sito da cui è stato caricato. Se questo tipo di controllo non venisse effettuato, mentre si visita un sito X sarebbe possibile per esso inviare dati al tuo account Gmail (se sei loggato) senza nemmeno dover indovinare nome utente e password, perché il browser avrebbe inviato i cookie di autenticazione corretti a Gmail.
Il "protocollo" CORS è lì per aiutarti a rilassare questa restrizione quando necessario.
Quindi la domanda che dovresti porti è: ne ho bisogno? Da un lato, non vedo perché il 99% dei siti WordPress dovrebbe averne bisogno, dall'altro i cookie di WordPress hanno una durata relativamente breve e il 99% dei siti WordPress non sarà un bersaglio di un tale attacco casuale.
Direi che, dato che l'API REST è mutabile e ha accesso a informazioni private, non dovresti usare l'API REST nella tua soluzione se devi abilitare CORS, è meglio scrivere la tua API "sola lettura".

L'OP non sta parlando del 99% dei siti WP là fuori, ma dei propri siti, e secondo la domanda è necessario rendere disponibili risorse da altri siti.

Che il punto è rispondere alla domanda, è l'obiettivo di questo sito.

@JesúsFranco, penso che la mia reputazione dimostri che so come rispondere alle domande e non ho bisogno dei tuoi consigli?

Quindi, hai un'idea specifica su come l'OP può risolvere questo problema?

@JesúsFranco, l'OP ha chiesto se è sicuro. La risposta è che non lo è. La soluzione è ovviamente non fare cose che richiedono l'uso di cors

La mia domanda si basa su ciò che affermi riguardo al rischio di accesso a informazioni private. In realtà, uno dei principi fondamentali dell'API è che solo lo sviluppatore può concedere l'accesso a informazioni private, poiché l'API così come fornita upstream non lo permette.

@JesúsFranco Per quanto ne so, l'API utilizza i cookie per l'autenticazione e le persone con il ruolo di amministratore, ad esempio, possono ottenere quasi tutte le informazioni. Se disabiliti completamente il CORS e io utilizzo qualche forma di phishing per portarti sul mio sito, posso scrivere del JS che eseguirà qualsiasi operazione sul tuo sito, perché sei autenticato in esso e il tuo browser invierà semplicemente i cookie di autenticazione come parte della richiesta. Non avrò nemmeno bisogno di indovinare il tuo nome utente... Non è nemmeno sufficiente bloccare l'accesso agli endpoint di "scrittura" poiché come amministratore puoi ottenere informazioni riservate

È possibile che attualmente non ci sia molto che possa essere ottenuto con l'API, ma il suo obiettivo è quello di poter sostituire l'intera amministrazione, quindi dovrà servire al client tutti i dati esistenti.

Grazie Mark, conoscere il meccanismo che può essere abusato per trasformare l'accesso all'API in qualcosa di insicuro è molto utile per pensare a come gestire quei rischi, e quindi poter decidere se utilizzare una patch, limitare in altro modo gli utilizzi se i metodi utilizzabili dagli script remoti, o scrivere una nuova API da zero.

@MarkKaplun Sono nuovo a WP-API quindi avevo una domanda. Consentire CORS solo per i metodi 'GET' esporrebbe comunque il server a vulnerabilità?

@shariqkhan, probabilmente è meglio chiederlo su SO o su security stack, ma in generale la risposta è sì. CORS dovrebbe essere disabilitato solo per siti di cui ti fidi o su sottodomini tuoi che non eseguono alcuna azione senza che vengano inviate credenziali di autorizzazione nel corpo della richiesta. Finché l'API REST utilizza i cookie per l'autenticazione e viene eseguita sullo stesso dominio del sito WP, dovresti essere molto cauto nel disabilitarlo.

ma ancora una volta, se disabiliti CORS solo per un URL specifico che sai non potrà essere utilizzato per fare danni, allora potrebbe essere OK. Non è tanto una questione di GET vs POST, ma di cosa viene effettivamente fatto su quel endpoint

Grazie @MarkKaplun, ho visto le tue molte risposte su SO/SE quindi so che sai di cosa parli, probabilmente lo chiederò su SO, anche se sento che la domanda potrebbe essere chiusa come 'troppo ampia' o come 'duplicato'. Sono incuriosito da come vari siti web come Github, Twitter (e molti siti basati su WordPress) aprono le loro API disabilitando le restrizioni CORS per tutti. Ero dell'idea che se disabiliti CORS solo per le richieste GET, sia abbastanza innocuo perché stai solo permettendo ad altri di recuperare dati e non modificare nulla?

La differenza tra wordpress e altri siti è che non usano autenticazione basata su cookie per l'API, e l'utilizzo dell'API richiede l'invio di informazioni di tipo utente e password esplicitamente in ogni richiesta. L'API di WordPress <rant alert> è stata progettata male in quel senso, e probabilmente non poteva essere progettata meglio dato che doveva supportare comunicazioni non sicure su HTTP che impedivano di utilizzare la tecnica utente/password poiché chiunque in ascolto su una (ad esempio) WiFi avrebbe scoperto i valori.

il fatto che i cookie siano impostati quando sei loggato è ciò che gli attaccanti possono sfruttare per inviare richieste AJAX come se fossero originate da te. Con il CORS attivo, queste richieste falliranno per altri domini, e poiché sei l'unico che controlla il dominio sei al sicuro. Più siti per cui disabiliti il CORS, più posti un attaccante può controllare e attaccarti convincendoti a visitare quel sito. La domanda riguardava la disattivazione completa del CORS per tutti i siti, che è molto pericolosa, ma se lo disabiliti per altri domini che controlli completamente, pur non essendo una grande cosa, non è così grave.
