¿Cómo el procedimiento almacenado impide la inyección de SQL?

10

Puede que no tenga muy claro el procedimiento almacenado. Alguien me puede explicar cómo el procedimiento almacenado previene la inyección de SQL con un ejemplo simple usando MySql.

    
pregunta Anandu M Das 01.10.2014 - 08:12
fuente

4 respuestas

12

Los procedimientos almacenados son una forma de consulta parametrizada. El problema fundamental que causa la inyección de SQL es que los datos se tratan como lenguaje de consulta.

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

En este ejemplo, si configuro $password en foo' OR 'x'='x , obtendremos esto:

SELECT * FROM users WHERE username = 'blah' AND password = 'foo' OR 'x'='x'

Dado que el carácter 'x' siempre es igual al carácter 'x', esta consulta siempre devolverá filas independientemente de si el usuario / paso es correcto. La base de datos no puede saber que no fue su intención, porque solo se le asigna una cadena sin contexto.

Para evitar esto, debe poder saber la diferencia entre la consulta y los datos. Los procedimientos almacenados resuelven este problema escribiendo la consulta de antemano, con marcadores para los parámetros, de modo que los datos se puedan pasar a ellos más adelante. Por ejemplo:

SELECT * FROM users WHERE username = ? AND password = ?

El controlador de la base de datos envía el nombre de este procedimiento almacenado (o, en consultas parametrizadas estándar, solo el propio texto de consulta) y una lista de parámetros, como entidades separadas distintas en el protocolo. Esto significa que el servidor de la base de datos puede analizar la cadena de consulta como lenguaje de consulta de forma segura y tratar los parámetros únicamente como datos, sin ninguna ambigüedad.

También escribí un artículo más largo. responda hace un tiempo que explica todo esto de una manera más detallada, si eso te sirve.

    
respondido por el Polynomial 01.10.2014 - 11:03
fuente
4

Los procedimientos almacenados no son inmunes a la inyección de SQL . Como se explica aquí:

enlace

Siempre que se pueda crear SQL dinámico dentro de los procedimientos almacenados, usted es vulnerable a la inyección de SQL.

Y MySQL a partir de 5.0.13 en adelante, tienen capacidad de SQL dinámico:

enlace

Y, por lo tanto, es vulnerable a la inyección de SQL.

En servidor SQL , aquí hay un ejemplo:

enlace

VULNERABLE STORED PROCEDURE USING EXEC STATEMENT.
CREATE PROCEDURE getDescription
   @vname VARCHAR(50)
AS
   EXEC('SELECT description FROM products WHERE name = '''+@vname+ '''')
RETURN

Y otro ejemplo:

VULNERABLE STORED PROCEDURE USING DYNAMIC CURSOR.
CREATE PROCEDURE printDescriptions
   @vname             VARCHAR(100)
AS
   DECLARE @vdesc VARCHAR(1000)
   DECLARE @vsql VARCHAR(4000)
   SET @vsql = 'SELECT description FROM products WHERE name='''+@vname+''''
   DECLARE cur CURSOR FOR EXEC @vsql

   OPEN cur
   FETCH NEXT FROM cur INTO @vdesc

   WHILE @@FETCH_STATUS = 0
   BEGIN
      PRINT @vdesc
      FETCH NEXT FROM cur INTO @vdesc
   END

   CLOSE cur
   DEALLOCATE cur
RETURN

Y en Oracle , aquí están los ejemplos:

enlace

enlace

La presentación anterior de David Litchfield en Blackhat Europe tiene algo más serio, de la inyección de SQL que puede llevar a una escalada de privilegios, por lo que un usuario de Oracle normal puede ejecutarse como DBA si los procedimientos almacenados son creados por DBA (por ejemplo, todos los objetos del sistema Oracle).

    
respondido por el Peter Teoh 12.01.2017 - 07:04
fuente
3

Una base de datos SQL trabaja una declaración en varios pasos. Al principio se analiza la prueba de la declaración SQL, después de eso se optimizará y compilará. Cuando esto termine, la base de datos tiene ahora una pieza interna de software que puede ejecutar la declaración SQL dada.

Los procedimientos almacenados están precompilados. En otras palabras, la base de datos crea esa pieza interna de software antes de usarla. En este caso, solo el código de programación se interpreta sin ninguna influencia de los parámetros.

Si pasa un parámetro inclusivo de la sentencia SQL completa a la base de datos, procesará los pasos descritos anteriormente.

Por ejemplo ...

SELECT * FROM myTable WHERE id=1

o le das algo así ...

SELECT * FROM myTable WHERE id=1;DROP TABLE myTable

Normalmente, nadie escribiría una declaración como la segunda en su código de programación, pero si toma por ejemplo parámetros directos de una solicitud web, es posible que una declaración como esa resulte.

var sqlString="SELECT * FROM myTable WHERE id=";
sqlString = sqlString+request.getParameter("id");
// database parse, compile and optimize
var result=database.doQuery(sqlString);

Si utiliza procedimientos almacenados o declaración preparada. El proceso de análisis y compilación ya está hecho en la base de datos. Toda la interpretación depende de su código de programación. Cuando la llama a la base de datos, solo inserte los parámetros dados en el código precompilado y ahora se muestran los tipos de datos aceptados.

var sqlString = "call queryMyTable(?)";
// get the precompiled statement from database
var statement = database.createStatement(sqlString);
// inject the parameter
statement.setParameter(1,request.getParameter("id"));
// if 'id' is a number it works fine ...
// but if 'id' is '1;DROP TABLE myTable' you will got a type cast error and the risk of SQL injection is banned
var result = statement.execute();

Los procedimientos almacenados y las declaraciones preparadas están a la vista de la seguridad igual.

    
respondido por el OkieOth 01.10.2014 - 09:40
fuente
0

Otra forma de pensarlo, de ser explícito y de aumentar las respuestas ya dadas.

SELECT * FROM users WHERE username = 'blah' AND password = 'foo' OR 'x'='x'

Sin la declaración preparada, OR después de que 'foo' se trate como código

Ahora, con la declaración preparada, OR (y todo lo demás) después de que 'foo' se trate como datos

    
respondido por el james6125 27.03.2018 - 19:23
fuente

Lea otras preguntas en las etiquetas

___ inyección de qstnhdr ___ MongoDB Nosql en código python ______ qstntxt ___

Aquí está el fragmento de código para acceder a MongoDB.

%pre%

Me dijeron que este código es vulnerable a la inyección NoSQL ya que la variable de condición no está correctamente desinfectada. Pero no pude entender cómo funciona la inyección con python. ¿Puede alguien darme un ejemplo como qué entrada puede causar los problemas o algunas referencias a un ataque de inyección relacionado? Por cierto, también hice algunas investigaciones por mi cuenta, pero solo encontré la inyección basada en Javascript y traté de no funcionar en este caso. Gracias.

    
______ answer83234 ___

El operador %code% en MongoDB es una característica que es mejor evitar. Su rendimiento es abismal, y no solo porque no se beneficia de los índices. Casi todos los casos de uso comunes se pueden resolver de manera mucho más eficiente con una consulta o agregación de búsqueda común, especialmente una tan trivial como esta. Pero esto es un intercambio de seguridad de pila, no un flujo de pila, así que concentrémonos en las implicaciones de seguridad.

La declaración %code% pasa un fragmento de código javascript a la base de datos que la base de datos ejecutará una vez para cada documento de la colección. Afortunadamente, este script no tiene acceso al objeto %code% ni a otras funciones de shell peligrosas y funciona en copias de los documentos, por lo que el atacante al menos no puede cambiar el contenido de la base de datos como ocurre con muchas inyecciones de SQL. Pero, por ejemplo, es vulnerable a los ataques donde el atacante quiere devolver otros resultados de los previstos.

Vamos a hacer un ejemplo. Digamos que tenemos un blog. Nuestro blog tiene muchos artículos que se pueden leer en público, pero también tenemos algunos artículos privados que son para nuestro uso interno y que no deben publicarse. Así que tenemos un campo %code% en nuestros documentos que puede ser %code% o %code% dependiendo de si nuestros visitantes deben ver el artículo o no. Nuestra consulta de MongoDB para obtener una lista de todos los artículos en una categoría determinada para mostrarla al visitante del sitio web es así:

%pre%

Eso debería asegurarnos de que nadie vea nuestros artículos ocultos. O lo hace? Cuando el usuario controla la variable %code% , puede establecerla en esta cadena:

%pre%

El fragmento de código Javascript resultante que se envía a la base de datos es el siguiente:

%pre%

Cuando tiene un fragmento de código javascript con varios comandos separados por %code% , se ejecutarán como una función y se necesita una declaración %code% para determinar qué valor se devolverá al llamante. Esta función siempre devolverá verdadero. Eso significa que el usuario también verá todos los artículos de nuestra colección, incluidos aquellos que se supone que están ocultos.

    
______ answer83261 ___
  

¿Puede alguien darme un ejemplo como qué entrada puede causar los problemas?

Para su pieza concreta de código, esto debería funcionar:

%pre%

%code% se usa para escapar de la cadena y la instrucción, luego sigue el ataque real %code% (ataque DOS), y luego el %code% aún en pie se transforma en una sintaxis válida a través de %code% .

Hasta la versión 2.4 de MongoDB, el objeto %code% era realmente global, por lo que podría cambiar los datos en la base de datos, e incluso recuperar datos usando inyección ciega .

Como ya no es posible, lo máximo que puede hacer un atacante es DOS y la evasión del filtro descrita por Philipp (lo que no sería un problema para su ejemplo, pero puede ser un problema en general).

Eso todavía es bastante malo, por lo que deberías defenderte escapando %code% , %code% y %code% .

    
___ Guardar mensajes privados cifrados en la base de datos