2012-04-18 25 views
6

C'è qualche modo in Java per scrivere in un file temporaneo in modo sicuro?java equivalent per mkstemp

Per quanto posso dire, l'unico modo per creare un file temporaneo (createTempFile) does't realtà aprirlo, allo stesso tempo, quindi c'è una condizione di competizione tra file aperto & scrittura file. Mi sto perdendo qualcosa? Non sono riuscito a trovare il codice sorgente C dietro createFileExclusively (String) in UnixFileSystem.java, ma dubito che possa davvero fare qualcosa dato che il file aperto si verifica nel codice Java dopo la creazione del file temporaneo (a meno che non provi a fare qualcosa con serrature di file?).

Il problema

Tra quando viene creato il file temporaneo & lo si apre, un malintenzionato potrebbe scollegare quel file temporanei & mettere roba dannoso lì. Ad esempio, un utente malintenzionato potrebbe creare una named pipe per leggere dati sensibili. Analogamente, se alla fine copi il file leggendolo, la pipa denominata potrebbe ignorare tutto ciò che è stato scritto, &, fornire contenuti dannosi da leggere.

Ricordo di aver letto numerosi esempi di attacchi di file temporanei negli ultimi 10 anni che sfruttano la condizione di competizione tra quando il nome appare nello spazio dei nomi e quando il file viene effettivamente aperto.

Speriamo che un fattore attenuante è che Java impostato è l'umask correttamente in modo che un utente con meno privilegi non può leggere/scrittura al file e in genere nella directory/tmp limita i permessi correttamente in modo che non è possibile eseguire un attacco unlink.

Ovviamente se si passa una directory personalizzata per il file temporaneo di proprietà di un utente con privilegi inferiori che è stato compromesso, l'utente potrebbe eseguire un attacco di scollegamento contro di voi. Cavolo, con inotify, è probabilmente ancora più facile sfruttare la condizione della competizione che un semplice loop di forza bruta che fa un elenco di directory.

+3

Puoi spiegare quali condizioni di competizione esistono? –

+0

Qualsiasi aggiornamento su questo (come in soluzioni alternative o trucchi Java7)? –

+0

@Mr_and_Mrs_D Ho appena aggiunto una risposta reale. – OrangeDog

risposta

0

Ricordare che su molti sistemi, solo perché un file non ha un nome non significa affatto che sia inaccessibile. Ad esempio, su Linux i descrittori di file aperti sono disponibili in /proc/<pid>/fd/<fdno>. Quindi assicurati che il tuo uso di file temporanei sia sicuro anche se qualcuno conosce/ha un riferimento al file aperto.

È possibile ottenere una risposta più utile se si specificano esattamente le classi di attacchi che si tenta di impedire.

+0

Ma in genere richiede privilegi elevati, quindi non ti interessa; se l'attaccante ha il permesso di guardare nello spazio di memoria (che è essenzialmente quello che è in grado di accedere al tuo fds), allora non c'è nulla che tu possa fare. Possono accedere a/proc//maps e possono persino leggere/scrivere la memoria cruda tramite/proc//mem. – Vitali

0

Sicuro rispetto ad altri ID utente ordinari? Sì, su qualsiasi sistema multiutente funzionante correttamente.

Sicuro contro l'utente o il superutente? No.

1

http://kurt.seifried.org/2012/03/14/creating-temporary-files-securely/

Java

uso java.io.File.createTempFile() - alcune interessanti informazioni a http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/

per le directory c'è un messaggio di aiuto a How to create a temporary directory/folder in Java?

Java 7

per i file utilizzare java.io.File.createTempFile()

per le directory utilizzare createTempDirectory()

http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html

+0

leggi gli altri commenti che ho postato sul motivo per cui createTempFile non è abbastanza buono rispetto allo standard "gold" di mkstemp (la condizione di competizione mkstemp avoid è presente in createTempFile). Ma sì, non credo che ci sia un modo migliore integrato in Java per creare un file nello spazio dei nomi e aprirlo in 1 comando. – Vitali

+0

@Vitali - Credo che usando java.nio.file.Files (si noti che non è lo stesso percorso di classe di cui sopra) i metodi createTempFile e createTempDirectory fanno ciò che si desidera, perché è possibile specificare un parametro Attributo file che include opzioni atomiche specifiche , comprese le autorizzazioni da impostare durante la creazione della directory/file (che dovrebbe essere simile a come mkstemp gestisce le cose). Riferimenti: https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createTempFile | https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/FileAttribute.html –

+0

La cosa fondamentale che mkstemp fa aprire il file (quindi sai che hai aperto il file appena creato e non una sostituzione). Nessuna di queste soluzioni Java lo fa. – OrangeDog

0

Dal Java 7 che abbiamo OpenOption.

Un oggetto che configura come aprire o creare un file.

Oggetti di questo tipo sono utilizzati da metodi come newOutputStream, newByteChannel, FileChannel.open e AsynchronousFileChannel.open durante l'apertura o la creazione di un file.

Di particolare interesse è StandardOpenOptions.CREATE_NEW.

Creare un nuovo file, in mancanza se il file esiste già. Il controllo dell'esistenza del file e la creazione del file, se non esiste, è atomico rispetto ad altre operazioni del file system.

Quindi, si può fare qualcosa di simile:

FileChannel mkstemp() { 
    Path path = Files.createTempFile(null, null); 
    Files.delete(path); 
    return FileChannel.open(path, WRITE, CREATE_NEW); 
} 

Attuare lo stesso comportamento modello è lasciato come esercizio al lettore.