Nozioni basilari di (in)sicurezza delle applicazioni Web – Parte 5 – File Include & Upload

Tempo di lettura: 8 minuti
Data pubblicazione: April 7, 2017

Dopo aver introdotto gli attacchi XSS e Directory Traversal, passiamo oggi ad altre due tipologie di attacco, ossia File Include e File Upload. Come per gli altri attacchi, questi sfruttano sistemi di filtraggio mancanti o non presenti.

File Include

Wikipedia la definisce una delle vulnerabilità più comuni nelle applicazioni web, tanto semplice da violare quanto pericolosa (come al solito) per gli ignari utenti che visitano il sito attaccato.

Essa permette ad un attaccante di includere un file, utilizzandolo per redirezionare i visitatori su altre pagine o avere accesso a file non protetti direttamente dall’url (come nel caso del Directory Traversal). Chiaramente sfrutta la funzionalità include presente in PHP.

Avviso di sicurezza su php.net
Avviso di sicurezza su php.net

La vulnerabilità si può dividere in due tipi:

  1. Remote File inclusion: permette ad un attaccante di includere ed eseguire un file remoto_, _ad esempio uno script nella pagina attaccata. In questo modo l’attaccante può eseguire codice maligno temporaneamente sottraendo dati e informazioni agli utenti;
  2. Local File inclusion: consiste nell’includere file _locali _non protetti disponibili sul server ed avere accesso ad essi.

Esempio 1

Nel primo esempio è presente una vulnerabilità RFI, nel quale possiamo inserire url nella richiesta GET ed essi vengono inclusi nella pagina, caricati e visualizzati,

Esempio 1 risolto
Esempio 1 risolto

Ovviamente non ho inserito un file maligno, ma una semplice pagina internet. Si potrebbe tranquillamente inserire uno script caricato su un sito di nostra proprietà malevolo che sottrae dati e informazioni.

Il codice della pagina è

<code class="php"><span class="line"><span class="k">if</span> <span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s2">"page"</span><span class="p">])</span> <span class="p">{</span>
</span><span class="line">  <span class="k">include</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s2">"page"</span><span class="p">]);</span>
</span>
<span class="line"><span class="p">}</span>
</span></code>

inserito senza nessun controllo nè filtraggio. Un’approfondimento di questo attacco si può trovare sulla pagina OWASP.

Esempio 2

Questo esempio mostra come potrebbe essere attaccata una vulnerabilità di tipo LFI. Possiamo sfruttare le tecniche imparate nell’articolo di Directory Traversal, inserendo un NULL BYTE alla fine della stringa inserita.

Esempio 2 risolto
Esempio 2 risolto

Il codice in questo caso è

<code class="php"><span class="line"><span class="k">if</span> <span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s2">"page"</span><span class="p">])</span> <span class="p">{</span>
</span><span class="line"><span class="nv">$file</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s2">"page"</span><span class="p">]</span><span class="o">.</span><span class="s2">".php"</span><span class="p">;</span>
</span><span class="line"><span class="c1">// simulate null byte issue</span>
</span><span class="line"><span class="nv">$file</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\x00.*/'</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="nv">$file</span><span class="p">);</span>
</span><span class="line">  <span class="k">include</span><span class="p">(</span><span class="nv">$file</span><span class="p">);</span>
</span>
<span class="line"><span class="p">}</span>
</span></code>

Un approfondimento è presente a questo indirizzo.

File Upload

Nel caso voleste creare un applicazione web, dando la possibilità agli utenti di caricare i file,** ricordate sempre che l’input deve essere controllato**, sempre!

Anche questo attacco sfrutta problemi di filtraggio e validazione, ed è ancora più pericoloso. Dando all’utente la possibilità di caricare un file senza eseguire a lato server un controllo sui possibili file caricati, è come se gli deste direttamente il controllo della macchina.

Esempio 1

Come accennato, viene data la possibilità di caricare un file. Scelgo quindi una shell scritta in PHP, presa dalla solita lista. Dopo averla caricata, mi aspetto di avere un terminale su cui poter eseguire comandi ed una successiva, se possibile, privilege escalation.

Visualizzazione dei dettagli del server
Visualizzazione dei dettagli del server
Stampa del file password
Stampa del file password

Il codice è

<code><span class="pun"><?</span><span class="pln">php require_once</span><span class="pun">(</span><span class="str">'../header.php'</span><span class="pun">);</span> <span class="pun">?></span>


<span class="pun"><?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">])</span><span class="pun">)</span>
<span class="pun">{</span><span class="pln"> 
  $dir </span><span class="pun">=</span> <span class="str">'/var/www/upload/images/'</span><span class="pun">;</span><span class="pln">
  $file </span><span class="pun">=</span><span class="pln"> basename</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">][</span><span class="str">'name'</span><span class="pun">]);</span><span class="pln">
  </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">move_uploaded_file</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">][</span><span class="str">'tmp_name'</span><span class="pun">],</span><span class="pln"> $dir</span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">)</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
  echo </span><span class="str">"Upload done"</span><span class="pun">;</span><span class="pln">
  echo </span><span class="str">"Your file can be found <a href=\"/upload/images/"</span><span class="pun">.</span><span class="pln">htmlentities</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">).</span><span class="str">"\">here</a>"</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> 
  </span><span class="pun">{</span><span class="pln"> 
      echo </span><span class="str">'Upload failed'</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span>
<span class="pun">}</span>
<span class="pun">?></span></code>

Esempio 2

In questo caso viene bloccata la possibilità di caricare un file PHP, ma è facilmente aggirabile:

  • rinominando il file in .php3, .php4 o .php5 in base al sistema;
  • aggiungendo un’estensione che non esiste dopo il .php, in modo che il sistema carichi comunque il file;
  • caricando un file .htaccess, abilitando un’altra estensione da eseguire con PHP.
Estensione fittizia per aggirare il filtro
Estensione fittizia per aggirare il filtro

Il codice dell’applicativo è

<code><span class="pun"><?</span><span class="pln">php require_once</span><span class="pun">(</span><span class="str">"../header.php"</span><span class="pun">);</span> <span class="pun">?></span>

<span class="pun"><?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">]))</span>
<span class="pun">{</span><span class="pln"> 
  $dir </span><span class="pun">=</span> <span class="str">'/var/www/upload/images/'</span><span class="pun">;</span><span class="pln">
  $file </span><span class="pun">=</span><span class="pln"> basename</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">][</span><span class="str">'name'</span><span class="pun">]);</span>
    <span class="kwd">if</span> <span class="pun">(</span><span class="pln">preg_match</span><span class="pun">(</span><span class="str">'/\.php$/'</span><span class="pun">,</span><span class="pln">$file</span><span class="pun">))</span> <span class="pun">{</span><span class="pln">
        DIE</span><span class="pun">(</span><span class="str">"NO PHP"</span><span class="pun">);</span>
    <span class="pun">}</span>
  <span class="kwd">if</span><span class="pun">(</span><span class="pln">move_uploaded_file</span><span class="pun">(</span><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'image'</span><span class="pun">][</span><span class="str">'tmp_name'</span><span class="pun">],</span><span class="pln"> $dir </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">))</span>
  <span class="pun">{</span><span class="pln">
  echo </span><span class="str">'Upload done !'</span><span class="pun">;</span><span class="pln">
  echo </span><span class="str">'Your file can be found <a href="/upload/images/'</span><span class="pun">.</span><span class="pln">htmlentities</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">).</span><span class="str">'">here</a>'</span><span class="pun">;</span>
  <span class="pun">}</span>
  <span class="kwd">else</span> 
  <span class="pun">{</span><span class="pln"> 
      echo </span><span class="str">'Upload failed'</span><span class="pun">;</span>
  <span class="pun">}</span>
<span class="pun">}</span>
<span class="pun">?></span></code>

È molto simile a quello di prima, viene solo controllata l’estensione del file.

Conclusioni

Come abbiamo visto, sono tutti e due attacchi semplici ma molto efficaci. OWASP ha creato un’ottima pagina per l’upload di file non filtrati, con esempi, rischi e consigli per prevenire quest’ultima tipologia di attacco. Nei prossimi articoli continueremo ad approfondire altre tecniche di attacco.