Prevenir Inyección SQL
Prevenir Inyección SQL
Prevenir Inyección SQL
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.