On December 18th, 2015 Juniper issued an advisory indicating that they had discovered unauthorized code in the ScreenOS software that powers their Netscreen firewalls. This advisory covered two distinct issues; a backdoor in the VPN implementation that allows a passive eavesdropper to decrypt traffic and a second backdoor that allows an attacker to bypass authentication in the SSH and Telnet daemons. Shortly after Juniper posted the advisory, an employee of FoxIT stated that they were able to identify the backdoor password in six hours. A quick Shodan search identified approximately 26,000 internet-facing Netscreen devices with SSH open. Given the severity of this issue, we decided to investigate.
Juniper’s advisory mentioned that versions 6.2.0r15 to 6.2.0r18 and 6.3.0r12 to 6.3.0r20 were affected. Juniper provided a new 6.2.0 and 6.3.0 build, but also rebuilt older packages that omit the backdoor code. The rebuilt older packages have the “b” suffix to the version and have a minimal set of changes, making them the best candidate for analysis. In order to analyze the firmware, it must be unpacked and then decompressed. The firmware is distributed as a ZIP file that contains a single binary. This binary is a decompression stub followed by a gzip-compressed kernel. The x86 images can be extracted easily with binwalk, but the XScale images require a bit more work. ScreenOS is not based on Linux or BSD, but runs as a single monolithic kernel. The SSG500 firmware uses the x86 architecture, while the SSG5 and SSG20 firmware uses the XScale (ARMB) architecture. The decompressed kernel can be loaded into IDA Pro for analysis. As part of the analysis effort, we have made decompressed binaries available in a GitHub repository.
Although most folks are more familiar with x86 than ARM, the ARM binaries are significantly easier to compare due to minimal changes in the compiler output. In order to load the SSG5 (ssg5ssg20.6.3.0r19.0.bin) firmware into IDA, the ARMB CPU should be selected, with a load address of 0x80000 and a file offset of 0x20. Once the binary is loaded, it helps to identify and tag common functions. 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:
ROM:0013DBCC ; ---------------------------------------------------------------------------
ROM:0013DBD0 off_13DBD0 DCD aAdmin_auth_c ; DATA XREF: sub_13DAF4+3Cr
ROM:0013DBD0 ; "admin_auth.c"
ROM:0013DBD4 off_13DBD4 DCD aAuthed_admin_1 ; DATA XREF: sub_13DAF4+44r
ROM:0013DBD4 ; "(authed_admin_id && task_id)"
ROM:0013DBD8 off_13DBD8 DCD dword_1E7FCF0 ; DATA XREF: sub_13DAF4:loc_13DB48r
ROM:0013DBD8 ; sub_13DAF4:loc_13DB94r
ROM:0013DBDC off_13DBDC DCD aSIdUTidUV0x08x ; DATA XREF: sub_13DAF4+6Cr
ROM:0013DBDC ; ">>> %s(id=%u, tid=%u, *v=0x%08x)"
ROM:0013DBE0 off_13DBE0 DCD aAuth_admin_ssh ; DATA XREF: sub_13DAF4+70r
ROM:0013DBE0 ; sub_13DAF4+C4r
ROM:0013DBE0 ; "auth_admin_ssh_special"
ROM:0013DBE4 off_13DBE4 DCD aVoid_0 ; DATA XREF: sub_13DAF4+BCr
ROM:0013DBE4 ; "void"
ROM:0013DBE8 off_13DBE8 DCD aSVSU ; DATA XREF: sub_13DAF4+C0r
ROM:0013DBE8 ; "<<< %s(*v='%s') = %u"
ROM:0013DBEC
ROM:0013DBEC ; =============== S U B R O U T I N E =======================================
ROM:0013DBEC
ROM:0013DBEC ; Attributes: bp-based frame
ROM:0013DBEC
ROM:0013DBEC sub_13DBEC ; CODE XREF: sub_13D650+180p
ROM:0013DBEC ; sub_13D92C+80p ...
ROM:0013DBEC
ROM:0013DBEC var_30 = -0x30
ROM:0013DBEC var_2C = -0x2C
ROM:0013DBEC var_28 = -0x28
ROM:0013DBEC var_24 = -0x24
ROM:0013DBEC
ROM:0013DBEC MOV R12, SP
ROM:0013DBF0 STMFD SP!, {R4-R8,R11,R12,LR,PC}
ROM:0013DBF4 SUB R11, R12, #4
ROM:0013DBF8 SUB SP, SP, #0x10
ROM:0013DBFC MOV R5, R0
ROM:0013DC00 MOV R6, #0
ROM:0013DC04 MOV R7, R6
ROM:0013DC08 MOV R8, R6
ROM:0013DC0C LDR R3, =dword_1E7FCF0
ROM:0013DC10 LDR R12, [R3]
ROM:0013DC14 CMP R12, R6
ROM:0013DC18 BEQ loc_13DC5C
ROM:0013DC1C ADD R0, R0, #0x6C
ROM:0013DC20 BL sub_402B9C
ROM:0013DC24 MOV R4, R0
ROM:0013DC28 ADD R0, R5, #0x80
ROM:0013DC2C BL sub_402B9C
ROM:0013DC30 LDRH R2, [R5,#0x68]
ROM:0013DC34 ADD R3, R5, #4
ROM:0013DC38 STR R4, [SP,#0x30+var_30]
ROM:0013DC3C STR R0, [SP,#0x30+var_2C]
ROM:0013DC40 LDRH R12, [R5,#0x94]
ROM:0013DC44 STR R12, [SP,#0x30+var_28]
ROM:0013DC48 LDRH R12, [R5,#0x96]
ROM:0013DC4C STR R12, [SP,#0x30+var_24]
ROM:0013DC50 LDR R0, =aSCtUUnSSipSDip ; ">>> %s(ct=%u, un='%s', sip=%s, dip=%s, "...
ROM:0013DC54 LDR R1, =aAuth_admin_int ; "auth_admin_internal"
ROM:0013DC58 BL sub_558F74
ROM:0013DC5C
ROM:0013DC5C loc_13DC5C ; CODE XREF: sub_13DBEC+2Cj
ROM:0013DC5C ADD R0, R5, #0x44
ROM:0013DC60 LDR R1, =aSUnSU ; "<<< %s(un='%s') = %u"
ROM:0013DC64 BL sub_ED7D94
ROM:0013DC68 CMP R0, #0
ROM:0013DC6C BNE loc_13DC78
ROM:0013DC70 MOV R0, #0xFFFFFFFD
ROM:0013DC74 LDMDB R11, {R4-R8,R11,SP,PC}
ROM:0013DC78 ; ---------------------------------------------------------------------------
ROM:0013DC78
ROM:0013DC78 loc_13DC78 ; CODE XREF: sub_13DBEC+80j
ROM:0013DC78 ADD R0, R5, #0x6C
ROM:0013DC7C BL sub_14724C
ROM:0013DC80 MOVS R0, R0,LSL#16
ROM:0013DC84 MOVNE R7, #1
ROM:0013DC88 BNE loc_13DDFC
ROM:0013DC8C LDRH R12, [R5,#0x68]
ROM:0013DC90 ADD R12, R12, #0xFF00
ROM:0013DC94 ADD R12, R12, #0xFE
ROM:0013DC98 MOV R12, R12,LSL#16
ROM:0013DC9C CMP R12, #0x20000
ROM:0013DCA0 BHI loc_13DCD8
ROM:0013DCA4 ADD R4, R5, #4
ROM:0013DCA8 MOV R0, R4
ROM:0013DCAC BL sub_141444
ROM:0013DCB0 CMP R0, #0
ROM:0013DCB4 BLE loc_13DCD8
ROM:0013DCB8 MOV R8, #1
ROM:0013DCBC ADD R0, R5, #0x6C
ROM:0013DCC0 BL sub_402B9C
ROM:0013DCC4 MOV R2, R0
ROM:0013DCC8 LDR R0, =0x5011008
ROM:0013DCCC MOV R1, R4
ROM:0013DCD0 BL sub_562678
ROM:0013DCD4 B loc_13DDFC
ROM:0013DCD8 ; ---------------------------------------------------------------------------
ROM:0013DCD8
ROM:0013DCD8 loc_13DCD8 ; CODE XREF: sub_13DBEC+B4j
ROM:0013DCD8 ; sub_13DBEC+C8j
ROM:0013DCD8 MOV R0, R5
ROM:0013DCDC BL sub_13DEA8
ROM:0013DCE0 MOVS R0, R0,LSL#16
ROM:0013DCE4 BEQ loc_13DDFC
ROM:0013DCE8 LDR R12, [R5,#0x98]
ROM:0013DCEC CMP R12, #0
ROM:0013DCF0 LDREQ R3, =0x2758560
ROM:0013DCF4 LDREQ R4, [R3]
ROM:0013DCF8 LDRNE R4, [R5,#0x98]
ROM:0013DCFC MOV R12, #0
ROM:0013DD00 STR R12, [R5,#0x98]
ROM:0013DD04 LDR R12, [R5,#0x9C]
ROM:0013DD08 CMP R12, #0
ROM:0013DD0C BNE loc_13DD18
ROM:0013DD10 BL sub_9E9CC
ROM:0013DD14 STR R0, [R5,#0x9C]
ROM:0013DD18
ROM:0013DD18 loc_13DD18 ; CODE XREF: sub_13DBEC+120j
ROM:0013DD18 MOV R0, R5
ROM:0013DD1C BL sub_13E3F8
ROM:0013DD20 MOVS R0, R0,LSL#16
ROM:0013DD24 BEQ loc_13DDFC
ROM:0013DD28 LDR R12, [R5,#0x98]
ROM:0013DD2C CMP R12, #0
ROM:0013DD30 LDREQ R3, =0x2758560
ROM:0013DD34 LDREQ R1, [R3]
ROM:0013DD38 LDRNE R1, [R5,#0x98]
ROM:0013DD3C MOV R12, #0
ROM:0013DD40 STR R12, [R5,#0x98]
ROM:0013DD44 MOV R0, R5
ROM:0013DD48 MOV R2, R4
ROM:0013DD4C BL sub_13EC1C
ROM:0013DD50 CMP R0, #0
ROM:0013DD54 BEQ loc_13DDFC
ROM:0013DD58 MOV R0, R5
ROM:0013DD5C BL sub_13EFAC
ROM:0013DD60 MOVS R0, R0,LSL#16
ROM:0013DD64 BEQ loc_13DDFC
ROM:0013DD68 ADD R0, R5, #0x6C
ROM:0013DD6C BL sub_4028BC
ROM:0013DD70 MOV R0, R5
ROM:0013DD74 BL sub_149564
ROM:0013DD78 CMP R0, #0
ROM:0013DD7C BEQ loc_13DDFC
ROM:0013DD80 MOV R6, R0
ROM:0013DD84 LDRH R12, [R5,#0x68]
ROM:0013DD88 ADD R12, R12, #0xFF00
ROM:0013DD8C ADD R12, R12, #0xFE
ROM:0013DD90 MOV R12, R12,LSL#16
ROM:0013DD94 CMP R12, #0x20000
ROM:0013DD98 BHI loc_13DDCC
ROM:0013DD9C ADD R4, R5, #4
ROM:0013DDA0 MOV R0, R4
ROM:0013DDA4 BL sub_141258
ROM:0013DDA8 MOVS R0, R0,LSL#16
ROM:0013DDAC BEQ loc_13DDCC
ROM:0013DDB0 LDR R3, =dword_1E7FCF0
ROM:0013DDB4 LDR R12, [R3]
ROM:0013DDB8 CMP R12, #0
ROM:0013DDBC BEQ loc_13DDCC
ROM:0013DDC0 LDR R0, =aLockForAdminSI ; "Lock for admin %s is cleared after an s"...
ROM:0013DDC4 MOV R1, R4
ROM:0013DDC8 BL sub_558F74
ROM:0013DDCC
ROM:0013DDCC loc_13DDCC ; CODE XREF: sub_13DBEC+1ACj
ROM:0013DDCC ; sub_13DBEC+1C0j ...
ROM:0013DDCC LDRH R3, [R5,#0x68]
ROM:0013DDD0 ADD R12, R3, #0xFF00
ROM:0013DDD4 ADD R12, R12, #0xFE
ROM:0013DDD8 MOV R12, R12,LSL#16
ROM:0013DDDC CMP R3, #3
ROM:0013DDE0 MOVNE R3, #0
ROM:0013DDE4 MOVEQ R3, #1
ROM:0013DDE8 CMP R12, #0x20000
ROM:0013DDEC ORRHI R3, R3, #1
ROM:0013DDF0 CMP R3, #0
ROM:0013DDF4 MOVNE R0, R5
ROM:0013DDF8 BLNE sub_13F080
ROM:0013DDFC
ROM:0013DDFC loc_13DDFC ; CODE XREF: sub_13DBEC+9Cj
ROM:0013DDFC ; sub_13DBEC+E8j ...
ROM:0013DDFC EOR R12, R7, #1
ROM:0013DE00 CMP R6, #0
ROM:0013DE04 MOVNE R12, #0
ROM:0013DE08 ANDEQ R12, R12, #1
ROM:0013DE0C CMP R12, #0
ROM:0013DE10 ADDNE R0, R5, #0x6C
ROM:0013DE14 BLNE sub_1472BC
ROM:0013DE18 LDRH R12, [R5,#0x68]
ROM:0013DE1C ADD R12, R12, #0xFF00
ROM:0013DE20 ADD R12, R12, #0xFE
ROM:0013DE24 MOV R12, R12,LSL#16
ROM:0013DE28 CMP R12, #0x20000
ROM:0013DE2C BHI loc_13DE4C
ROM:0013DE30 EOR R12, R8, #1
ROM:0013DE34 CMP R6, #0
ROM:0013DE38 MOVNE R12, #0
ROM:0013DE3C ANDEQ R12, R12, #1
ROM:0013DE40 CMP R12, #0
ROM:0013DE44 ADDNE R0, R5, #4
ROM:0013DE48 BLNE sub_141490
ROM:0013DE4C
ROM:0013DE4C loc_13DE4C ; CODE XREF: sub_13DBEC+240j
ROM:0013DE4C LDR R3, =dword_1E7FCF0
ROM:0013DE50 LDR R12, [R3]
ROM:0013DE54 CMP R12, #0
ROM:0013DE58 BEQ loc_13DE7C
ROM:0013DE5C LDR R0, [R5,#0x98]
ROM:0013DE60 CMP R0, #0
ROM:0013DE64 ADDNE R2, R0, #8
ROM:0013DE68 LDREQ R2, =aVoid_0 ; "void"
ROM:0013DE6C LDR R0, =aSVsysSU ; "<<< %s(vsys='%s') = %u"
ROM:0013DE70 LDR R1, =aAuth_admin_int ; "auth_admin_internal"
ROM:0013DE74 MOV R3, R6
ROM:0013DE78 BL sub_558F74
ROM:0013DE7C
ROM:0013DE7C loc_13DE7C ; CODE XREF: sub_13DBEC+26Cj
ROM:0013DE7C MOV R0, R6
ROM:0013DE80 LDMDB R11, {R4-R8,R11,SP,PC}
ROM:0013DE80 ; End of function sub_13DBEC
ROM:0013DE80
ROM:0013DE80 ; ---------------------------------------------------------------------------
The argument to the strcmp call is <<< %s(un=’%s’) = %u, 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, as long as they know a valid username. If you want to test this issue by hand, telnet or ssh to a Netscreen device, specify a valid username, and the backdoor password. If the device is vulnerable, you should receive an interactive shell with the highest privileges.
The interesting thing about this backdoor is not the simplicity, but the timing. Juniper’s advisory claimed that versions 6.2.0r15 to 6.2.0r18 and 6.3.0r12 to 6.3.0r20 were affected, but the authentication backdoor is not actually present in older versions of ScreenOS. We were unable to identify this backdoor in versions 6.2.0r15, 6.2.0r16, 6.2.0r18 and it is probably safe to say that the entire 6.2.0 series was not affected by this issue (although the VPN issue was present). We were also unable to identify the authentication backdoor in versions 6.3.0r12 or 6.3.0r14. We could confirm that versions 6.3.0r17 and 6.3.0r19 were affected, but were not able to track down 6.3.0r15 or 6.3.0r16. This is interesting because although the first affected version was released in 2012, the authentication backdoor did not seem to get added until a release in late 2013 (either 6.3.0r15, 6.3.0r16, or 6.3.0r17).
Detecting the exploitation of this issue is non-trivial, but there are a couple things you can do. Juniper provided guidance on what the logs from a successful intrusion would look like:
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 …
Although an attacker could delete the logs once they gain access, any logs sent to a centralized logging server (or SIEM) would be captured, and could be used to trigger an alert.
FoxIT has a created a set of Snort rules that can detect access with the backdoor password over Telnet and fire on any connection to a ScreenOS Telnet or SSH service:
# Signatures to detect successful abuse of the Juniper backdoor password over telnet.
# Additionally a signature for detecting world reachable ScreenOS devices over SSH.
alert tcp $HOME_NET 23 -> any any (msg:"FOX-SRT - Flowbit - Juniper ScreenOS telnet (noalert)"; flow:established,to_client; content:"Remote Management Console|0d0a|"; offset:0; depth:27; flowbits:set,fox.juniper.screenos; flowbits:noalert; reference:cve,2015-7755; reference:url,http://kb.juniper.net/JSA10713; classtype:policy-violation; sid:21001729; rev:2;)
alert tcp any any -> $HOME_NET 23 (msg:"FOX-SRT - Backdoor - Juniper ScreenOS telnet backdoor password attempt"; flow:established,to_server; flowbits:isset,fox.juniper.screenos; flowbits:set,fox.juniper.screenos.password; content:"|3c3c3c20257328756e3d2725732729203d202575|"; offset:0; fast_pattern; classtype:attempted-admin; reference:cve,2015-7755; reference:url,http://kb.juniper.net/JSA10713; sid:21001730; rev:2;)
alert tcp $HOME_NET 23 -> any any (msg:"FOX-SRT - Backdoor - Juniper ScreenOS successful logon"; flow:established,to_client; flowbits:isset,fox.juniper.screenos.password; content:"-> "; isdataat:!1,relative; reference:cve,2015-7755; reference:url,http://kb.juniper.net/JSA10713; classtype:successful-admin; sid:21001731; rev:1;)
alert tcp $HOME_NET 22 -> $EXTERNAL_NET any (msg:"FOX-SRT - Policy - Juniper ScreenOS SSH world reachable"; flow:to_client,established; content:"SSH-2.0-NetScreen"; offset:0; depth:17; reference:cve,2015-7755; reference:url,http://kb.juniper.net/JSA10713; classtype:policy-violation; priority:1; sid:21001728; rev:1;)
If you are trying to update a ScreenOS system and are running into issues with the signing key, take a look at Steve Puluka’s blog post.
We would like to thank Ralf-Philipp Weinmann of Comsecuris for his help with unpacking and analyzing the firmware and Maarten Boone of Fox-IT for confirming our findings and providing the Snort rules above.
Commands
root@seclab's password:
Remote Management Console
SSG140-> get
address show address book
admin show admin information
adsl show adsl info
alarm show alarm info
alg application layer gateway information
alg-portnum get ALG port num
alias get alias definitions
arp show ARP entries
asp asp information
attack show attacks
auth show authentication information
auth-server authentication server settings
chassis show chassis information
clock show system clock
config show system configuration
console show console parameters
core-dump show core dump parameters
counter show counters
crypto-policy configure cryptographic policies
di get deep inspection parameters
dialer get dialer information
dip show all dips in a vsys or root
dip-in show incoming dip table info
dns show dns info
domain show domain name
dot1x display IEEE802.1X global configuration
dscp-group show dscp group
envar show environment variables
event show event messages
file show file information
fips-mode FIPS mode function
firewall show firewall protection information
flow show flow info
fprofile show status of flow profiling
gate show gate info
group show groups
group-expression group expressions details
hostname show host name
igmp IGMP
ike get IKE info
infranet Infranet Controller configuration
interface show interfaces
ip get ip parameters
ip-classification Show IP classification
ippool get ippool info
ipsec get ipsec information
irdp show IRDP status
l2tp get l2tp information
license-key get license key info
log show log info
mac-learn show mac learning table
memory show memory info
mip show all mips in a vsys or root
mld Multicast Listener Discovery
multicast-group-policy multicast group policy
nrtp show nrtp information
nsmgmt show NSM agent status/configuration
nsrp show nsrp info
ntp get ntp parameters
os show task information
password-policy password policy
patch get patch commands
pattern-update show http/ssl proxy info
performance get performance info
pim show global PIM-SM information
pki show the pki settings
policy show policy
ppp get PPP settings
pppoa show pppoa configuration and statistics
pppoe show pppoe configuration and statistics
proxy-arp-entry show all proxy-arp-entrys in a vsys or root
proxy-id vpn proxy-id setting
qos-profile show QoS profile
rm show resource management info
route show routes in a vrouter
sa show security association
sa-filter config debug message per SA filter
scheduler show scheduler
scp show SCP status
script show script
service show service book
session show all software sessions
session-cache display session cache
shdsl show shdsl info
snmp show SNMP information
snmpv3 show snmpv3 information
snmpwalk snmp walk
socket show socket info
ssh show SSH status
ssl show ssl info
syslog show syslog information
system show system info
tech-support show tech support information
timer show timer info
traffic-shaping show traffic shaping info
url show url filter information
user show user
user-group user group settings
vip show virtual IP info
vpn show vpn session
vpn-group Keyword for showing vpn group setup
vpnmonitor show vpn monitor parameters
vrouter show virtual router info
vrrp Virtual Router Redundancy Protocol
webauth webauth settings
webtrends show webtrends information
xauth get xauth information
xlate show xlate ctx info
zone configure zone