Finding the vulnerability
During routine exploration of vulnerable servers, I discovered the presence of CVE-2017-9841 on a target domain using Nuclei with the http/cves/2017/CVE-2017-9841.yaml template. The scanner flagged an exposed PHPUnit utility script under the /vendor tree.

What CVE-2017-9841 is
Util/PHP/eval-stdin.php in PHPUnit (before 4.8.28 and 5.x before 5.6.3) allows remote attackers to execute arbitrary PHP code sent in an HTTP POST body beginning with <?php . This is usually exposed when an application leaves its vendor folder web-accessible, so the eval-stdin.php file can be requested directly. Knowing this enabled me to submit PHP payloads via the POST body to the vulnerable endpoint.

Attempts at full Remote Code Execution
I attempted several approaches to obtain a shell (using system, exec, passthru, etc.), but each attempt yielded the same error: Call to undefined function.

Inspecting phpinfo() revealed a long list of disabled functions via disable_functions β including many common command-execution functions and other potentially dangerous calls. That constrained direct command execution from PHP.

I also attempted to identify the running user with get_current_user() and explored options such as adding SSH keys to an account, but SSH was not available on the host and many web-server users are configured with shells like /sbin/nologin, so those avenues were not feasible.

Editing cronjobs to gain code execution was also not possible in this environment.
Using PHP payloads for nondestructive access
The shell wasnβt there β the attack surface was. You donβt always need a shell to reach the prize.
Listing directories and reading files
Because direct command execution was blocked, I focused on file-system access via PHP, which allowed enumeration and content retrieval of files. PHP payloads used:
- Listing Directory
|
|

- Reading Files
|
|

Downloading source code
After locating the web-root, I saved the above PHP scripts as list_dir.php and get_file.php and wrote a small Python tool to recursively download directory contents. The downloader iterated directory listings and fetched files, saving them locally.
|
|
Running that tool produced a local copy of the siteβs source code and configuration files.

Source code analysis & discovery of database credentials
Within the downloaded source code I discovered database connection details (IP address and credentials) stored in configuration files. The database IP was a private class-A address, indicating it lived on an internal network and could not be accessed directly from the internet.

Pivoting to the database via the compromised host
A compromised host is a bridge β sometimes itβs all you need to cross into a private world.
Using the compromised web host as a pivot/proxy, I verified the credentials and connected to the database by running simple PHP database-connection payloads from the web host.
Verification payload used:
|
|
This showed the server could connect to the database.

To execute arbitrary queries and extract data, I used another PHP payload that accepts a query parameter and returns JSON results. That payload:
|
|

I wrapped that into a small Python utility to run queries and save results locally for analysis.
|
|


Looking for other databases on the private network
Because the database lived on a private network, I probed the internal network (from the compromised host) for other database servers. For that I deployed a small port-checking PHP script to test connectivity to hosts/ports internally:
|
|
Using the above, I scanned internal addresses and found multiple hosts with MySQL (port 3306) open. With further checks, two of those were reachable and contained the same dataset (one appeared to be a backup).




Attack Path Visualization

Conclusion
This engagement showed how an exposed vendor file (eval-stdin.php from PHPUnit) combined with permissive file placement and stored credentials can lead to serious data exposure β even without full shell access. Key takeaways:
- Leaving development/test libraries or tooling under a web-accessible
vendortree is dangerous. Files intended for developer use (like PHPUnit utilities) must never be reachable from the web. - Sensitive configuration data (like DB credentials) stored in plain text within the web root greatly increases risk when code disclosure occurs.
- Even when
exec-style functions are disabled, attackers can still abuse application-level file-read and database-access functionality to exfiltrate data. - Internal network services (databases, backups) are at risk when a web server can reach them and credentials are present on that host.
If you are defending a system, treat the above as a demonstration of impact β not as an instruction to perform similar actions. Immediately prioritize containment and remediation if you discover a similar situation in your environment.
Recommended mitigations and hardening (defensive, non-actionable)
Below are defensive measures to reduce the risk of code- and data-exposure like the scenario above. These recommendations are focused on configuration, operational controls, and incident response β not on exploit techniques.
1. Patch and remove unsafe dev/test artifacts
- Remove PHPUnit and other development tooling from production deployments. Tools like PHPUnit should never be in production
vendordirectories that are accessible by the webserver. - Keep dependencies up to date. Apply vendor and library security patches promptly β in this case, the vulnerable
eval-stdin.phpwas fixed in patched PHPUnit releases.
2. Prevent web access to non-public files
- Block
/vendorand other development directories at the webserver level (via webserver config or rewrite rules) so vendor files cannot be served as public assets. - Use
open_basedir/ proper webroot layout so that only intended application assets are accessible from the document root.
3. Secure application configuration & secrets
- Avoid hard-coding credentials in files inside the webroot. Store secrets outside the web root, use environment variables injected securely at runtime, or use a secrets manager (vault, cloud secret store).
- Encrypt or otherwise protect configuration files when feasible and rotate credentials on a regular schedule (and after any suspected compromise).
- Least privilege for DB accounts β ensure database accounts used by the web app have minimal permissions necessary for their operation (no unnecessary admin rights).
4. Network segmentation and access controls
- Segment internal networks so that compromised web hosts cannot freely reach internal database subnets. Use firewalls and host-based rules to restrict which application servers can access which DB servers.
- Restrict management interfaces and internal tools to trusted administrative networks or via jump hosts/VPNs.
5. Hardening the PHP runtime and the host
- Minimize enabled PHP functions carefully, but be aware that relying on
disable_functionsalone is not sufficient to prevent data exfiltration through application logic. - Harden file permissions so that the webserver user cannot read configuration files that are not required for operation.
- Run services with least privilege; avoid running the webserver as overly privileged users.
6. Web application controls
- Input validation and least-privilege application features β do not expose ad-hoc file-read/exec features to the web in production.
- Implement a WAF (Web Application Firewall) to detect and block known attack signatures (including attempts to access unusual PHP files under the vendor tree).
- Disable serving of
.phpfiles from directories that should not contain executable scripts (e.g., storage, uploads).
7. Monitoring, detection, and logging
- Log web requests and server errors centrally and monitor for suspicious access patterns (e.g., requests to
vendor/phpunit/.../eval-stdin.php). - Alert on anomalous database connections or unusual query volumes from web hosts.
- Implement file integrity monitoring to detect unexpected files or payloads dropped on the webroot.
8. Incident response steps (high level)
If you detect a similar compromise or exposure:
- Isolate the affected host from the network (to stop further exfiltration).
- Rotate credentials that were present on the host (database, API keys) after containment β do this via a secure process.
- Collect forensic evidence (logs, disk images) and preserve it for investigation.
- Check for persistence (webshells, unauthorized scheduled tasks, new users) and remediate thoroughly.
- Restore from trusted backups if necessary and ensure the vulnerability that led to the compromise is patched before returning the host to production.
- Notify stakeholders and comply with applicable reporting laws/regulations.
9. Preventative practices
- Secure CI/CD pipelines so development dependencies are never pushed to production unintentionally.
- Perform regular code reviews and automated scanning (SAST/DAST) and scheduled vulnerability scans to detect exposures like web-accessible vendor directories.
- Periodic pen-testing and threat-modeling to identify attack paths focusing on sensitive data exposure.