Fluid Attacks logo
Contact Us
Young hacker smiling
Zero false positives

Expert intelligence + effective automation

Contact logo Contact Us
GET A DEMO

Evitar Inyección SQL

Necesidad

Se requiere contar con lineamientos que prevengan la inyección de código SQL en bloques de código PL/SQL.

Contexto

A continuación se describe las circunstancias bajo las cuales la siguiente solución tiene sentido:

  1. Se cuenta con una aplicación usando bloques de código PL/SQL, ya sea desde forms, reports, packages, funciones, procedimientos.

  2. Debe validarse la entrada de información antes de ser usada.

Solución

Al momento de desarrollar aplicaciones que utilicen bases de datos relacionales es muy importante protegerlas contra ataques de inyección de código SQL. A continuación presentamos las consideraciones para evitar este tipo de ataques:

  1. Validar variables de entrada. Dentro de estas variables debemos considerar:

    • Variables tipo varchar.

    • Variables tipo datetime.

    • Variables tipo numeric.

    • Variables tipo objeto.

  2. Reemplace las ocurrencias de comillas simples por comillas dobles.

  3. Se recomienda el uso de los paquetes: DBMS_Assert.Simple_Sql_Name(), DBMS_Assert.Enquote_Literal() y la función !ToChar.

  4. Exponer los datos de la base de datos sólo a través de un API desarrollado en PL/SQL, libreria de aplicación. Recordar el usuario de estas librerías no debería poder acceder a efectuar sentencias SQL sobre los datos.

  5. Cuestionar un diseño donde el SQL siempre sea dinámico.

  6. Preferir el uso de SQL estático, sólo usar SQL dinámico como ultima opción.

  7. No confundir contenido dinámico con SQL dinámico, o no sacrificar seguridad por la necesidad de repetir procedimientos con valores constantes asignados.

  8. Preferir SQL generado con placeholders o posiciones asignadas de sustitución en vez de concatenación, tal y como se muestra en el siguiente ejemplo:

    avoid-sql
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    /* Binding : placeholders */
    EXECUTE IMMEDIATE
      'UPDATE employee SET salary = :val
        WHERE hire_date BETWEEN :lodate AND :hidate'
      USING v_start, v_end;
    
    /* Concatenation */
    EXECUTE IMMEDIATE
      'UPDATE employee SET salary = ' || val_in ||
      ' WHERE hire_date BETWEEN ' ||
        ' TO_DATE (''' || TO_CHAR (v_start)  || ''')' ||
        ' AND ' ||
        ' TO_DATE (''' || TO_CHAR (v_end)  || ''')';
    
  9. Cuando una sentencia SQL deba ser ejecutada por alguno de los objetos para generación dinámica de SQL de PL/SQL, esta sentencia debe contener "texto de sentencia" seguro, esto es contenido de texto estático mas texto dinámico seguro.

  10. El texto estático esta compuesto sólo por expresiones varchar2 estáticas.

  11. El texto dinámico es cualquier texto que no sea estático.

  12. El texto dinámico seguro esta conformado por la salida de uno de estos tres procedimientos de Oracle: DBMS_Assert.Simple_Sql_Name(), DBMS_Assert.Enquote_Literal() o To_Char(x f, n).

  13. Siempre valide antes de ejecutar. Un ejemplo de código bien construido se muestra a continuación. Sin embargo falta la clausula authid:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function f(b in boolean, VC2 in varchar2) return number is
      Quote         constant varchar2(1) := '''';
      Doubled_Quote constant varchar2(2) := Quote||Quote;
      Start_  constant varchar2(32767) := 'select PK from ';
      Tab_1   constant varchar2(32767) := 'Tab_1';
      Tab_2   constant varchar2(32767) := 'Tab_2';
      Where_  constant varchar2(32767) := ' where VC2 = ';
      Tab constant varchar2(32767) :=
        case b
          when true then Tab_1
        else           Tab_2
      end;
      SQL_Text_Literal constant varchar2(32767) :=
      Quote||Replace(VC2, Quote, Doubled_Quote)||Quote;
      Stmt constant varchar2(32767) :=
        Start_||
        Tab||
        Where_||
        Sys.DBMS_Assert.Enquote_Literal(SQL_Text_Literal);
      PK number;
    begin
      execute immediate Stmt into PK;
      return PK;
    end f;
    

Service status - Terms of Use