Diventa Autore per CoreTech | Scopri di più
18/03/20 CoreTech Blog
OS command injection (iniezione di comando del sistema operativo o semplicemente iniezione di comando ) è un tipo di vulnerabilità injection. Il payload inserito dall'utente malintenzionato viene eseguito come comando del sistema operativo. Gli attacchi di inserimento di comandi del sistema operativo sono possibili solo nel caso in cui il codice dell'applicazione Web include chiamate al sistema operativo e l'input dell'utente viene utilizzato nella chiamata. Essi non hanno un linguaggio specifico - vulnerabilità di iniezione di comando possono apparire in tutti i linguaggi che consentono di chiamare un comando della shell di sistema: C, Java, PHP, Perl, Ruby, Python, e molti alti.
Il sistema operativo esegue i comandi arbitrari inseriti con i privilegi del server web. Pertanto, di per sé, la vulnerabilità di iniezione di comando non porta alla compromissione completa del sistema. Tuttavia, gli aggressori potrebbero essere in grado di utilizzare l'escalation dei privilegi e altre vulnerabilità per ottenere più accesso.
Nota: L'iniezione di comando è spesso confusa con l'iniezione di codice . Le vulnerabilità di inserimento di codice consentono all'utente malintenzionato di inserire un codice nel linguaggio di programmazione in cui è compilata l'applicazione Web.
Lo sviluppatore dell'applicazione PHP di esempio desidera che l'utente sia in grado di visualizzare l'output del comando Windows ping nell'applicazione web. L'utente deve inserire l'indirizzo IP e l'applicazione invia ping ICMP a tale indirizzo. Sfortunatamente, lo sviluppatore considera troppo attendibile l'utente e non esegue la convalida dell'input. L'indirizzo IP viene passato utilizzando il metodo GET e quindi utilizzato nella riga di comando.
<?php
$address = $_GET["address"];
$output = shell_exec("ping -n 3 $address");
echo "<pre>$output</pre>";
?>
L'utente malintenzionato abusa di questo script manipolando la richiesta GET con il seguente payload:
http://example.com/ping.php?address=8.8.8.8%26dir
La funzione shell_exec esegue il comando del sistema operativo seguente: ping -n 3 8.8.8.8&dir. Il simbolo & in Windows separa i comandi del sistema operativo. Di conseguenza, l'applicazione vulnerabile esegue un comando aggiuntivo (dir) e visualizza l'output del comando (elenco directory) sullo schermo:
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=30ms TTL=56
Reply from 8.8.8.8: bytes=32 time=35ms TTL=56
Reply from 8.8.8.8: bytes=32 time=35ms TTL=56
Ping statistics for 8.8.8.8:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 30ms, Maximum = 35ms, Average = 33ms
Volume in drive C is OS
Volume Serial Number is 1337-8055
Directory of C:\Users\Noob\www
(...)
È possibile utilizzare caratteri speciali diversi per inserire un comando arbitrario. Il più semplice e più comune per Linux è il punto e virgola (;) e per Windows, la e commerciale (&). Tuttavia, anche i seguenti payload per lo script ping.php funzioneranno:
Esistono diversi metodi per garantire la sicurezza dell'applicazione e impedire l'esecuzione arbitraria di comandi tramite inserimento di comandi. Il più semplice e sicuro è quello di non utilizzare mai chiamate come shell_exec in PHP per eseguire i comandi del sistema operativo host. È invece necessario utilizzare i comandi equivalenti del linguaggio di programmazione. Ad esempio, se uno sviluppatore desidera inviare posta utilizzando PHP su Linux/UNIX, potrebbe essere tentato di utilizzare il comando mail disponibile nel sistema operativo. Dovrebbero invece utilizzare la funzione mail() in PHP.
Questo approccio può essere difficile se non esiste un comando equivalente nel linguaggio di programmazione. Ad esempio, non esiste un modo diretto per inviare pacchetti ping ICMP da PHP. In questi casi, è necessario utilizzare l'igienizzazione dell'input prima di passare il valore a un comando della shell. Come con tutti i tipi di iniezioni, il modo più sicuro è quello di utilizzare una whitelist. Ad esempio, nello script ping.php, è possibile verificare se la variabile address è un indirizzo IP:
$address = filter_var($_GET["address"], FILTER_VALIDATE_IP);
Si sconsiglia di utilizzare le liste nere perché gli aggressori potrebbero trovare un modo per aggirarle. Tuttavia, se è assolutamente necessario utilizzare una lista nera, è necessario filtrare o eseguire l'escape dei seguenti caratteri speciali: