Prevenir Inyección SQL

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 4

Prevenir Inyección SQL

Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la


programación segura en Java al prevenir los ataques de tipo inyección SQL. Éste tipo de
vulnerabilidad es común en aplicaciones que utilicen bases de datos relacionales que no
realizan validación de entradas.
Necesidad
Prevenir SQL Injection utilizando PreparedStatement en Java
Contexto
A continuación se describen las circunstancias bajo las cuales la siguiente solución tiene
sentido:

1. Se cuenta con una aplicación programada en Java.


2. La aplicación utiliza una base de datos relacional.
3. Se conoce como usar la clase PreparedStatement.
4. Se busca proteger la aplicación, no determinar si ésta es vulnerable.
Solución
1. Para evitar un ataque SQLi se debe tener en cuenta la siguiente estrategia:

 Todas las consultas deben ser parametrizadas.


 Todo dato dinámico debe ser vinculado explícitamente a las consultas
parametrizadas.
 La concatenación de cadenas (variables alfanuméricas) nunca debe usarse para
generar SQLdinámico.
2. Cuando deba generar SQL dinámico valide todas las entradas que conformarán las
partes de la sentencia SQL de manera que no se puedan inyectar subconsultas o
modificaciones a la consulta original.
3. Consulte la posibilidad de incluir librerías de protección de ataques tales
como HDIV [2].
4. Cuando esté asignando los privilegios que el usuario de conexión de la aplicación
tendría sobre el esquema de su base de datos, recuerde no asignarle privilegios
que le permitan hacer modificaciones sobre el esquema. Adicionalmente, los
privilegios deberían ser finamente seleccionados de manera que sólo acceda a los
objetos que debe acceder. Recuerde el principio del menor privilegio.
5. El método adecuado para prevenir ataques de inyección SQL en Java es usar
comandos preparados o procedimientos almacenados parametrizados en lugar de
incluir directamente la entrada del usuario en una instrucción SQL. Las
declaraciones preparadas automáticamente se escapan de metacaracteres como
son la comilla simple y los caracteres punto y coma.
6. El siguiente segmento de código muestra como usar la
clase java.sql.PreparedStatement en lugar de java.sql.Statement.

preparedstatement.java
1 String selectStatement = "SELECT * FROM User WHERE userId =? ";
2 PreparedStatement prepStmt = con.prepareStatement(selectStatement);
3 prepStmt.setString(1, userId);
4 ResultSet rs = prepStmt.executeQuery();
7. Nótese que la solución es independiente del gestor de bases de datos utilizado.
8. A continuación se presenta una aplicación web de ejemplo protegida ante SQL
Injection. Primero se creará la base de datos ejemplo, con una única tabla llamada
datos con la siguiente información.
5 mysql> select * from datos;
6 +------+-----------+
7 | cod | nombre |
8 +------+-----------+
9 | 1 | Bogota |
10 | 2 | Medellin |
11 | 3 | Manizales |
12 | 4 | Cartagena |
13 +------+-----------+
9. Para esto, primero creamos la base de datos ejemplo.
14 % echo "create database ejemplo;" | mysql -u root -p
10. Luego ejecutamos las siguientes instrucciones, de tal forma que se cree la tabla con los
datos requeridos.
15 /*Table structure for table `datos`
16
17 DROP TABLE IF EXISTS `datos`;
18 /*!40101 SET @saved_cs_client = @@character_set_client */;
19 /*!40101 SET character_set_client = utf8 */;
20 CREATE TABLE `datos` (
21 `cod` varchar(100) DEFAULT NULL,
22 `nombre` varchar(100) DEFAULT NULL
23 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
24 /*!40101 SET character_set_client = @saved_cs_client */;
25
26 /*insert on `datos`
27
28 LOCK TABLES `datos` WRITE;
29 /*!40000 ALTER TABLE `datos` DISABLE KEYS */;
30 INSERT INTO `datos` VALUES
31 ('1','Bogota'),('2','Medellin'),('3','Manizales'),('4','Cartagena');
32 /*!40000 ALTER TABLE `datos` ENABLE KEYS */;
33 UNLOCK TABLES;
11. Para esto, lo más sencillo es crear, por ejemplo, un archivo llamado db.sql donde se copia
ese contenido y posteriormente se ejecuta.
34 % mysql -u root -p ejemplo < db.sql
12. Una vez se tiene la base de datos construida, se crea una estructura de directorios y
archivos como la siguiente:
35 % ls -R
36 .:
37 index.jsp WEB-INF/ +
38 ./WEB-INF: +
39 lib/ web.xml +
40 ./WEB-INF/lib: +
41 mysql-connector-java-5.0.8-bin.jar
13. El archivo web.xml es un descriptor típico de despligue que incluso puede ser ignorado
para contenedores de servlets con soporte de la especificación igual o superior a 3.0. En
nuestro caso se utilizará.
42 <?xml version="1.0" encoding="ISO-8859-1"?>
43 <!DOCTYPE web-app
44 PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
45 "http://java.sun.com/dtd/web-app_2_3.dtd">
46 <web-app>
47 </web-app>
14. El jar que contiene el driver de conexión a MySQL puede descargarse desde el sitio oficial.
Este debe ser accesible por el servidor de aplicaciones. Una forma sencilla de conseguirlo
es incluir el jar en la carpeta WEB-INF/lib del proyecto.
15. El archivo index.jsp se muestra a continuación. Primero se realiza el import de las clases en
el paquete java.sql, tales como PreparedStatement y ResultSet entre otras.
48 <html>
49 <head>
50 <title>Prueba</title>
51 </head>
52 <body>
53 <%@ page import="java.sql.*;" %>
16. Se establece la conexión usando como usuario root, contraseña Prog=seg y la base de
datos ejemplo.
54 <%
55 Connection conexion=null;
56 PreparedStatement prepStmt=null;
57 try {
58 Class.forName("com.mysql.jdbc.Driver").newInstance();
59 conexion = DriverManager.getConnection(
60 "jdbc:mysql://localhost:3306/ejemplo?user=root&password=Prog=seg");
17. Se crea la consulta especificando que el parámetro será el valor que se comparará con el
campo cod.
61 String selectStatement = "SELECT cod , nombre FROM datos W
18. Se obtiene por método GET el id de la ciudad que se desea visualizar, y se utiliza para
parametrizar la consulta.
62 String id = request.getParameter("id");
63 prepStmt = conexion.prepareStatement(selectStatement);
64 prepStmt.setString(1, id);
19. Se ejecuta la consulta y se muestra los valores obtenidos.
65 ResultSet tabla = prepStmt.executeQuery();
66 out.println("Codigo\tNombre");
67 while(tabla.next()) {
68 out.print("<br />");
69 out.println(tabla.getInt(1)+"\t"+tabla.getString(2));
70 }
71 out.print("<br /><br />");
72 }
73 catch(ClassNotFoundException e){
74 out.println("Clase no encontrada");
75 }
76 catch(SQLException e){
77 out.println("Excepcion SQL");
78 }
79 catch(Exception e){
80 out.println("Excepcion no esperada");
81 }
82 finally{
83 if (conexion!=null){
84 conexion.close();
85 }
86 if (prepStmt!=null){
87 prepStmt.close();
88 }
89 }
90 %>
91 </body>
92 </html>
20. Para utilizar la aplicación, basta con pasar por método GET el código de la ciudad que se
desea visualizar.
93 http://localhost:8080/sqli/index.jsp?id=2
21. Pueden intentarse ataques tales como 1 or 1=1 para comprobar que la aplicación no
presenta fallas de inyección.

También podría gustarte

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy