Archivi tag: http post

cURL: interagire con l’interfaccia Web dei dispositivi di rete mediante linea di comando

Spesso e volentieri abbiamo a che fare con delle macchine *nix sprovviste di Desktop Enviroment (altrimenti conosciuto come server X), attraverso le quali è necessario accedere all’interfaccia Web di alcuni dispositivi di rete SOHO, in modo da effettuare le classiche operazioni di management (cambio di configurazione, riavvio, ecc.).

A tal proposito, esiste un tool molto potente da utilizzare mediante CLI, che prende il nome di cURL.

curlAdesso vedremo quali sono le analisi preliminari che ci permetteranno di capire se l’interfaccia Web con cui vogliamo interagire potrà essere manipolata tramite cURL o meno.

Analisi del codice sorgente

Il primo step consiste nello scaricare il codice sorgente dalla pagina, utilizzando le giuste credenziali di accesso (se previste). Ad esempio:

[root@linuxbox ~]# curl -u username:password http://192.168.1.1

A questo punto possiamo distinguere due macro casi:

1) la pagina Web contiene prevalentemente del codice HTML ed i cambi di configurazione possono essere effettuati mediante dei semplici form e l’invio dei dati attraverso HTTP POST o GET. In tal caso siamo stati fortunati e potremo procedere;

2) la pagina Web contiene soprattutto del codice javascrip e tutte le operazioni di management si avvalgono del suddetto codice. In questo caso siamo stati sfortunati e dovremo demordere, in quanto cURL non supporta javascrip.

Poniamoci quindi nel caso 1 e procediamo.

Per prima cosa occorre analizzare il codice sorgente della pagina di interesse andando alla ricerca dei tag:

<form></form>

all’interno dei quali è presente l’attributo action che punta alla pagina Web che si occuperà di processare i dati del form. Ad esempio:

 
<form action="apply.cgi" method="post">
<input type="hidden" name="page" value="device.asp">

    <input type="submit" name="action" value="Reboot">
</form>

Inoltre, bisogna capire quali e quanti campi di input (con relativo valore), identificati mediante gli attributi id o name, è necessario sottoporre alla suddetta pagina Web. Infatti, molto spesso, come misura molto blanda per contrastare alcuni attacchi Web quali il CSRF (vedi qui per ulteriori dettagli), vengono utilizzati dei campi di input di tipo hidden da inviare insieme al contenuto degli altri campi del form.

Una volta capito quali sono i campi da inoltrare alla pagina specificata dall’attributo action del form HTML (magari utilizzando il classico metodo trial-and-error), possiamo procedere con il loro inoltro vero e proprio, avvalendoci, ad esempio, del seguente comando:

curl -u username:password -s -d "action=Reboot&page=device.asp" http://192.168.1.1/apply.cgi

Nella fattispecie, la pagina che si occuperà di processare i dati è apply.cgi, mentre i campi di input inviati sono action, il cui valore è Reboot, e page, il cui valore è device.asp. Da notare che le suddette informazioni sono state inviate in formato querystring (ovvero utilizzando il carattere & di concatenazione).

Infine, occorre precisare che la flag -s evita di inviare allo standard output le statistiche relative al processamento della pagina richiesta, mentre la flag -d (data) è quella che ci permette di inviare i dati attraverso un semplice HTTP POST.

Per ora è tutto. Alla prossima.

Contromisure agli attacchi CSRF

In questo post ho parlato degli attacchi CSRF (Cross Site Request Forgery). Ora vediamo quali sono le possibili contromisure per evitare (o minimizzare) gli effetti nefasti che tale minaccia può provocare.

 

sechttp.jpg

La semplice definizione del metodo HTTP (GET oppure POST) utilizzato per l’invio del contenuto dei form al server non è sufficiente come contromisura. Infatti, se lato server tali variabili non vengono processate nel modo corretto, una richiesta di tipo POST può essere facilmente trasformata in una richiesta di tipo GET, quindi vulnerabile ai CSRF. Nella fattispecie, pur avendo un form simile al seguente:

<form method="post" action="page.php">
<fieldset>
<legend>Inserisci Contatto</legend>
<input type="text" name="nome" id="nome"/>nome:
<input type="text" name="cognome" id="cognome"/>cognome:
<input type="text" name="telefono" id="telefono"/>telefono:
<input type="submit" name="invia" id="invia" value="Invia"/>
</fieldset>
</form>

dove tutti i campi sono obbligatori, lo si potrebbe facilmente tradurre in questa chiamata HTTP GET:

http://www.nomesito.it/page.php?nome=Mario&cognome=Rossi&telefono=06676754&invia=Invia

Quindi, se un attaccante mandasse un’email contenente la suddetta URL alla vittima, e quest’ultima (che ha una sessione attiva su www.nomesito.it) cliccasse sul collegamento, automaticamente verrebbe salvato nel database un record Mario Rossi 06676754.

Pensate a cosa potrebbe succedere se il sito vulnerabile fosse quello di una banca e la URL trappola portasse l’utente vittima ad effettuare (a sua insaputa) un bonifico di N € sul c/c dell’attaccante…

Per fortuna si può correre ai ripari impostando alcuni meccanismi di sicurezza.

Per prima cosa, occorre scindere lato server (ad esempio nel codice PHP) le chiamate HTTP POST dalle chiamate HTTP GET, utilizzando le giuste variabili globali, ovvero $_POST nel primo caso e $_GET nel secondo.

Se si utilizzano la variabile $_POST ed il filtro sul referer HTTP i margini di sicurezza sono buoni (ma non ottimali), in quanto non potrà funzionare la tecnica enunciata in precedenza, ovvero la trasformazione delle chiamate HTTP POST in chiamate HTTP GET e non verranno accettate richieste provenienti da siti esterni.

Se invece si sceglie il GET come metodo di invio dei dati, oppure non si fa una scelta esplicita e si gestiscono i dati diretti al server mediante la variabile globale $_REQUEST (che non fà alcuna distinzione tra GET e POST), allora è assolutamente necessario procedere in questo modo:

1) si crea un stringa random (token);

2) tale token lo si associa automaticamente ad un campo di input hidden (nascosto);

3) si richiede che il valore del suddetto campo hidden sia uguale a quello del token affinchè si possano salvare i dati nel database.

Per intenderci, si potrebbe utilizzare il seguente codice PHP:

session_start();

$token = sha1(time());

$_SESSION['token'] = $token;

session_write_);

nella pagina del login, mentre in tutte le altre pagine il codice sarà:

session_start();

$token = $_SESSION['token'];

session_write_);

if(isset($_REQUEST['invia']))
{
    if(isset($_REQUEST['token']) && $_REQUEST['token'] == $token)
    {
          //invia i dati
    }

    else
    {
          die('Non hai i permessi per visualizzare la pagina');
    }
}

Il campo di input hidden è così definito:

<input type="hidden" name="token" id="token" value="<?php echo $token ?>"/>

Attraverso questa tecnica l’attaccante non potrà conoscere a priori il valore del token e quindi non sarà in grado di “forgiare” una URL malevola. Inoltre, è consigliabile utilizzare tale procedura anche se si utilizza la variabile $_POST, poichè il token è l’unica contromisura quasi infallibile contro gli attacchi in questione.

Un’altro metodo per mitigare i CSRF consiste nella verifica del campo HTTP_REFERER relativo all’header HTTP.

Però, poichè tale controllo è facilmente aggirabile (basti pensare che alcuni browser, tra i quali Firefox, non inviano per default il referer e che tale campo risulta comunque spoofabile, utilizzando ad esempio cULR), solitamente dedico il suo impiego alle sole pagine “riservate” (ovvero accesibili solo dopo autentica da parte dell’utente) che non prevedono l’invio di dati al server.

Il codice PHP è il seguente:

if($_SERVER['HTTP_REFERER'] != '' && !strstr($_SERVER['HTTP_REFERER'], "http://www.nomesito.it"))
{
        die('non hai i permessi per visualizzare la pagina');
}

In soldoni, verifico che il referer HTTP sia vuoto (per non penalizzare utenti legittimi che adoperano un browser che non invia i referer) oppure che contenga il dominio del mio sito, “accertandomi” così che l’utente non provenga da domini “esterni”.

Fine del post, fatene buon uso.

A presto.