PRIMARY CATEGORY → CHECKLISTS • WEB PENTESTING
Mindmap

Zoom in
Enumeration - Common Web App
e.g. WordPress, Tomcat, Jenkins, Joomla…
Check this out
Enumeration - Custom Web App
- Web Technologies
e.g. Server-Side Programming Language → Whatweb, Wappalyzer
e.g. Robots.txt, Sitemap…
-
Web Crawling to list accesible web pages and HTLM juicy comments
-
Accesible Web pages functionality while having Burpsuite open
i.e. While traffic passes through Burpsuite
- Source Code Review for each accesible resource
i.e. GET/POST Parameters exposed in the Source Code of each Web Application Page
- Non-hidden HTTP Parameters: Look for any type of injection
We must look for any resource that accepts user input and subsequently send it to the server
e.g.
GET/POST Parameters in a Login/Registration Form → SQLi
GET/POST Parameters in Contact Form | Comments | Support Tickets → XSS
A web page with GET parameters such as File, Page and so on → LFI or RFI
A web page with GET/POST parameters such as url → SSRF
A web application where a logged-in user can update its profile picture by uploading a file → File Upload
-
Custom HTTP Response Headers and Cookies
-
Fuzz for Resources: Directories and Files
Based on the Server-Side Programming Language used i.e. <URL>/<RESOURCE>.php
Juicy Extensions →
txt,xml,zip,bk,bak,gzand so on
Try appending a
/to the end as well ( e.g.ffuf ... -u '<URL>/FUZZ/')
-
Valid domain→ Fuzz for Virtual Hosts and Subdomains
-
Fuzz for HTTP Hidden Parameters
Be careful with 301 status code, always follow redirects, then filter out ( e.g.
ffuf ...<SNIP>... -r)
- After finding a new VHOST, fuzz it again as a new base domain
e.g. domain.tld → web1337.domain.tld → dev.web1337.domain.tld
-
DNS Server available ( i.e. 53 TCP Port open ) → DNS Zone Transfer
-
Login/Register Feature → Valid/Potential Usernames ( e.g. Meet-the-team or About-us page ) → CEWL + Bruteforce
-
Login/Register Feature → Infer existing users based on error messages on a failed login attempt
See User Enumeration
- User enumeration via Side-Channels Attacks
e.g. Response time based on the user entered to determine whether it exists or not
- Valid Usernames → Brute-Force Passwords
Always look for web app’s credential policy to narrow down possible passwords → Check the sign-up page
-
Password-Reset functionality → Check for weak/predictable password-reset tokens, then brute-force them
-
2FA implemented → Try Brute-Force it
-
Authentication required to access existing resources ( e.g. 302 Found to
login.php) → Check for Authentication Bypass via Direct Access -
Always inspect and verify cookies on a web application → Weak/Predictable Cookies or generated based on user data ( e.g. username, role… )
XSS
-
Web Page with a Contact Form → Check for XSS
-
Web Page with a Comment Section → Check for XSS
-
Support Web Page with a Ticket creation Feature → Check for XSS
SQLi
-
Login/Registration Panel → Check for Authentication Bypass via SQLi
-
Any POST or GET Parameter. Any Cookie and User-Agent value as well
LFI
- Any POST or GET parameter ( Check LFI Known Parameters )
e.g.
<URL>?page=<VALUE>or<URL>?language=<VALUE>
- Look for Hidden Parameters through Fuzzing on each Web Application resource
File Upload
-
Look for any File Upload feature within the given web application
-
If the website has a login feature and we are logged in, check for File Upload as well
Command Injection
- Any POST or GET Parameter
HTTP Verb Tampering
- Try the same request with a different HTTP method (e.g. GET ↔ POST, POST ↔ PUT, GET ↔ HEAD )
IDOR
- Look for any direct object reference in the web application to test for its system access control
XXE
-
Search for any HTTP request which sends an XML data structure on its body
-
A File Upload feature that allows SVG images
SSRF
- Look for any HTTP parameter in any existing resource that has a name like
urlor that contains a URL within it
e.g.
<URL>?url=http://example.com?id=1or<URL>?to=http://api.example.com/users/1
SSTI
Usually appears on websites running Flask or Django
- Any POST or GET parameter that its reflected in the response
SSI Injection
-
Any POST or GET parameter
-
File Upload Feature → Upload a file containing SSI directives → Request that uploaded resources so the server can process that directives before serving it
-
User input stored within a file in the web root directory → Request the given resource for SSI directives processing by the web server
XSLT Injection
- Any POST or GET parameter that is reflected in the response
GraphQL
-
HTTP proxy enabled and logging al requests → Search for GraphQL queries or mutations
-
Fuzz for GraphQL endpoints
e.g.
<TARGET>:<PORT>/graphql
REST API
-
HTTP proxy enabled and logging al requests → Search for REST API requests
-
Fuzz for REST API endpoints
e.g.
<TARGET>:<PORT>/api/v1/
Exploitation - Common Web App
Exploitation - Custom Web App
When testing any input data through a certain HTTP Parameter looking for a possible injection/bypass, remember to try all available HTTP verbs ( HTTP Verb Tampering )
e.g.
Abusing Insecure Function Calls through an IDOR and HTTP Verb Tampering
User Reset Password Feature →
POST
Access Denied
Zoom in
GET
“Password changed successfuly”
Zoom in
SQLi
- SQLi Type Identification
Always check first IN-BAND SQLi ( e.g. UNION or Error-based ), then Blind
- DBMS Identification
Data Exfiltration
-
Enumeration: Databases, Tables, Columns, Fields
-
Check if the current DB user has Read/Write permissions: FILE Privilege and
secure_file_privempty or set to an interesting path
If READ permissions → Look for interesting files
Read files
- Web Application Source Code Script ( e.g. PHP Scripts )
So we can look for any existing security flaw by analyzing the code
-
Web Server Configuration Files ( i.e. Apache, Nginx, Tomcat… )
-
Virtual Hosts Configuration Files ( e.g. Web Root Path, .HTPasswd files or another type of sensitive files )
-
Configuration files within the Web Root ( e.g. config.php, db_conn.php… )
-
Service Configuration files that are externally accesible such as FTP, SSH, RSYNC, CIFS, SQUID, SNMP and so on
-
Home Directory Files such as SSH Keys, Shell History Files…
If WRITE Permissions →
Write files
- Web Shell Deployment on Web Root or any directory on which the system user running the DBMS has write permissions
XSS
Try with different payloads
LFI
Bypasses
Try different Bypasses
Important
There are situations where the webapp does not return the expected output from the browser
Zoom in
Therefore, we could try to carry out the same actions using
curlcurl --silent --location --request GET '<URL>?p=....//....//....//....//....//....//....//....//etc/passwd'
Zoom in
Try all of them
Simple and Double
To find the Approved Path → Examine requests sent by existing forms or fuzz for existing web directories under the same path until we get a match ( e.g.
<URL>?lang=./<DIR>/../../../etc/passwd)
Once we are able to exploit the LFI to point to other web files →
Sensitive Data Exposure
We may deal with a VHOST whose config. file has a randon name, so we cannot list its content to disclose the webroot path → Disclose the latter through fuzzing
It also applies to Log Files
Source code Disclosure
Check LFI PHP Filters if
include()orrequire()is used
- Look for any security flaw or information present in the rest of the web application scripts
e.g. Check a File Upload Validation Filters to try to bypass them or the context of an SQL Query looking for an SQLi
RCE
data:// | input:// | expect://)
Non-standard location → Server Logs Fuzzing
File Upload
- If the Web Application runs X (e.g. PHP), try uploading an X script (e.g. test.php)
If the given upload is not allowed, security filters may have been set up. If so →
Bypasses
If none of the previous bypasses work →
Alternative Methods
-
Fuzz for allowed extensions (e.g. SVG)
-
Check Limited File Uploads
-
LFI ↔ File Upload Chain → Fuzz for allowed Extensions → Add a Code Snippet (e.g. mini WebShell) within the file ( e.g. Image Metadata ) before uploading it
Check this out
If the File Upload Feature allows SVG →
-
SVG’s rendered content is displayed on the Web Application → External Entity Definition within the SVG ( XXE ) → Source Code Disclosure of any existing script within the webapp
-
SVG not rendered → OOB Data Exfiltration over HTTP via Blind XXE
Once either of them are exploited →
-
Expect://PHP extension enabled → RCE -
SSRF → Internal Port Discovery | SSRF > Internal Network Enumeration
-
If data cannot be extracted using
file://orphp://filtervia XXE, check File Disclosure through SSRF -
Internal Virtual Host discovery by checking web server configuration files
Once a malicious file is uploaded, we must know the path where it is stored in order to request it, and thereby gain RCE
Disclosing the Uploads Directory Path
- Image path referenced in the source code
e.g.
<img src=http://<TARGET>/uploads/<IMAGE>
-
Upload Feature’s Source Code Disclosure through other security flaws
e.g. LFI, XXE ( e.g. SVG Upload with an External Entity ) or SQLi ( Read Files )
Command Injection
- Try a basic command injection to see if there is any input validation or sanitizacion in place
if not, reverse shell and pwned. If so →
- Try to bypass them with different filter evasions and command obfuscation
HTTP Verb Tampering
-
Send an OPTIONS HTTP request to know the supported HTTP methods by the web server
-
In case of any error or unauthorized operation, simply try changing the HTTP request method to look for differences in the HTTP response
IDOR
This attack vector results from a bad access control system or its absence and a direct object reference
Simple Direct Object Reference (e.g. <URL>?id=1 )
- Just try changing its value to something else to test the access control system
More Secure Direct Object Reference (e.g. <URL>?id=6B29FC40-CA47-1067-B31D-00DD010662DA or <URL>?id=098f6bcd4621d373cade4e832627b4f6 )
- Check if the reference is being created in the frontend ( e.g. JS Function ) before being sent to the server
i.e. Function Disclosure
Once we discover the IDOR →
XXE
Once we have located an HTTP request that sends XML data within its body
Data Disclosure
-
If the web application runs PHP, try XXE using PHP Filter Wrapper
-
If not, try XXE using CDATA
-
If our input is not reflected anywhere in the HTTP response, check if the web application handles error properly
-
If not, try Error based XXE
-
If we are dealing with a Blind XXE, see Blind OOB XXE
RCE
- Bear in mind that we can achieve RCE as well
SSRF
Once we have located a POST/GET parameter that sends an HTTP request to another location
- Confirm SSRF by sending a request to a TCP listener under control
After confirming that we are dealing with an SSRF:
If the SSRF request is reflected in the main HTTP response →
- Internal IP Range Knowledge → Internal Host Discovery
Just check for open TCP ports as we cannot send ICMP packets over HTTP
- Internal Port Discovery by sending HTTP requests to each port and filtering the response
First, use this wordlist when fuzzing. If there is not hit, then
<( seq 1 65535 )
e.g. Accessing another vhost and get a 403 error → Try to access it via SSRF
-
Gopher Protocol Available → Send a POST request via SSRF parameter to an specific endpoint
-
file://scheme available → File Disclosure
Much more restricted and limited
We cannot extract the content of any existing ile as it won’t be reflected in the response
SSTI
After identifying an GET/POST parameter vulnerable to SSTI →
Template Engine → Jinja2
Python → Flask
Template Engine → Twig
PHP
SSI Injection
Once an SSI Injection is identified →
-
Print Environment Variables to look for any sensitive/juicy data
XSLT Injection
After identifying an XSLT Injection →
GraphQL
Once identified that GraphQL is being used →
- Check for a GraphiQL instance under
<TARGET>:<PORT>/graphqlor others
It eases the enumeration process. If not, simply use InQL Burpsuite extension
-
GraphQL Engine identified → Look for in-depth information about the latter
i.e. Threat Matrix for a specific GraphQL Engine
-
Introspection enabled → Enumerate ⬇️
Types Fields for a specific Type Queries Mutations
- Dump all information → Graph representation using GraphQL-Voyager
To get a better overview
- Look for any web security flaw if not properly validation/sanitization is performed by the GraphQL application
- Login validation via GraphQL and Rate-limit restriction → Password Brute-force if GraphQL Batching is enabled to bypass restrictions
API Attacks
After identifying a REST API →
- Verify if a Swagger endpoint exists
e.g.
/swagger
- Look for deprecated API versions
e.g.
/v0/REST API Version accessible with endpoints not requiring authentication
e.g. Authorization Bypass
e.g. Improper restriction of excessive authentication attempts
e.g. Exposure of sensitive information due to incompatible policies or Improperly controlled modification of dinamically-determined object attributes
e.g. Exposure of sensitive information to an unauthorized actor
- Test for SSRF on a vulnerable endpoint
e.g. File upload feature that references the uploaded file by a path using the
file://scheme
- Test for SQL Injection on a vulnerable endpoint



