Megosztás a következőn keresztül:


CA2100: Sql-lekérdezések áttekintése biztonsági rések esetén

Tulajdonság Érték
Szabályazonosító CA2100
Cím Sql-lekérdezések áttekintése biztonsági rések esetén
Kategória Biztonság
A javítás kompatibilitástörő vagy nem törik Nem törés
Alapértelmezés szerint engedélyezve a .NET 8-ban Nem

Ok

A metódus a System.Data.IDbCommand.CommandText tulajdonságot egy karakterlánc argumentumból a metódusra épülő sztring használatával állítja be.

Ez a szabály alapértelmezés szerint a teljes kódbázist elemzi, de ez konfigurálható.

Szabály leírása

Ez a szabály feltételezi, hogy bármely sztring, amelynek értéke fordításkor nem határozható meg, felhasználói bemenetet tartalmazhat. A felhasználói bemenetből létrehozott SQL-parancssztring sebezhető az SQL-injektálási támadásokkal szemben. Sql-injektálási támadás esetén egy rosszindulatú felhasználó olyan bemenetet ad meg, amely megváltoztatja a lekérdezések kialakítását, és megpróbálja megrongálni vagy jogosulatlanul hozzáférni az alapul szolgáló adatbázishoz. A tipikus technikák közé tartozik egyetlen idézőjel vagy aposztróf injektálása, amely az SQL literális sztringelválasztója; két kötőjel, amely egy SQL-megjegyzést jelent; és pontosvesszővel, amely azt jelzi, hogy egy új parancs következik. Ha a felhasználói bemenetnek a lekérdezés részét kell képeznie, használja az alábbiak egyikét a hatékonyság sorrendjében felsorolva a támadás kockázatának csökkentéséhez.

  • Használjon tárolt eljárást.

  • Használjon paraméteres parancssztringet.

  • A parancssztring létrehozása előtt ellenőrizze a felhasználói bemenetet mind a típus, mind a tartalom esetében.

Az alábbi .NET-típusok implementálják a CommandText tulajdonságot, vagy sztringargumentum használatával konstruktorokat biztosítanak a tulajdonság beállításához.

Bizonyos esetekben előfordulhat, hogy ez a szabály nem határozza meg a sztring értékét fordításkor, még akkor sem, ha megteheti. Ezekben az esetekben ez a szabály hamis pozitív eredményt ad, ha ezeket a sztringeket SQL-parancsokként használja. Az alábbi példa egy ilyen sztringre mutat.

int x = 10;
string query = "SELECT TOP " + x.ToString() + " FROM Table";

Ugyanez vonatkozik implicit használat ToString() esetén is.

int x = 10;
string query = String.Format("SELECT TOP {0} FROM Table", x);

Szabálysértések kijavítása

A szabály megsértésének kijavításához használjon paraméteres lekérdezést.

Mikor kell letiltani a figyelmeztetéseket?

Ha a parancsszöveg nem tartalmaz felhasználói bemenetet, nyugodtan letilthatja a szabály figyelmeztetését.

Figyelmeztetés mellőzése

Ha csak egyetlen szabálysértést szeretne letiltani, adjon hozzá előfeldolgozási irányelveket a forrásfájlhoz a szabály letiltásához és újbóli engedélyezéséhez.

#pragma warning disable CA2100
// The code that's violating the rule is on this line.
#pragma warning restore CA2100

Ha le szeretné tiltani egy fájl, mappa vagy projekt szabályát, állítsa annak súlyosságát none a konfigurációs fájlban.

[*.{cs,vb}]
dotnet_diagnostic.CA2100.severity = none

További információ: Kódelemzési figyelmeztetések letiltása.

Kód konfigurálása elemzéshez

A következő beállítások segítségével konfigurálhatja, hogy a kódbázis mely részein futtassa ezt a szabályt.

Ezeket a beállításokat konfigurálhatja csak erre a szabályra, az összes szabályra, vagy az ebben a kategóriában szereplő összes szabályra (Biztonság), amelyekre vonatkozik. További információ: Kódminőségi szabály konfigurációs beállításai.

Adott szimbólumok kizárása

Bizonyos szimbólumokat, például típusokat és metódusokat kizárhat az elemzésből. Ha például meg szeretné adni, hogy a szabály ne fusson a nevesített MyTypetípusok egyikén sem, adja hozzá a következő kulcs-érték párot a projekt egyik .editorconfig fájljához:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

Engedélyezett szimbólumnévformátumok a beállításértékben (a következővel |elválasztva):

  • Csak szimbólumnév (a névvel ellátott összes szimbólumot tartalmazza, függetlenül attól, hogy milyen típusú vagy névtérrel rendelkezik).
  • A szimbólum dokumentációazonosító-formátumában szereplő teljes nevek. Minden szimbólumnévhez szimbólum típusú előtag szükséges, például M: metódusokhoz, T: típusokhoz és N: névterekhez.
  • .ctor konstruktorok és .cctor statikus konstruktorok számára.

Példák:

Beállítás értéke Összegzés
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType Megegyezik az összes elnevezett MyTypeszimbólummal.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 Megegyezik az összes elnevezett MyType1 szimbólummal vagy MyType2.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) Megfelel a megadott metódusnak MyMethod a megadott teljes jogosultsággal rendelkező aláírással.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) Egyezik az adott metódusokkal MyMethod1 és MyMethod2 a megfelelő, teljes mértékben minősített aláírásokkal.

Adott típusok és származtatott típusok kizárása

Bizonyos típusokat és azok származtatott típusait kizárhatja az elemzésből. Ha például meg szeretné adni, hogy a szabály ne fusson a nevesített MyType és származtatott típusok egyik metódusán sem, adja hozzá a következő kulcs-érték párot a projekt egyik .editorconfig fájljához:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

Engedélyezett szimbólumnévformátumok a beállításértékben (a következővel |elválasztva):

  • Csak típusnév (a névvel rendelkező összes típust tartalmazza, függetlenül attól, hogy milyen típust vagy névteret tartalmaz).
  • A szimbólum dokumentációazonosító-formátumában szereplő teljes nevek opcionális T: előtaggal.

Példák:

Beállítás értéke Összegzés
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType Megfelel az összes névvel ellátott MyType típusnak és az összes származtatott típusnak.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 Megfelel az összes névvel ellátott MyType1 típusnak, vagy MyType2 az összes származtatott típusnak.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType Egyezik MyType a megadott teljes névvel és az összes származtatott típusával.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 Egyezik az adott típusokkal MyType1 és MyType2 a megfelelő teljes névvel, valamint az összes származtatott típussal.

Példa

Az alábbi példa egy metódust mutat be, UnsafeQueryamely megsérti a szabályt és egy metódust, SaferQueryamely egy paraméteres parancssztring használatával teljesíti a szabályt.

Imports System
Imports System.Data
Imports System.Data.SqlClient

Namespace ca2100

    Public Class SqlQueries

        Function UnsafeQuery(connection As String,
         name As String, password As String) As Object

            Dim someConnection As New SqlConnection(connection)
            Dim someCommand As New SqlCommand()
            someCommand.Connection = someConnection

            someCommand.CommandText = "SELECT AccountNumber FROM Users " &
            "WHERE Username='" & name & "' AND Password='" & password & "'"

            someConnection.Open()
            Dim accountNumber As Object = someCommand.ExecuteScalar()
            someConnection.Close()
            Return accountNumber

        End Function

        Function SaferQuery(connection As String,
         name As String, password As String) As Object

            Dim someConnection As New SqlConnection(connection)
            Dim someCommand As New SqlCommand()
            someCommand.Connection = someConnection

            someCommand.Parameters.Add(
            "@username", SqlDbType.NChar).Value = name
            someCommand.Parameters.Add(
            "@password", SqlDbType.NChar).Value = password
            someCommand.CommandText = "SELECT AccountNumber FROM Users " &
            "WHERE Username=@username AND Password=@password"

            someConnection.Open()
            Dim accountNumber As Object = someCommand.ExecuteScalar()
            someConnection.Close()
            Return accountNumber

        End Function

    End Class

    Class MaliciousCode

        Shared Sub Main2100(args As String())

            Dim queries As New SqlQueries()
            queries.UnsafeQuery(args(0), "' OR 1=1 --", "[PLACEHOLDER]")
            ' Resultant query (which is always true):
            ' SELECT AccountNumber FROM Users WHERE Username='' OR 1=1

            queries.SaferQuery(args(0), "' OR 1=1 --", "[PLACEHOLDER]")
            ' Resultant query (notice the additional single quote character):
            ' SELECT AccountNumber FROM Users WHERE Username=''' OR 1=1 --'
            '                                   AND Password='[PLACEHOLDER]'
        End Sub

    End Class

End Namespace
public class SqlQueries
{
    public object UnsafeQuery(
       string connection, string name, string password)
    {
        SqlConnection someConnection = new SqlConnection(connection);
        SqlCommand someCommand = new SqlCommand();
        someCommand.Connection = someConnection;

        someCommand.CommandText = "SELECT AccountNumber FROM Users " +
           "WHERE Username='" + name +
           "' AND Password='" + password + "'";

        someConnection.Open();
        object accountNumber = someCommand.ExecuteScalar();
        someConnection.Close();
        return accountNumber;
    }

    public object SaferQuery(
       string connection, string name, string password)
    {
        SqlConnection someConnection = new SqlConnection(connection);
        SqlCommand someCommand = new SqlCommand();
        someCommand.Connection = someConnection;

        someCommand.Parameters.Add(
           "@username", SqlDbType.NChar).Value = name;
        someCommand.Parameters.Add(
           "@password", SqlDbType.NChar).Value = password;
        someCommand.CommandText = "SELECT AccountNumber FROM Users " +
           "WHERE Username=@username AND Password=@password";

        someConnection.Open();
        object accountNumber = someCommand.ExecuteScalar();
        someConnection.Close();
        return accountNumber;
    }
}

class MaliciousCode
{
    static void Main2100(string[] args)
    {
        SqlQueries queries = new SqlQueries();
        queries.UnsafeQuery(args[0], "' OR 1=1 --", "[PLACEHOLDER]");
        // Resultant query (which is always true):
        // SELECT AccountNumber FROM Users WHERE Username='' OR 1=1

        queries.SaferQuery(args[0], "' OR 1=1 --", "[PLACEHOLDER]");
        // Resultant query (notice the additional single quote character):
        // SELECT AccountNumber FROM Users WHERE Username=''' OR 1=1 --'
        //                                   AND Password='[PLACEHOLDER]'
    }
}

Lásd még