Un poco de seguridad, SQL Injection

Un poco de seguridad, SQL Injection

Gracias a los comentarios de los compañeros de Java Mexico, vimos que como mostre anteriormente no es la forma mas segura, por no decir la menos indicada, en realizar conexiones a una base de datos y mucho menos en un ambiente web que como dice ezamudio es de naturaleza multiusuario y por tanto la concurrencia es algo vital.

Hoy les traigo un pequeño ejemplo de como podemos usando injeccion SQL obtener acceso a los datos de un servidor, borrar datos, modificar, etc. En este caso solo mostraremos como loguearnos sin siquiera tener una contraseña.

Imagenes

Codigo

Clase Principal

package clases;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.*;

public class Principal extends JFrame{
 
 JTextField txt=new JTextField("admin",12);
 JPasswordField clave=new JPasswordField(12);
 JButton b;
 JLabel linfo;
 JPanel plogin=new JPanel();
 JPanel pabajo=new JPanel();
 
 public Principal(){
  setLayout(new BorderLayout());
  linfo=new JLabel("");
  b=new JButton("Aceptar");
  b.addActionListener(new ActionListener() {
   
   @Override
   public void actionPerformed(ActionEvent arg0) {
    Conexion c=new Conexion();
    Connection conn=c.getConexion();
    try {
     Statement st=conn.createStatement();
     ResultSet rs=st.executeQuery("select * from usuario where clave='"+new String(clave.getPassword())+"'");
     if(rs.next()){
      linfo.setText("Logueado como Administrador");
     }else{
      linfo.setText("Clave Incorrecta");
     }
     rs.close();
     st.close();
     c.cerrarConexion();
     pabajo.updateUI();
     repaint();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   
   }
  });
  plogin.add(new JLabel("Usuario:"));
  plogin.add(txt);
  plogin.add(new JLabel("Clave:"));
  plogin.add(clave);
  plogin.add(b);
  pabajo.add(linfo);
  add(plogin);
  add(pabajo,BorderLayout.SOUTH);
 
 }
 
 public static void main(String arg[]){
  Principal p=new Principal();
  p.setVisible(true);
  p.setBounds(0, 0, 400, 180);
  p.setLocationRelativeTo(null);
  p.setDefaultCloseOperation(EXIT_ON_CLOSE);
 }
}

Clase Conexion

package clases;

import java.sql.*;

public class Conexion {

 private Connection con = null;

 public Conexion() {
  try {
   Class.forName("com.mysql.jdbc.Driver").newInstance();
   con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sqlinjection", "root","**");
  } catch (InstantiationException | IllegalAccessException
    | ClassNotFoundException | SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 public Connection getConexion(){
  return con;
 }
 
 public void cerrarConexion(){
  try {
   con.close();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Explicacion

La contraseña en la Base de Datos es "a1/S#$d$" y como sabrán la consulta que se hizo para la conexión a la Base de Datos tiene la siguiente estructura:

" select * from usuario where clave=' "+new String(clave.getPassword())+" ' "

conociendo esa estructura podríamos jugar con ella, engañando al sistema, si sabemos que para verificar la clave recibe un texto cualquiera entre comillas simples de esta forma clave='123', podríamos entonces saber que al cerrar las comillas y agregarle un operador OR como lo es en MySql las dos barras ( || ), podríamos agregar una expresión verdadera y sumada con una contraseña errada nos daría acceso de igual forma ya que para que sea verdad se necesitaría una de las dos y como le vamos a agregar una expresión verdadera ya contaríamos con al menos 1 expresión verdadera. Nos quedaría de la siguiente forma:

clave='123' || '1'='1'

Si lo que escribimos en la casilla de la contraseña es 123' || '1'='1' completando de esta forma la consulta anterior nos quedaría así:

select * from usuario where clave='123' || '1'='1';

Lo que esta en negrita es lo que añadimos, podremos entonces entrar al sistema.

Pueden descargar el proyecto con los archivos fuentes, las imágenes y el JAR directamente desde aquí.