Skip to main content

Databases

Part of 01 Web in the Web Application Testing Cheatsheet.

Contents:

Per-database pages: MySQL | PostgreSQL | MSSQL | MongoDB | Redis | SQLite | Oracle


1. Overview​

Databases are the payoff of a web pentest. Every step before them (recon, fingerprinting, injection) is preparation. Once you reach the DB, you get credentials, hashes, file read/write, and often direct RCE.

This file is an introductory index: how to tell which DB you are likely looking at, what it leaks without credentials, and which sibling file to open next. Each database has its own dedicated page; this README is the shared entry point, not a substitute for those pages.

Per-database pages in this folder:

1.1 Why databases matter​

Four reasons, in order of impact:

  1. Credentials - user tables almost always contain password hashes or plaintext passwords. Reused credentials pivot to SSH, RDP, admin panels.
  2. File read/write - most DB engines can read and write local files (LOAD_FILE, pg_read_file, xp_cmdshell, COPY ... TO PROGRAM). Read /etc/passwd, web.config, wp-config.php. Write a webshell.
  3. Command execution - MySQL UDF, MSSQL xp_cmdshell, PostgreSQL COPY ... TO PROGRAM, MongoDB $where with JS. Direct OS command.
  4. Lateral movement - linked MSSQL servers, PostgreSQL dblink, MySQL federated tables. From one DB to another host.

1.2 Default ports​

DBDefault portCommon deviationsProtocol
MySQL / MariaDB33063307, 13306, 33060 (X Protocol)MySQL wire
PostgreSQL54325433, 15432PG wire
MSSQL14331434 (browser), dynamic high portsTDS
Oracle15211522, 1526, 2483TNS
MongoDB2701727018, 27019MongoDB wire
Redis63796380, 16379RESP
Elasticsearch9200 (HTTP), 9300 (transport)9201HTTP/JSON
CouchDB59846984 (TLS)HTTP/JSON
Cassandra9042 (CQL), 7000 (gossip)9142CQL binary
Memcached1121111212text / binary
SQLiten/a (file)-file

1.3 Auth models​

DBDefault authNotes
MySQLpasswordcaching_sha2_password (8.x), mysql_native_password (5.x)
PostgreSQLpassword + pg_hba.conftrust, md5, scram-sha-256, peer
MSSQLpasswordWindows auth (NTLM/Kerberos) or SQL auth
OraclepasswordOS auth, password, external
MongoDBnone (legacy) / SCRAMPre-3.0 no auth by default
Redisnonerequirepass optional; often no auth
Elasticsearchnone (pre-7)X-Pack security optional

2. Detection - which DB is it?​

2.1 Port-based​

# Version detection on every open port
nmap -sV -Pn -p- --min-rate 5000 <TARGET>

# Targeted per-DB NSE scripts
nmap -p 3306 --script mysql-info,mysql-enum <TARGET>
nmap -p 5432 --script pgsql-brute <TARGET>
nmap -p 1433 --script ms-sql-info,ms-sql-config,ms-sql-empty-password <TARGET>
nmap -p 27017 --script mongodb-info,mongodb-databases <TARGET>
nmap -p 6379 --script redis-info <TARGET>
nmap -p 1521 --script oracle-tns-version <TARGET>

Expected output (MySQL example):

3306/tcp open mysql MySQL 8.0.32-0ubuntu0.22.04.2
| mysql-info:
| Protocol: 10
| Version: 8.0.32-0ubuntu0.22.04.2

2.2 Banner grabbing​

# Raw connect - most DBs greet you with a banner
nc -nv <TARGET> 3306 # MySQL
nc -nv <TARGET> 5432 # PostgreSQL (needs startup packet)
nc -nv <TARGET> 6379 # Redis (type PING)
nc -nv <TARGET> 27017 # MongoDB (binary - use mongosh)

2.3 Error-message fingerprinting (from web app)​

The fastest way: cause a SQL error and read the message.

Error text containsDB
You have an error in your SQL syntaxMySQL
Warning: mysql_MySQL (PHP)
PostgreSQL.*ERROR / pg_queryPostgreSQL
Microsoft OLE DB Provider for SQL ServerMSSQL
Unclosed quotation mark after the character stringMSSQL
ORA-01756 / ORA-00933Oracle
SQLite3::query / SQLite format 3SQLite
MongoError / MongoServerErrorMongoDB
sqlite3.OperationalErrorSQLite (Python)

2.4 Response-header hints (app stack, not the DBMS)​

HTTP response headers identify the application stack (language, framework, web server). They do NOT identify the database. Treat the table below as a weak prior for which DB is plausible given the stack - never as proof. Confirm with error-message fingerprinting (2.3) or a direct connect.

Header / body markerApp stack hintDB commonly paired (guess only)
X-Powered-By: PHPPHPMySQL / MariaDB (typical LAMP)
X-Powered-By: ExpressNode.js / ExpressMongoDB or PostgreSQL (both common)
Server: Microsoft-IIS + .aspxIIS / ASP.NETMSSQL (common)
X-AspNet-VersionASP.NETMSSQL (common)
Server: gunicorn / WerkzeugPython (Django/Flask)PostgreSQL / MySQL / SQLite (no single default)
Set-Cookie: JSESSIONID + .jspJava / servlet containerOracle / PostgreSQL / MySQL (no single default)

2.5 Default credentials​

DBUsernamePasswordNotes
MySQLroot(empty)Fresh installs often empty
PostgreSQLpostgrespostgresCommon in Docker
MSSQLsa(empty) / sasa disabled on modern
OraclescotttigerClassic demo account
OraclesystemmanagerCommon default
MongoDB--Pre-3.0 no auth at all
Redis--No auth by default
Elasticsearch--No auth pre-7.0

2.6 Decision tree​

Open port?
|
+-- 3306 / 3307 / 33060 ----------> MySQL / MariaDB -> MySQL.md
+-- 5432 / 5433 ------------------> PostgreSQL -> PostgreSQL.md
+-- 1433 / 1434 / dynamic --------> MSSQL -> MSSQL.md
+-- 1521 / 1526 ------------------> Oracle -> Oracle.md
+-- 27017 / 27018 ----------------> MongoDB -> MongoDB.md
+-- 6379 / 6380 ------------------> Redis -> Redis.md
+-- 9200 / 9300 ------------------> Elasticsearch -> (link: 02 Frameworks)
+-- 5984 / 6984 ------------------> CouchDB -> (link: 02 Frameworks)
+-- 9042 -------------------------> Cassandra -> (link: 02 Frameworks)
+-- 11211 ------------------------> Memcached -> (link: 02 Frameworks)
+-- no port, file-based ----------> SQLite -> SQLite.md
|
+-- HTTP app with SQL errors?
|
+-- error mentions MySQL -----> MySQL.md
+-- error mentions PG --------> PostgreSQL.md
+-- error mentions MSSQL -----> MSSQL.md
+-- error mentions ORA -------> Oracle.md

3. Enumeration without credentials​

3.1 What each DB leaks unauthenticated​

DBUnauthenticated leak
MySQLVersion + auth plugin via handshake
PostgreSQLVersion via error / startup message
MSSQLVersion via TDS pre-login
MongoDBFull DB list + collections (pre-3.0)
RedisFull keyspace (KEYS *, INFO, CONFIG GET)
ElasticsearchFull index list + docs (/_cat/indices)
MemcachedFull keyspace (stats items, get)

3.2 nmap NSE scripts​

DBScripts
MySQLmysql-info, mysql-enum, mysql-brute, mysql-databases, mysql-users, mysql-variables, mysql-empty-password
PostgreSQLpgsql-brute
MSSQLms-sql-info, ms-sql-config, ms-sql-empty-password, ms-sql-brute, ms-sql-dump-hashes, ms-sql-xp-cmdshell
Oracleoracle-tns-version, oracle-brute, oracle-sid-brute, oracle-enum-users
MongoDBmongodb-info, mongodb-databases, mongodb-brute
Redisredis-info, redis-brute

3.3 Metasploit auxiliary scanners​

DBModule
MySQLauxiliary/scanner/mysql/mysql_login, mysql_hashdump, mysql_enum
PostgreSQLauxiliary/scanner/postgres/postgres_login, postgres_hashdump, postgres_sql
MSSQLauxiliary/scanner/mssql/mssql_login, mssql_hashdump, mssql_enum
MongoDBauxiliary/scanner/mongodb/mongodb_login
Redisauxiliary/scanner/redis/redis_login

3.4 Common unauth bugs​

  • Redis without requirepass - full keyspace, CONFIG SET dir + CONFIG SET dbfilename -> write SSH key or webshell.
  • MongoDB pre-3.0 - no auth by default. show dbs returns everything.
  • Elasticsearch pre-7.0 - no auth by default. /_cat/indices returns everything.
  • Memcached - no auth by design. stats items + get returns all cached data.
  • CouchDB - admin party mode (pre-1.0): anyone is admin.

4. Common misconfigurations​

MisconfigImpactDetection
Exposed to internetDirect attack surfacePort scan from outside
Weak / default credsFull DB accesshydra, nmap --script *-brute
Anonymous / trust authNo creds neededpg_hba.conf trust, MySQL empty password
No TLSCreds sniffable on wirenmap --script ssl-* returns nothing
Over-privileged service accountPrivilege escalationSHOW GRANTS, \du
FILE privilege (MySQL)Read/write local filesSHOW GRANTS FOR CURRENT_USER()
xp_cmdshell enabled (MSSQL)Direct RCEEXEC sp_configure xp_cmdshell
COPY ... TO PROGRAM (PG)Direct RCEPG >= 9.3, superuser
MongoDB $whereJS executionAny write access