2013-04-10 23 views
6

Yerel bir SQL Express veritabanındaki bilgileri güncellemek için oluşturduğum bu HTTP işleyicisine sahibim.Göreli URI yollarını önlemek için dizgi temizleme

Bir kullanıcının, sorgu dizesi olarak "/../../file.zip" gibi göreli URI yollarını kullanmasının mümkün olduğunu ve kısıtlanmış alanın dışındaki dosyaları karşıdan yükleyebileceğini anladım.

Site henüz yayında değil, bu yüzden şu anda bir güvenlik sorunu değil, bunun gibi şeyleri önlemek isterim.

Giriş sorgusundan herhangi bir ".." öğesini kaldıran basit bir string.replace satırı ekledim.

Bunu sağlamak için burada yapmam gereken başka bir şey var mı?

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

Genelde, zararlı dizileri kaldırmaya çalışmak yerine geçersiz girdiyi reddetmelisiniz - değiştirmenin ne yaptığını düşünün. ./. Boş dosya isimleri, öndeki ve sondaki noktalar ve boşluklar, kontrol karakterleri, 'SHORTN ~ 1.AME' ve potansiyel olarak ayrılmış dosya adları ('com1' et al) gibi tuhaflıklara neden olan bir dizi desen de vardır. Dosya adlarında girdiyi kullanmak, özellikle Windows'da (http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247 (v = vs.85) .aspx) doğru almak zor. eğer yapabiliyorsanız (Jason'ın önerdiği gibi) yerel diskteki dosya adı için üretilmiş bir kimlik kullanın. – bobince

+0

@bobince Harika ipuçları var. Bu yüzden soruyu sordum, bunun için daha iyi bir yol olacağını bildiğimden, bunun gibi önemli bir konuya biraz baktım. –

cevap

10

Genellikle bu sorunu kontrol etmek için bu basit kodu kullanın:

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; 
} 

gol (derlenemeyecektir.Ancak olmayabilir bu yüzden size fikir vermek için sadece, doğrudan yazın) Path.GetFullPath kullanmaktır. Bu yöntem herhangi bir /../ etc dosyasını tam bir yola çevirecektir. Ardından, döndürülen yolun izin verilen dizinde olduğunu kontrol edin.
bu yöntem beklenenden daha slighty farklı yol, Sen Request.QueryString["filename"] aslında bir dosyayı temsil eden bir anahtar olabilir olabilir ayrıntılı açıklamalar

+1

Bu yaklaşımın arkasındaki fikirden hoşlanıyorum - sistemin hangi dosyayı açacağını size söyleyelim ve geçerli olduğundan emin olun. Eğer dosya isminde karakterleri veya dizeleri kara listeye almaya çalışırsanız, şüphesiz bir şeyleri özleyeceksiniz. –

+0

Burada da harika bir fikir. Bu, orijinal olarak yapmaya çalıştığım şeydi, ancak kullanılacak doğru yöntemi bulamadım. GetFullPath, bulamadığım yöntemdir. –

2

için MSDN okumak döner olabileceğini dikkatli olun. Kullanıcıların dosya anahtarlarını kolayca tahmin edebilmesini istemiyorsanız, anahtar bir sayı veya rastgele bir dize olabilir. Eşlemeyi bir veritabanında saklayabilir ve yerel dosya adını almak için anahtarı kullanabilirsiniz (ve ikisini değiştirmek ve gerçekten uygulama ayrıntılarınızı gizlemek istiyorsanız bir ekran dosya adı).

+0

Bunu yapmanın en iyi yolu bence, ama orijinal sorumu cevapladığından @Fabske cevabını işaretledim. Bunu nasıl yapacağımdan emin değilim, ama bu yaklaşımı kullanmaya bakacağım. –