I programmi dovrebbero controllare i collegamenti simbolici prima di creare file?

2

Abbiamo ricevuto una segnalazione di bug (formulata come problema di sicurezza) per un programma, in cui si affermava che quando il programma crea file su disco, non verifica per prima cosa se esiste un collegamento simbolico sul percorso del file da creare. Per questo motivo, un utente malintenzionato può creare un collegamento simbolico, che il programma (quando viene eseguito da un altro utente) può provare a sovrascrivere, sovrascrivendo in tal modo un file a cui l'utente malintenzionato potrebbe altrimenti non avere accesso in scrittura.

Per illustrare, ecco un esempio con gcc, che è anche "vulnerabile" a questo problema:

  1. Eve invia ad Alice un file .tar.gz contenente un programma C. All'interno dell'archivio è evil.c e a.out , che è un collegamento simbolico a /home/alice/.xinitrc .
  2. Sotto qualche pretesa, Eva chiede ad Alice di compilare il programma (e non fare nient'altro).
  3. Eve esegue gcc evil.c , che di per sé dovrebbe essere sicuro (escludendo buffer overflow ecc. nel compilatore).
  4. gcc (tecnicamente il linker) proverà a scrivere il binario risultante in a.out , quindi sovrascrivendo .xinitrc di Alice.
  5. La prossima volta che Alice avvia il suo server X, viene eseguito il codice di Eve.

Nel nostro caso, la situazione è molto simile a gcc - il programma crea file solo nella directory corrente (a meno che non sia detto altrimenti), con nomi prevedibili, e di per sé non esegue alcun codice dal suo input.

È qualcosa di cui i programmi come i compilatori devono preoccuparsi?

    
posta Vladimir Panteleev 08.07.2017 - 00:26
fonte

2 risposte

1

Sì, i programmi dovrebbero prestare attenzione ai collegamenti simbolici se i programmi leggono o scrivono file da / a directory in cui gli utenti con privilegi inferiori possono creare collegamenti simbolici. Altrimenti è possibile che un utente possa leggere o scrivere su file che dovrebbero essere protetti.

Ma dovresti evitare un controllo come if(!issymlink(path)) { writeto(path) } perché sarebbe soggetto a una condizione di competizione. Ad esempio, in linux, puoi utilizzare il flag O_NOFOLLOW in open per fallire con un errore se il percorso punta a un collegamento simbolico.

    
risposta data 20.07.2017 - 10:00
fonte
1

Questo è un problema di programmazione generale. In effetti, dovresti chiederti se vuoi sovrascrivere tutti i link al file quando è moltiplicato. Il bug report si riferisce solo a collegamenti simbolici, ma potrebbe esistere un problema equivalente con i collegamenti fisici:

  • l'utente A usa il programma per generare (e sovrascrivere se esiste) un file nella cartella F (diciamo /F/app_file )
  • l'utente A ha accesso in scrittura alla cartella G
  • l'utente B ha accesso in scrittura alla cartella F ma non alla cartella G
  • l'utente B collega un file dalla cartella G alla cartella F ( ln /G/file /F/app_file )
  • l'utente A esegue il programma e sovrascrive il file nella cartella G

Non è nemmeno strettamente correlato a Unix, dal momento che Windows supporta anche collegamenti e giunzioni (come hai detto nel commento).

Il modo comune per evitare questo problema è provare a scollegare il file prima di scriverci (assumendo il linguaggio C):

remove(filepath);                  // unlink the file if it was previously multiply linked
FILE *fd = fopen(filepath, "w");   // will not overwrite any file other than filepath
    
risposta data 20.07.2017 - 10:52
fonte

Leggi altre domande sui tag