sql >> Database >  >> RDS >> Sqlserver

Hoe moet ik een tabelnaam doorgeven aan een opgeslagen proces?

Allereerst moet u NOOIT doe SQL-commandocomposities op een client-app zoals deze, dat is wat SQL-injectie is. (Het is OK voor een admin-tool die geen eigen rechten heeft, maar niet voor een applicatie voor gedeeld gebruik).

Ten tweede, ja, een geparametriseerde oproep naar een opgeslagen procedure is zowel schoner als veiliger.

Echter , aangezien u hiervoor Dynamic SQL moet gebruiken, wilt u de doorgegeven string nog steeds niet in de tekst van de uitgevoerde query opnemen. In plaats daarvan wil je de doorgegeven string gebruiken om de namen op te zoeken van de werkelijke tabellen die de gebruiker moet kunnen opvragen.

Hier is een eenvoudig naïef voorbeeld:

CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS
-- Counts the number of rows from any non-system Table, *SAFELY*
BEGIN
    DECLARE @ActualTableName AS NVarchar(255)

    SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME = @PassedTableName

    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';'

    EXEC(@SQL)
END

Sommigen hebben terecht gevraagd waarom dit veiliger is. Hopelijk kunnen kleine Bobby Tables dit duidelijker maken:0

Antwoorden op meer vragen:

  1. QUOTENAME alleen is niet gegarandeerd veilig. MS moedigt ons aan om het te gebruiken, maar ze hebben geen garantie gegeven dat het niet door hackers kan worden omzeild. Ter info, bij echte beveiliging draait alles om de garanties. Het opzoeken van tabellen met QUOTENAME is een ander verhaal, het is onbreekbaar.

  2. QUOTENAME is niet strikt noodzakelijk voor dit voorbeeld, de Lookup-vertaling op INFORMATION_SCHEMA alleen is normaal gesproken voldoende. QUOTENAME staat hier omdat het in de beveiliging een goede vorm is om een ​​volledige en correcte oplossing op te nemen. QUOTENAME hier beschermt in feite tegen een duidelijk, maar vergelijkbaar potentieel probleem dat bekend staat als latente injectie .

Ik moet er rekening mee houden dat u hetzelfde kunt doen met dynamische kolomnamen en de INFORMATION_SCHEMA.COLUMNS tafel.

U kunt de noodzaak van opgeslagen procedures ook omzeilen door in plaats daarvan een geparametriseerde SQL-query te gebruiken (zie hier:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netwerk-4.8). Maar ik denk dat opgeslagen procedures een beter beheersbare en minder foutgevoelige beveiligingsfaciliteit bieden voor gevallen als deze.



  1. Registreer en voer PostgreSQL 9.0 uit als Windows-service

  2. SQL INTERSECT

  3. Hoge beschikbaarheid van PostgreSQL met master-slave- en master-masterarchitecturen

  4. PostgreSQL:een berekende kolom gebruiken in dezelfde query