2013-04-10 24 views
6

Ho questo gestore HTTP che ho creato per aggiornare le informazioni in un database SQL Express locale.Sanitizzazione della stringa per impedire i relativi percorsi URI

Mi sono reso conto che era possibile per un utente utilizzare i percorsi URI relativi "/../../file.zip" come stringa di query e sarebbe in grado di scaricare file al di fuori dell'area riservata.

Il sito non è ancora attivo, quindi non è un problema di sicurezza in questo momento, ma mi piacerebbe davvero evitare cose come questa.

Ho aggiunto una riga semplice string.replace che rimuove qualsiasi ".." dalla query di input.

C'è altro che dovrei fare qui per garantire questo?

public void ProcessRequest(HttpContext context) 
{ 
    string filesPath = "C:/Downloads/"; 
    string fileName = context.Request.QueryString["filename"]; 
    fileName = fileName.Replace("'", "''").Replace("..", "").Replace("/", "").Replace("\\", ""); 

    if (!string.IsNullOrEmpty(fileName) && File.Exists(filesPath + fileName)) 
    { 
     context.Response.ContentType = "application/octet-stream"; 
     context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", fileName)); 
     context.Response.WriteFile(filesPath + fileName); 
     //Do work to update SQL database here 
    } 
    else 
    { 
     context.Response.ContentType = "text/plain"; 
     context.Response.Write(filesPath + fileName + " Invalid filename"); 
    } 
} 
+1

In generale, è necessario rifiutare l'input non valido piuttosto che provare a rimuovere le sequenze dannose. Considera ciò che sostituisce con "./.". Ci sono anche molti schemi che causano stranezza, come nomi di file vuoti, punti e spazi iniziali e finali, caratteri di controllo, 'SHORTN ~ 1.AME' e potenzialmente i nomi file riservati (' com1' et al). Usare l'input nei nomi dei file è difficile da ottenere, [specialmente in Windows] (http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247 (v = vs.85) .aspx) - molto meglio se puoi (come suggerisce Jason) usa un ID generato per il nome del file sul disco locale. – bobince

+0

@bobince Ottimi consigli lì. Questo è il motivo per cui ho fatto la domanda, poiché sapevo che ci sarebbe stato un modo migliore per avvicinarsi a questo, stavo solo cercando un po 'di sicurezza su un problema importante come questo. –

risposta

10

io di solito uso questo semplice codice per controllare questo problema:

(digito direttamente in modo che non può compilare, è solo per darvi l'idea)

private string getPath(string basePath, string fileName) 
{ 
    var fullPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(basePath, fileName)); 
    if (fullPath.StartsWith(basePath)) 
     return fullPath; 
    return null; 
} 

L'obiettivo è quello di utilizzare Path.GetFullPath. Questo metodo tradurrà qualsiasi /../ etc in un percorso completo. Quindi verificare che il percorso restituito sia nella directory consentita.
fate attenzione che questo metodo può rendimenti leggermente diverso percorso del previsto, leggere MSDN per spiegazioni dettagliate

+1

Mi piace l'idea alla base di questo approccio: lascia che il sistema ti dica quale file sta per aprire e assicurati che sia valido. Se provi a mettere in blacklist caratteri o stringhe nel nome del file, ti mancheranno sicuramente qualcosa. –

+0

Ottima idea anche qui. Questo era quello che stavo cercando di fare in origine, ma non sono riuscito a trovare il metodo corretto da usare. GetFullPath è il metodo che non sono riuscito a trovare. –

2

si potrebbe avere Request.QueryString["filename"] in realtà essere una chiave che rappresenta un file. La chiave potrebbe essere un numero o una stringa casuale se non si desidera che gli utenti siano in grado di indovinare facilmente le chiavi dei file. È possibile archiviare il mapping in un database e utilizzare la chiave per recuperare il nome file locale (e magari un nome file visualizzato se si desidera che i due differiscano e in realtà nascondano i dettagli dell'implementazione).

+0

Questo è il modo migliore per farlo credo, ma ho risposto @Fabske perché ha risposto alla mia domanda originale. Non sono sicuro di come farlo, ma cercherò di utilizzare questo approccio. –