Versione sicura di Path.Combine
-
03-07-2019 - |
Domanda
Ho un rootPath
di cui mi fido e un relativePath
che non ho. Voglio combinarli in modo tale da essere sicuro che il risultato sia rootPath
e che l'utente non possa usare ..
per tornare indietro punto. Voglio fare il percorso relativo per consentire cose come: ciao \ .. \ mondo
== world
Soluzione
Per espandere: usa Path.Combine, quindi chiama GetFullPath sul risultato e controlla che quel risultato inizi con rootPath.
Non ti proteggerà dagli hardlink, ma dovrebbe catturare cose semplici come i punti doppi.
quanto sopra come codice:
string Resolve(string fileName)
{
string root = FileRoot();
string ret = Path.GetFullPath(Path.Combine(root, fileName));
if (ret.StartsWith(root.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar)) return ret;
throw new ArgumentException("path resolved to out of accesable directroy");
}
Altri suggerimenti
Potresti semplicemente chiamare Path.GetFullPath ()
e verificare se inizia con il tuo rootPath
affidabile. Se tendi alla paranoia, controlla anche che rootPath
sia rootato
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Patch.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
Per una spiegazione del primo test vedere il commento di Alex Martelli sulla risposta del tecnophile.
Una cosa che puoi fare è contare il numero di barre rovesciate ( \
) e punti doppi ( ..
) e assicurarti che il numero di double- i punti sono più piccoli del numero di barre rovesciate. Per andare al di sopra del rootPath
nella struttura della tua cartella, avrai bisogno di almeno tutte le barre rovesciate come i punti doppi - quindi, se consenti solo relativePath
con almeno un'altra barra rovesciata, dovresti essere al sicuro.