SQL Injection

que es SQL injection, explicamelo detalladamente en que consiste y las modalidades : basada en errores, tiempo, booleanos, uniones y stacked querys

La SQL Injection (inyección SQL) es una técnica de ataque cibernético que explota vulnerabilidades en la forma en que una aplicación interactúa con su base de datos. Los atacantes insertan código SQL malicioso en las consultas que una aplicación web realiza a su base de datos, lo que puede permitirles acceder, modificar o eliminar datos sin autorización1.

Modalidades de SQL Injection

  1. SQL Injection Basada en Errores:
    • Descripción: Consiste en insertar código SQL que provoque un error en la base de datos. Los mensajes de error pueden revelar información sobre la estructura de la base de datos.
    • Ejemplo: '; DROP TABLE users; --
  2. SQL Injection Basada en Tiempo:
    • Descripción: Utiliza funciones de tiempo para determinar si una consulta es verdadera o falsa. Esto puede ser usado para extraer datos de la base de datos.
    • Ejemplo: '; IF (1=1) { WAITFOR DELAY '0:0:5' --
  3. SQL Injection Basada en Booleanos:
    • Descripción: Inserta condiciones booleanas en las consultas SQL para filtrar datos. Si la condición es verdadera, la consulta devuelve resultados; si es falsa, no devuelve nada2.
    • Ejemplo: '; AND 1=1 UNION SELECT username, password FROM users --
  4. SQL Injection Basada en Uniones:
    • Descripción: Utiliza la cláusula UNION para combinar los resultados de múltiples consultas SQL. Esto puede ser usado para extraer datos de diferentes tablas.
    • Ejemplo: '; UNION SELECT username, password FROM users --
  5. SQL Injection Basada en Consultas Empilhadas:
    • Descripción: Inserta múltiples consultas SQL en una sola línea, separadas por punto y coma. Esto puede ser usado para ejecutar múltiples comandos en una sola solicitud.
    • Ejemplo: '; DROP TABLE users; SELECT * FROM users --

Prevención de SQL Injection

Para prevenir ataques de SQL Injection, es importante seguir buenas prácticas de seguridad, como:

  • Uso de declaraciones preparadas (Prepared Statements): Evita la concatenación directa de entradas del usuario en las consultas SQL.
  • Validación y saneamiento de entradas: Asegúrate de que todas las entradas del usuario sean validadas y saneadas antes de ser utilizadas en consultas SQL.
  • Principio de menor privilegio: Limita los permisos de la base de datos para que las aplicaciones solo tengan acceso a los datos necesarios.

Laboratorio de prueba para SQL Injection

Vamos a crear un laboratorio de prueba para practicar los ataques de SQL Injection:

Instalamos las herramientas que vamos a utilizar:

apt install mariadb-server apache2 php-mysql

Comprobamos que están corriendo los servicios mariadb y apache2

systemctl status apache2

~# systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
     Active: active (running) since Mon 2024-12-09 10:22:41 UTC; 21min ago
 Invocation: fcdbf07c016a4e8f9b6a7eba53ebc183
       Docs: https://httpd.apache.org/docs/2.4/
   Main PID: 101574 (apache2)
      Tasks: 55 (limit: 1110)
     Memory: 7.3M (peak: 7.5M)
        CPU: 187ms
     CGroup: /system.slice/apache2.service
             ├─101574 /usr/sbin/apache2 -k start
             ├─101576 /usr/sbin/apache2 -k start
             └─101577 /usr/sbin/apache2 -k start

~# systemctl status mariadb
● mariadb.service - MariaDB 11.4.3 database server
     Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; preset: enabled)
     Active: active (running) since Mon 2024-12-09 10:22:36 UTC; 22min ago
 Invocation: 0e663c8377c74f15becc832ea34b1594
       Docs: man:mariadbd(8)
             https://mariadb.com/kb/en/library/systemd/
   Main PID: 101138 (mariadbd)
     Status: "Taking your SQL requests now..."
      Tasks: 9 (limit: 7327)
     Memory: 89.4M (peak: 93.6M)
        CPU: 2.101s
     CGroup: /system.slice/mariadb.service
             └─101138 /usr/sbin/mariadbd

Vamos a crear la base de datos con su tabla y columnas que nos servirá para hacer las consultas mysql

La primera vez al conectar con mysql -u root -p, podemos darle a enter sin escribir nada.

~# mysql -uroot -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 31
Server version: 11.4.3-MariaDB-1 Ubuntu 24.10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 

Los componentes principales de mysql son las bases de datos , tablas y columnas. Cada base de datos tiene tablas y cada tabla tiene columnas. Así que las consultas básicas para visualizar esto son: show databases; use database; show tablas; describe tabla; select * from tabla; select campo, campo from tabla.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.001 sec)

MariaDB [(none)]> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mysql]> show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| column_stats              |
| columns_priv              |
| db                        |
| event                     |
| func                      |
| general_log               |
| global_priv               |
| gtid_slave_pos            |
| help_category             |
| help_keyword              |
| help_relation             |
| help_topic                |
| index_stats               |
| innodb_index_stats        |
| innodb_table_stats        |
| plugin                    |
| proc                      |
| procs_priv                |
| proxies_priv              |
| roles_mapping             |
| servers                   |
| slow_log                  |
| table_stats               |
| tables_priv               |
| time_zone                 |
| time_zone_leap_second     |
| time_zone_name            |
| time_zone_transition      |
| time_zone_transition_type |
| transaction_registry      |
| user                      |
+---------------------------+
31 rows in set (0.001 sec)

MariaDB [mysql]> describe user;
+------------------------+---------------------+------+-----+----------+-------+
| Field                  | Type                | Null | Key | Default  | Extra |
+------------------------+---------------------+------+-----+----------+-------+
| Host                   | char(255)           | NO   |     |          |       |
| User                   | char(128)           | NO   |     |          |       |
| Password               | longtext            | YES  |     | NULL     |       |
| Select_priv            | varchar(1)          | YES  |     | NULL     |       |
| Insert_priv            | varchar(1)          | YES  |     | NULL     |       |
| Update_priv            | varchar(1)          | YES  |     | NULL     |       |
| Delete_priv            | varchar(1)          | YES  |     | NULL     |       |
| Create_priv            | varchar(1)          | YES  |     | NULL     |       |
| Drop_priv              | varchar(1)          | YES  |     | NULL     |       |
| Reload_priv            | varchar(1)          | YES  |     | NULL     |       |
| Shutdown_priv          | varchar(1)          | YES  |     | NULL     |       |
| Process_priv           | varchar(1)          | YES  |     | NULL     |       |
| File_priv              | varchar(1)          | YES  |     | NULL     |       |
| Grant_priv             | varchar(1)          | YES  |     | NULL     |       |
| References_priv        | varchar(1)          | YES  |     | NULL     |       |
| Index_priv             | varchar(1)          | YES  |     | NULL     |       |
| Alter_priv             | varchar(1)          | YES  |     | NULL     |       |
| Show_db_priv           | varchar(1)          | YES  |     | NULL     |       |
| Super_priv             | varchar(1)          | YES  |     | NULL     |       |
| Create_tmp_table_priv  | varchar(1)          | YES  |     | NULL     |       |
| Lock_tables_priv       | varchar(1)          | YES  |     | NULL     |       |
| Execute_priv           | varchar(1)          | YES  |     | NULL     |       |
| Repl_slave_priv        | varchar(1)          | YES  |     | NULL     |       |
| Repl_client_priv       | varchar(1)          | YES  |     | NULL     |       |
| Create_view_priv       | varchar(1)          | YES  |     | NULL     |       |
| Show_view_priv         | varchar(1)          | YES  |     | NULL     |       |
| Create_routine_priv    | varchar(1)          | YES  |     | NULL     |       |
| Alter_routine_priv     | varchar(1)          | YES  |     | NULL     |       |
| Create_user_priv       | varchar(1)          | YES  |     | NULL     |       |
| Event_priv             | varchar(1)          | YES  |     | NULL     |       |
| Trigger_priv           | varchar(1)          | YES  |     | NULL     |       |
| Create_tablespace_priv | varchar(1)          | YES  |     | NULL     |       |
| Delete_history_priv    | varchar(1)          | YES  |     | NULL     |       |
| ssl_type               | varchar(9)          | YES  |     | NULL     |       |
| ssl_cipher             | longtext            | NO   |     |          |       |
| x509_issuer            | longtext            | NO   |     |          |       |
| x509_subject           | longtext            | NO   |     |          |       |
| max_questions          | bigint(20) unsigned | NO   |     | 0        |       |
| max_updates            | bigint(20) unsigned | NO   |     | 0        |       |
| max_connections        | bigint(20) unsigned | NO   |     | 0        |       |
| max_user_connections   | bigint(21)          | NO   |     | 0        |       |
| plugin                 | longtext            | NO   |     |          |       |
| authentication_string  | longtext            | NO   |     |          |       |
| password_expired       | varchar(1)          | NO   |     |          |       |
| is_role                | varchar(1)          | YES  |     | NULL     |       |
| default_role           | longtext            | NO   |     |          |       |
| max_statement_time     | decimal(12,6)       | NO   |     | 0.000000 |       |
+------------------------+---------------------+------+-----+----------+-------+
47 rows in set (0.002 sec)

MariaDB [mysql]> select User, Password from user;
+-------------+----------+
| User        | Password |
+-------------+----------+
| mariadb.sys |          |
| root        | invalid  |
| mysql       | invalid  |
+-------------+----------+
3 rows in set (0.002 sec)

Vamos a crear nuestra propia base de datos con los campos usuario , password, … para que desde un script en php establezcamos una conexión con dicha base de datos, y podamos realizar SQL Injection

MariaDB [mysql]> create database SQLInjection;
Query OK, 1 row affected (0.001 sec)

MariaDB [mysql]> show databases;
+--------------------+
| Database           |
+--------------------+
| SQLInjection       |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.001 sec)

MariaDB [mysql]> use SQ
SQL                  SQL_NO_CACHE         SQL_TSI_MINUTE       SQL_TSI_YEAR        
SQL_BIG_RESULT       SQL_SMALL_RESULT     SQL_TSI_MONTH        SQLEXCEPTION        
SQL_BUFFER_RESULT    SQL_THREAD           SQL_TSI_QUARTER      SQLSTATE            
SQL_CACHE            SQL_TSI_DAY          SQL_TSI_SECOND       SQLWARNING          
SQL_CALC_FOUND_ROWS  SQL_TSI_HOUR         SQL_TSI_WEEK         SQRT                
MariaDB [mysql]> use SQLInjection;
Database changed
MariaDB [SQLInjection]> show tables;
Empty set (0.001 sec)

MariaDB [SQLInjection]> create table users(id int(32), username varchar(32), password varchar(32));
Query OK, 0 rows affected (0.042 sec)

MariaDB [SQLInjection]> show tables;
+------------------------+
| Tables_in_SQLInjection |
+------------------------+
| users                  |
+------------------------+
1 row in set (0.001 sec)

MariaDB [SQLInjection]> describe users;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(32)     | YES  |     | NULL    |       |
| username | varchar(32) | YES  |     | NULL    |       |
| password | varchar(32) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.001 sec)

MariaDB [SQLInjection]> # Vamos a introducir datos
MariaDB [SQLInjection]> insert into users(id, username, password) values(1, 'admin', 'admin123');
Query OK, 1 row affected (0.002 sec)

MariaDB [SQLInjection]> insert into users(id, username, password) values(2, 'david', 'david1234');
Query OK, 1 row affected (0.002 sec)

MariaDB [SQLInjection]> insert into users(id, username, password) values(3, 'Hacker', 'hacker321');
Query OK, 1 row affected (0.003 sec)

MariaDB [SQLInjection]> # Mostrar todos los campos de la tabla o ciertos campos de la tabla
MariaDB [SQLInjection]> select * from users;
+------+----------+-----------+
| id   | username | password  |
+------+----------+-----------+
|    1 | admin    | admin123  |
|    2 | david    | david1234 |
|    3 | Hacker   | hacker321 |
+------+----------+-----------+
3 rows in set (0.001 sec)

MariaDB [SQLInjection]> select username from users;
+----------+
| username |
+----------+
| admin    |
| david    |
| Hacker   |
+----------+
3 rows in set (0.001 sec)

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *