Pregunta

Me gustaría saber si estoy a salvo de la inyección SQL cuando uso algo así con PostgresSQL:

CREATE or REPLACE FUNCTION sp_list_name( VARCHAR )
RETURNS SETOF v_player AS '
   DECLARE
      v_start_name ALIAS FOR $1;
      r_player  v_player%ROWTYPE;
      v_temp VARCHAR;
   BEGIN
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      LOOP
         RETURN NEXT r_player;
      END LOOP;
      RETURN;
   END;
' LANGUAGE 'plpgsql' VOLATILE;

Quiero usar esta función para enumerar el nombre del jugador que comienza con una letra.

select * from sp_list_name( 'A' );

me da jugadores con apellido que comienza con A.

Traté de inyectar sql con

select * from sp_list_name( 'A; delete from t_player;--' );
select * from sp_list_name( '''; delete from t_player;--' );

¿Estoy seguro?

¿Qué caso me podrían inyectar?

Saludos

¿Fue útil?

Solución

En términos de su procedimiento, parece seguro ya que la variable en el SP no se expandirá en código, pero aún puede exponerse si no utiliza una consulta parametrizada como " SELECT * DESDE sp_list_name (?); " en su código de aplicación . Algo así como " SELECT * FROM sp_list_name ('$ start_name'); " podría ser subvertido por un usuario que pasa un nombre de inicio de " '); eliminar de t_player donde last_name NOT IN (' " ;. Por lo tanto, utilice una consulta parametrizada o verificación de cordura sus entradas en su programa.

NB: Para otros, tenga en cuenta que una variable en un procedimiento almacenado no se expandirá en código incluso si contiene un 'o; EJECUTAR , para lo cual usaría las funciones quote_literal , no replace ) así reemplazando; o 'es totalmente innecesario (en el procedimiento almacenado, la aplicación que lo usa es una historia diferente, por supuesto) y evitaría que siempre encuentre el " tl; dr " o " O'Grady " equipos.

Leo Moore, Karl, LFSR Consulting : v_temp_name en el procedimiento almacenado NOT se expandirá en código en el SP (no EJECUTAR ), la verificación tendría que hacerse en la aplicación, no en el SP (o el OP podría simplemente usar una consulta parametrizada en su código de aplicación). Lo que otros sugieren es similar a preocuparse por

my $bar = "foo; unlink('/etc/password');"; 
my $baz = $bar;

realmente ejecuta el desvinculado en ausencia de una evaluación.

Otros consejos

Regla n. ° 1 para evitar la inyección sql: desinfecte todas las entradas que provienen de alguien / algo en lo que no puede confiar / sobre el que no tiene control.

El problema en sí no se encuentra dentro del código de la base de datos, sino de la aplicación que está ejecutando esas declaraciones.

La forma adecuada de protegerse contra la inyección de SQL es a través de Lista blanca * - breve es establecer los caracteres que va a aceptar y filtrarlos.

La forma incorrecta es Lista negra - La lista negra de los caracteres no aceptados es va a generar problemas, porque no puedes mantenerte al día con los atacantes. Hay formas de evitar las listas negras a través de tablas ASCII, caracteres de escape y demás.

Además, aquí hay una buena hoja de trucos para probar en su sitio. Ejecute algunas pruebas e intente que las cosas fallen.

* En la aplicación, no el DB (Gracias James)

No está generando SQL para usted, por lo que esto parece seguro (para mí).

No sé de dónde provienen los datos que está llamando a su procedimiento almacenado. Así que aún debe protegerse contra desbordamientos del búfer, etc.

Ref. Listado blanco. Esto está bien si se siguen ciertas otras condiciones. Es absolutamente imprescindible desglosar todas las entradas en su forma más simple, así que no solo verifique los nombres de las consultas SQL, las comillas simples, etc. Pueden representarse o codificarse utilizando otros conjuntos de caracteres y es esto lo que forma parte de la lista blanca, no específicamente Palabras clave SQL en sí mismas.

Estaba trabajando para un cliente en particular que permitía el nombre de usuario / contraseña a un recurso protegido (¡lo que en última instancia podría darle un pase de acceso a partes seguras de un aeropuerto!). Puede eludir el campo de inicio de sesión ingresando 'y luego creando consultas SQL desde allí para recuperar cuentas de usuario y contraseñas.

El problema era que el cliente ya había gastado £ 200k construyendo el sitio con un proveedor que parecía que nunca antes había realizado desarrollo web. La solución fue un adicional de £ 60k, que era una función validada () que solo verificaba la unión, selección, palabras clave y otras. Cuando se les preguntó qué hicieron para la codificación / canicolización (que luego tuve que explicar) fue el momento de la planta rodadora.

La casa de desarrollo y el proyecto (caro) quedaron enlatados.

Podría considerar validar el contenido de

 v_start_name 
. Verifique la cadena de puntos y coma, caracteres de comentario, iguales, etc. Recuerde verificar los valores de caracteres y hexadecimales. Recuerde permitir un nombre con guión, p. 'Smith-Brown' es probablemente aceptable 'Smith - Brown' es potencialmente inyección.

Si no está familiarizado con Hex in SQL Injection, las siguientes son introducciones rápidas

http: // www .arejae.com / blog / sql-injection-attack-using-t-sql-and-hexadecimal.html

http://www.securityfocus.com/infocus/1768

DECLARE
      v_start_name ALIAS FOR $1;
      r_player  v_player%ROWTYPE;
      v_temp VARCHAR;
   BEGIN
      --  new pseudo code here
      if v_start_name has bad chars exit with error message
      -- end pseudo code here
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      LOOP
         RETURN NEXT r_player;
      END LOOP;
      RETURN;
   END;

Saludos Karl

Simplemente reemplace su v_start_name para deshacerse de " ;; " etc. es decir

v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');

Esto reemplazará el; con espacios en blanco frustrando un ataque de inyección SQL

Para obtener más detalles, consulte Funciones de cadena en PostgresSQL

Como LFSR Consulting también ha comentado. Es mejor utilizar WhiteList (es decir, no procesar ninguna entrada con caracteres no válidos como ';') en lugar de BlackList (es decir, tratar de limpiar los datos ya que el usuario también podría realizar un ataque de inyección SQL en su Reemplazar).

Para obtener más información, eche un vistazo a Ataques de inyección SQL

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top