Tenemos un montón de procedimientos almacenados de SQL Server que se basan en SQL dinámico.

Los parámetros para el procedimiento almacenado se utiliza en una instrucción SQL dinámico.

Necesitamos un estándar de la función de validación dentro de estos procedimientos almacenados para validar estos parámetros y evitar la inyección de código SQL.

A asumir que tienen estas restricciones:

  1. No podemos reescribir los procedimientos para no utilizar SQL Dinámico
  2. Que no podemos usar sp_OACreate etc., utilizar expresiones regulares para la validación.
  3. Que no podemos modificar la aplicación a la que llama al procedimiento almacenado para validar los parámetros antes de que se pasan al procedimiento almacenado.

Hay una serie de personajes que podemos filtrar para asegurar que no son susceptibles a la inyección de SQL?

ouch. normalmente es 3) que deben ser modificados para evitar la inyección de código SQL. Recuerde, es «SQL Injection», no «SQL Rechazo». Una vez que se llega a la base de datos, ya debe ser limpiado. Pero si usted dice que no se puede cambiar la aplicación, entonces supongo que no se puede. Interesados para ver las respuestas.

OriginalEl autor frankadelic | 2010-11-04

8 Comentarios

  1. 10

    Creo que hay tres casos diferentes que usted tiene que preocuparse acerca de:

    • cadenas (algo que requiere comillas): '''' + replace(@string, '''', '''''') + ''''
    • nombres (nada donde cotizaciones no están permitidos): quotename(@string)
    • cosas que no puede ser citado: esto requiere la creación de listas blancas

    Nota: Todo en una variable de cadena (char, varchar, nchar, nvarchar, etc.) que viene de usuario-fuentes controladas, debe utilizar uno de los métodos anteriores. Esto significa que incluso las cosas que esperan ser números citada si están almacenados en las variables de cadena.

    Para obtener más detalles, consulte el Microsoft Revista (Obsoleto enlace: 2016-10-19).

    He aquí un ejemplo utilizando los tres métodos:

    EXEC 'SELECT * FROM Employee WHERE Salary > ''' +
         REPLACE(@salary, '''', '''''') +   -- replacing quotes even for numeric data
         ''' ORDER BY ' + QUOTENAME(@sort_col) + ' ' +  -- quoting a name
         CASE @sort_dir WHEN 'DESC' THEN 'DESC' END     -- whitelisting

    También tenga en cuenta que al hacer todas las operaciones de cadena en línea en la EXEC declaración de que no hay preocupación con el truncamiento de los problemas. Si asigna los resultados intermedios de las variables, debe asegúrese de que las variables son suficientemente grandes como para sostener los resultados. Si usted SET @result = QUOTENAME(@name) debe definir @result a contener, al menos, 258 (2 * 128 + 2) caracteres. Si usted SET @result = REPLACE(@str, '''', '''''') debe definir @result a ser dos veces el tamaño de @str (suponga que cada personaje en @str podría ser una cita). Y, por supuesto, la variable de la cadena de la celebración de la final de la instrucción SQL debe ser lo suficientemente grande para contener todos los SQL estático, además de las variables de resultado.

    Estoy de acuerdo aquí, que depende totalmente de lo que SQL se está construyendo

    OriginalEl autor Gabe

  2. 6

    Los casos triviales puede ser fijado por la QUOTENAME y REEMPLAZAR:

    set @sql = N'SELECT ' + QUOTENAME(@column) + 
       N' FROM Table WHERE Name = ' + REPLACE(@name, '''', '''''');

    Aunque QUOTENAME puede ser utilizado en los literales demasiado para agregar las comillas simples y reemplazar las comillas simples con doble comillas simples, porque se trunca la entrada a 128 caracteres no se recomienda.

    Pero esto es sólo la punta del iceberg. Hay varias partes de nombres (dbo.table) usted necesita tomar el cuidado apropiado de: citando el multipartname daría como resultado un identificador no válido [dbo.table], se ha de analizar y dividir (con PARSENAME), luego debidamente citadas en [dbo].[table].

    Otro problema es el truncamiento de los ataques, lo cual puede ocurrir incluso si el trivial REEMPLAZAR en los literales, ver Nueva SQL Truncamiento de los Ataques Y Cómo evitarlos.

    El problema de la Inyección de SQL nunca puede ser resuelto con una función mágica ubicada en cada procedimiento. Es como preguntar «quiero una función que va a hacer que el código se ejecute más rápido». La prevención de los ataques de inyección es y end-to-end juego que requiere la codificación de la disciplina todo el camino a través de, no se puede añadir simplemente como una idea de último momento. Su mejor oportunidad es para inspeccionar cada procedimiento y analizar el T-SQL de código línea-por-línea, con un ojo abierto para las vulnerabilidades, a continuación, solucionar los problemas como se encuentran.

    Recomiendo no el uso de PARSENAME ya que está diseñada para ser utilizada en el ya citado nombres. Si el usuario indica que desea obtener los datos de secret..table desea consultar en contra de [secret..table] y obtener un error. Usted no quiere que él para ser capaz de consultar [secret]..[table]!
    En mi opinión, la ejecución de cualquier SQL dinámico usar cualquier otra cosa que sp_executesql con todos los valores pasados como parámetros es pura negligencia.

    OriginalEl autor Remus Rusanu

  3. 4

    Con estas restricciones que son bastante jodidos.

    Aquí hay dos opciones que podrían dar alguna dirección:

    1. Uso de la lista blanca validador/parser que solo acepta consultas que se presentan en un formato y con palabras clave y las tablas que se espera. Esta será probablemente sólo trabajo con un muy buen analizador SQL que realmente entiende la sintaxis.

    2. Ejecutar consultas en un entorno restringido. Por ejemplo, el uso de una cuenta de usuario con derechos limitados. Por ejemplo, sólo permiten (leer) el acceso a ciertos puntos de vista que nunca volverán a datos sensibles y no permitir el acceso a todos los otros puntos de vista, todos los procedimientos almacenados, funciones y tablas. Incluso más seguro es ejecutar las consultas en otro servidor de base de datos. También no se olvide de desactivar el OPENROWSET comando.

    Tenga en cuenta lo siguiente:

    1. Cuando usted acepta todas las consultas excepto los que tienen las palabras clave inválidas, definitivamente va a fallar, porque el negro listado de siempre falla. Especialmente con un lenguaje complicado como SQL.

    2. No olvides que permite SQL dinámico a partir de fuentes que no se puede confiar en que es el mal en su sentido más puro, incluso cuando el uso de estos consejos, porque de vez en cuando bugs se descubrió que puede ser objeto de abuso por el envío de especialmente diseñado SQL en un servidor. Por lo tanto, incluso si usted aplica estos consejos, el riesgo sigue ahí.

    3. Cuando usted decide ir con una solución que permite a SQL dinámico. Por favor, no piense que usted puede venir para arriba con una solución segura, especialmente si usted está tratando de proteger los datos empresariales confidenciales. Contratar a un servidor de base de datos especialista en seguridad para ayudar con eso.

    OriginalEl autor Steven

  4. 3

    Esta es una muy desagradable problema, su no un problema que se quiere resolver, sin embargo, aquí es un caso trivial de que funciona, (revisores, por favor, hágamelo saber si me he perdido un caso, este viene con NO garantías)

    create proc Bad 
      @param nvarchar(500) 
    as 
    
    exec (N'select ''' + @param + N'''') 
    
    go
    
    -- oops injected
    exec Bad 'help'' select ''0wned!'' select ''' 
    
    go 
    
    create proc NotAsBad
       @param nvarchar(500) 
    as 
    
    declare @safish nvarchar(1000), @sql nvarchar(2000) 
    set @safish = replace(@param, '''', '''''')
    
    set @sql = N'select ''' + @safish  + N''''
    
    exec (@sql) 
    
    go 
    
    -- this kind of works, but I have not tested everything
    exec NotAsBad 'help'' select ''0wned!'' select ''' 
    +1, yo nunca he visto nada que sugiera que esto no funciona.
    En mi opinión, la ejecución de cualquier SQL dinámico usar cualquier otra cosa que sp_executesql con todos los valores pasados como parámetros es pura negligencia.
    Sigue siendo vulnerable. Supongamos que el cuerpo de NotAsBad contiene lo siguiente: set @sql = N select * from ‘ [email protected] ….si el usuario puede adivinar el nombre de una tabla pueden presentar @param = ‘tablename; caída de la base de datos xyz; –‘
    esto funciona bien para el caso trivial, por supuesto, dependiendo de su contexto que necesita para escapar de sql en diferentes formas, de ahí la advertencia en contra de hacer esto, estoy de acuerdo con @KM, en general, esto es algo como esto es una mala idea y no un problema que se quiere resolver

    OriginalEl autor Sam Saffron

  5. 2

    OWASP tiene alguna información sobre esta estrategia. Debe ser siempre un último y desesperado opción (como se explica en el artículo que estoy enlazando a), pero si es la única opción…

    http://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

    una cita de un artículo acerca de ser un desesperado opción

    Sin embargo, esta metodología es frágil
    en comparación con el uso parametrizada
    las consultas. Esta técnica sólo debe ser
    utiliza, con precaución, para modernizar el legado
    código de una manera rentable.
    Las aplicaciones creadas a partir de cero, o
    aplicaciones que requieren bajo riesgo
    la tolerancia debe ser construido o
    re-escrito, utilizando con parámetros
    las consultas.

    En esencia, el argumento en contra de este enfoque es, incluso si usted hace escapar de todo el conocido mal de entrada, no hay ninguna garantía de que alguien no quiere venir para arriba con una manera de evitar esto en el futuro.

    Sin embargo, para responder a su pregunta específicamente…

    una lista de los caracteres de escape está en el artículo que he enlazado más arriba.

    Editar Como se señaló, el artículo no proporciona muy buenos enlaces. Sin embargo, para SQL Server, este no: http://msdn.microsoft.com/en-us/library/ms161953.aspx

    Tenga en cuenta que la lista de caracteres que necesita para escapar variará dependiendo de la base de datos de la plataforma, pero parece que usted está utilizando SQL Server, por lo que este debe ser relevante..

    Cita del artículo a continuación:

    Filtrado de entrada también puede ser útil en la protección contra inyección SQL mediante la eliminación de los caracteres de escape. Sin embargo, debido a la gran cantidad de personajes que pueden presentar problemas, esto no es una defensa confiable. El siguiente ejemplo busca el delimitador de cadena de caracteres.

    private string SafeSqlLiteral(string inputSQL)
    {
      return inputSQL.Replace("'", "''");
    }

    COMO Cláusulas

    Tenga en cuenta que si usted está utilizando una cláusula similar, los caracteres comodín todavía debe ser escapado:

    s = s.Replace("[", "[[]");
    s = s.Replace("%", "[%]");
    s = s.Replace("_", "[_]");
    -1: El artículo no dice lo que los caracteres de escape para MS SQL Server. Sólo vincula a otro artículo que no se haga evidente que los caracteres de escape.
    Estás en lo correcto. La edición de mi respuesta.

    OriginalEl autor David

  6. 2

    Hay una serie de personajes que podemos filtrar para asegurar que no son susceptibles a la inyección de SQL?

    NO

    De inyección SQL no es llamado un «Cierto Conjunto De Caracteres de la Inyección», y por una razón. El filtrado de cierto personaje podría complicar el particular explotar, pero no evitar la inyección de código SQL en sí. Para explotar una inyección SQL que uno tiene que escribir SQL. Y SQL no está limitado a unos pocos caracteres especiales.

    OriginalEl autor Your Common Sense

  7. 0

    Se puede obtener de SQL CLR puede ser de gran utilidad — al menos puede utilizar para escribir mucho, mucho más eficaz en la desinfección de lo que se puede hacer usando T-SQL. En un perfact mundo, puede reemplazar el almacenado de los procs completamente con parametrizada declaraciones y otras estructuras más sólidas.

    por desgracia, no puedo utilizar el CLR debido a restricciones DBA

    OriginalEl autor Wyatt Barnett

  8. -1

    Existe otro enfoque que puede, posiblemente, el trabajo, aunque depende de lo que los personajes están permitidos en el procedimiento almacenado de parámetros. En lugar de escapar los caracteres problemáticos que pueden ser utilizados para la inyección de SQL, eliminar a los personajes en su lugar. Por ejemplo, si usted tiene este SP:

    create procedure dbo.MYSP(@p1 varchar(100))
    as begin
      set @p1 = Replace(@p1, '''',' '); -- Convert single quotes to spaces
      set @p1 = Replace(@p1, ';', ' ');
      set @p1 = Replace(@p1, '--', ' ');      
      set @p1 = Replace(@p1, '/*', ' ');      
      set @p1 = Replace(@p1, '*/', ' ');      
      set @p1 = Replace(@p1, 'xp_', ' ');      
      ...
    end;

    que puede sustituir a cualquier comillas simples con espacios o con una cadena vacía. Este enfoque también puede ser usado para reemplazar los caracteres de comentario como /* */– mediante el uso de más Reemplazar comandos (como ya he demostrado más arriba). Pero tenga en cuenta que este método sólo funciona si usted nunca esperan que estos caracteres en la entrada normal, y esto depende de su aplicación.

    Nota el conjunto de reemplazado caracteres se basa en la https://msdn.microsoft.com/en-us/library/ms161953(SQL.105).aspx

    La inyección de SQL es que no se llama una «oferta Única inyección». Por una razón.
    Yo no estoy familiarizado con ‘comilla simple inyección», la técnica que acabo de describir es un método de protección contra Inyección SQL y se basa en el artículo de Microsoft he hecho referencia anteriormente. Estoy claro por qué usted abajo-votaron a favor de esta respuesta.
    Estoy siempre dispuesto a aprender más acerca de la seguridad, y yo daría la bienvenida a su explicación de por qué Microsoft recomendación en msdn.microsoft.com/en-us/library/ms161953(SQL.105).aspx es «deliberadamente imperfecto».
    Porque si esta recomendación se utilizan en este sitio, por ejemplo, sería incapaz de publicar su respuesta en todos.
    De nuevo estoy tratando de entender aquí – es tu punto de vista de que Microsoft recomendación es patético? A mí me parecía un enfoque que puede ayudar a la pregunta original, teniendo en cuenta todas las restricciones que figuran en la pregunta.

    OriginalEl autor Ubercoder

Dejar respuesta

Please enter your comment!
Please enter your name here