2013-01-14 15 views
10

DB erişim katmanımızda bazı dinamik sorgu oluşturma işlemlerine sahibiz. Elbette bir şey mümkün enjeksiyon saldırıları önlemek için yapılmalıdır böyleceORDER BY deyiminde SQL Injection'ı önleyin yan tümce

protected string BuildSortString(string sortColumn, string sortDirection, string defaultColumn) 
{ 
    if (String.IsNullOrEmpty(sortColumn)) 
    { 
     return defaultColumn; 
    } 

    return String.Format("{0} {1}", sortColumn, sortDirection); 
} 

sorundur, sortColumn ve sortDirection hem dizeleri olarak dışarıdan geliyor: Örneğin, bir ORDER BY maddenin bir parçası oluşturmak için aşağıdaki yöntemi var . Bunun nasıl yapılabileceği hakkında bir fikri olan var mı? Eğer dizeleri uğraşmak zorunda varsa

cevap

11

, ardından beyaz listeleme en iyi bahistir. İlk olarak, sortDirection, beyaz listeye oldukça önemsiz olmalıdır: Bir büyük/küçük harfe duyarlı olmayan "asc"/"desc" ile karşılaştırmalı ve ayarlanmalıdır. Diğerleri için tercihim bilinen sütunlara numaralı sütunlarda, veriler ve doğrulama için beklenen Type numarasından geçerek olabilir. Ama mutlak bir tutam, sen (demek) zorlamak için regex ile tüm kesinlikle alfa-sayısal (az, AZ, 0-9 aralığında - belki alt çizgi gerekirse) - ve sonra [], yani

ekleyin
return string.Format("[{0}] {1}", sortColumn, sortDirection); 

Ancak, bilinen sütunların katı beyaz listesi, yön için bir numara gibi çok daha iyi olurdu.

+0

+1, ben "mutlak tutam" konulu kişisel vurgu ekleyeceğiz, normalde bu yüzden alanları sipariş edilebileceği üzerinde kontrole sahip beyaz listeye istiyorum tarafından (veya bu konu için sorgulanan). Karar vermek için müşteriye bırakmak, hangi sorguları optimize edeceğini öğrenmek için muhtemelen birden çok müşteriyi analiz etmeniz gerektiği anlamına gelir. Orada, bitti, eğlenceli değil: -/ –

+1

İlk bakışta bizim durumumuzda bir beyaz liste oluşturmak mümkündür. Bir deneyelim, teşekkürler Mark. – Andrei

0

Geçilen sütun adını ve yönünü temel alarak geçiş yaptığınız büyük bir CASE deyimini kullanarak bunu yapabilirsiniz. There's an SO answer on that here.

SELECT 
    * 
FROM 
    My_Table 
WHERE 
    Whatever = @something 
ORDER BY 
    CASE @sort_order 
      WHEN 'ASC' THEN 
       CASE @order_by 
        WHEN 'surname' THEN surname 
        WHEN 'forename' THEN forename 
        WHEN 'fullname' THEN fullname 
        ELSE surname 
       END 
      ELSE '1' 
    END ASC, 
    CASE @sort_order 
      WHEN 'DESC' THEN 
       CASE @order_by 
        WHEN 'surname' THEN surname 
        WHEN 'forename' THEN forename 
        WHEN 'fullname' THEN fullname 
        ELSE surname 
       END 
      ELSE '1' 
    END DESC 
+2

Bu tür TSQL inşası, (benim tecrübemde) sadece gerçekleştirmeyen kesinlikle korkunç planlarla sonuçlanma eğilimindedir. –

0

Çözüm: Sen gibi kod bakarak olacağız cmd.Parameters veya EscapedString ama (her zaman işe ve beklenen İstisnalar keyfini) cmd.Parameters tercih

örnek:

cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)"; 
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1; 
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2; 

Using prepared statements with parameters helps to defend against SQL injection in most common cases, when you would otherwise interpolate untrusted content into a string and then execute the string as an SQL statement.

But a query parameter takes the place of a single value. You can't use a query parameter as a substitute for a dynamic table name, column name, list of values (e.g. for an IN() predicate), expressions, or SQL keywords.

For those cases, you can use techniques like filtering or whitelisting so you don't interpolate untrusted content into your SQL strings.

Filtering is where you strip out any characters that would cause trouble. If you know your dynamic column name should only be alphanumeric characters, then apply a filter to your variable before using it in SQL. Or else just reject a variable if it doesn't match a regular expression like /^[A-Za-z0-9]*$/

+3

@Destrictor Downvote benim değil, ama OP ile ilgili cevabı. OP'nin başlığını tekrar okuyun "** ORDER BY deyiminde SQL Injection'u önleme **" –

+0

parametreleri "order by" için geçerli değildir - Wolfwyrd'nin yanıtı –

+1

@Destrictor gibi bir aşırı karmaşık sorgu yapmadıkça, bu parametre değiştirilemez hayır, en azından aynı şekilde olamazlar.'foo' tarafından verilen sipariş, temelde '1'e göre sıralama' ile aynıdır - bu sabittir ve herhangi bir sıralama yapmaz. Bu nedenle, açıkça bir sözdizimi hatasıdır: '1 numaralı SİPARİŞ BY tarafından tanımlanan SELECT öğesi, bir sütun konumunu tanımlayan ifadenin bir parçası olarak bir değişken içerir. Değişkenlere yalnızca bir sütun ismine referans veren bir ifade ile sipariş verirken izin verilir. ' –

1

Eğer int yerine string parametrelerini kabul etmek için yöntemini değiştirmek eğer Başka bir çözüm.

protected string BuildSortString(int sortColumn, int sortDirection, string defaultColumn) 
{ 
    if (String.IsNullOrEmpty(sortColumn)) 
    { 
     return defaultColumn; 
    } 
//sortdirection 0-> "ASC" else "DESC" 
//sorColumn 1 for your firstcolumn, 2 for your second column etc. 
    return String.Format("{0} {1}", sortColumn, sortDirection==0? " ASC " : " DESC "); 
} 

İyi şanslar.

0

Böyle bir şey yapabileceğini:

public string BuildSortString(string sortColumn, SortDirection direction, string defaultColumn) 
{ 
    string sortDirection = direction.ToString(); 

    if (String.IsNullOrEmpty(sortColumn)) 
    { 
     return VerifyColumn(defaultColumn); 
    } 

    return String.Format("{0} {1}", VerifyColumn(sortColumn), sortDirection); 
} 

private string VerifyColumn(string column) 
{ 
    switch (column) // fill this with a whitelist of accepted columns 
    { 
     case "some_column": 
      return column; 
    } 

    return String.Empty; // the column must be invalid (do whatever you want here) 
} 

public enum SortDirection 
{ 
    ASC, DESC 
} 
İlgili konular