sql >> Databasteknik >  >> RDS >> Sqlserver

Hur ska jag skicka ett tabellnamn till en lagrad proc?

Först och främst bör du ALDRIG gör SQL-kommandokompositioner på en klientapp som den här, det är vad SQL Injection är. (Det är OK för ett administratörsverktyg som inte har några egna rättigheter, men inte för en applikation för delad användning).

För det andra, ja, ett parametriserat anrop till en lagrad procedur är både renare och säkrare.

Men , eftersom du kommer att behöva använda Dynamic SQL för att göra detta, vill du fortfarande inte inkludera den skickade strängen i texten i den körda frågan. Istället vill du använda den skickade strängen för att slå upp namnen på den faktiska tabeller som användaren ska tillåtas att fråga i vägen.

Här är ett enkelt naivt exempel:

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

Vissa har rättvist frågat varför detta är säkrare. Förhoppningsvis kan lilla Bobby Tables göra detta tydligare:0

Svar på fler frågor:

  1. Enbart QUOTENAME är inte garanterat säkert. MS uppmuntrar oss att använda det, men de har inte gett någon garanti för att det inte kan överskuggas av hackare. FYI, verklig säkerhet handlar om garantierna. Tabelluppslagningen med QUOTENAME är en annan historia, den är okrossbar.

  2. QUOTENAME är inte strikt nödvändig för det här exemplet, endast uppslagsöversättningen på INFORMATION_SCHEMA är normalt tillräcklig. QUOTENAME är med här eftersom det är en bra form inom säkerhet att inkludera en komplett och korrekt lösning. QUOTENAME här skyddar faktiskt mot ett distinkt, men liknande potentiellt problem som kallas latent injektion .

Jag bör notera att du kan göra samma sak med dynamiska kolumnnamn och INFORMATION_SCHEMA.COLUMNS tabell.

Du kan också kringgå behovet av lagrade procedurer genom att använda en parameteriserad SQL-fråga istället (se här:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=nätverksram-4.8). Men jag tror att lagrade procedurer ger en mer hanterbar och mindre felbenägen säkerhetsfacilitet för fall som detta.



  1. Hur man kontrollerar MySQL-databasstorlek i Linux

  2. skillnaden mellan primärnyckel och unik nyckel

  3. 27 oracle dba-skript för Oracle Database för administration och övervakning

  4. Hur ska jag tackla --secure-file-priv i MySQL?