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.
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.
La vulnerabilità si può dividere in due tipi:
Nel primo esempio è presente una vulnerabilità RFI, nel quale possiamo inserire url nella richiesta GET ed essi vengono inclusi nella pagina, caricati e visualizzati,
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.
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.
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.
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.
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.
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>
In questo caso viene bloccata la possibilità di caricare un file PHP, ma è facilmente aggirabile:
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.
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.