TECHNICAL BULLETIN
| PROBLEM: | In recent months, many servers running ssh have been compromised using the SSH CRC32 Compensation Attack Detector. Compromised machines have either not been upgraded to SSH protocol 2 or have not disabled drop back to SSH protocol 1. Use of this attack allows a remote user to gain root access on a server. |
| PLATFORM: | Any server running SSH protocol 1 or SSH protocol 2 configured to drop back to protocol 1. |
| ABSTRACT: | This technical bulletin describes the SSH CRC32 Compensation Attack Detector vulnerability and the operation of an exploit code that attacks that vulnerability. It discusses detecting the version of sshd that a system is running and how to differentiate between different versions. |
[Revised: 5/9/2002 Added SSH protocol 1 comments to conclusion.]
In recent months, many servers running ssh have been compromised using the SSH CRC32 Compensation Attack Detector. Compromised machines have either not been upgraded to SSH protocol 2 (SSH-2) or have not disabled drop back to SSH protocol 1 (SSH-1). Use of this attack allows a remote user to gain root access on a server. Over the last few weeks we have also seen many rumors about different exploitable versions of the sshd daemon. This Technical Bulletin will attempt to sort out what we know about these vulnerabilities and what you can do about them.
The vulnerability being exploited in all of these attacks is known as the SSH CRC32 Compensation Attack Detector. It was found by Michal Zalewski of Bindview in February of 2001. The exploited code was actually inserted in sshd to compensate for a deficiency in the SSH-1 protocol. The exploited code watches for an attempt to attack the deficiency. The attack detector creates a dynamically allocated table in memory to store the connection information it uses to detect an attack. Using a crafted packet, it is possible to create a table with zero length and to then push data into the zero length table, overwriting memory including the function’s return address. As soon as an intruder can change a function’s return address, he can run any code and use it to open a shell running with the privilege of the sshd daemon (usually root).
Note: There is more than one SSH protocol and more than one version of the sshd program. All of the current 1.x versions of the sshd program implement SSH protocol 1.5, which is generally called the SSH-1 protocol. Program versions 2 and higher with drop back to protocol 1 enabled show the SSH 1.99 protocol or if drop back is disabled, they show SSH 2.0 protocol. Both of these are the SSH-2 protocol. If you telnet to port 22 on a machine that is running the sshd daemon, you get back a string that tells you the protocol currently being implemented and the version of the sshd daemon. For example, a returned string might be: SSH-1.5-1.2.27 which tells you that the daemon is implementing protocol version 1.5 and that the daemon is version 1.2.27.
Note: The SSH-2 daemons implement a drop back to protocol 1 mode for protocol 1 clients. For OpenSSH, both the SSH-1 and SSH-2 protocols are implemented in the single sshd daemon. For F-Secure and ssh.com versions of SSH, the protocols are implemented in two different programs. The SSH-2 protocol daemon accepts the connection and passes it to an SSH-1 protocol daemon if the client is not able to handle the SSH-2 protocol. In both cases, the drop back is turned on or off with a command in the sshd configuration file.
We obtained a copy of an exploit code for the CRC32 Compensation Detector attack and tested it against several versions of sshd. The exploit code runs on Linux systems and only attacks sshd running on other Linux systems. Because buffer overflow attacks are hardware specific (you are pushing machine codes into memory) this exploit program would have to be rewritten to attack other platforms such as Solaris running on a Sparc processor. Because the vulnerability is dependent on the software, any UNIX system running a vulnerable version of sshd is vulnerable to this exploit, just not this particular implementation of it.
The exploit code we obtained has seven different exploits in it selected from the following list.
( 1)
Small - SSH-1.5-1.2.26
( 2) Small - SSH-1.5-1.2.27
( 3) Small - SSH-1.5-1.2.31
( 4) Small - SSH-1.5-1.3.07
( 5) Small - SSH-1.5-OpenSSH-1.2.3
( 6) Small - SSH-1.99-OpenSSH_2.2.0p1
( 7) Big - SSH-1.99-OpenSSH_2.2.0p1
We noted that many of the exploits are not limited to the indicated version of sshd but work against several of the versions. Note also that attacks 6 and 7 on the SSH-2 protocol actually attack the SSH-1 protocol part of the sshd daemon. We don’t know what the difference is between attacks 6 and 7. If the option to drop back to SSH-1 protocol is disabled, the exploits don’t work.
For example, see OpenSSH 2.2.0 in the table below. We tested it three times, first with both protocols enabled, next with only protocol 2, and lastly with only protocol 1. As you can see, the exploits only worked when protocol 1 was enabled.
|
|
|
SSH Attack |
|
|
|
||
|
SSH Version String (protocol) |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
|
SSH-1.5-1.2.21 |
F |
F |
F |
F |
F |
F |
F |
|
SSH-1.5-1.2.26 |
W |
W |
F |
|
|
|
|
|
SSH-1.5-1.2.27 |
W |
W |
F |
|
|
|
|
|
SSH-1.5-1.2.31 |
W |
W |
F |
F |
|
|
|
|
SSH-1.5-1.2.32 |
|
Q |
Q |
Q |
|
|
|
|
SSH-1.5-1.3.5 |
|
Q |
Q |
Q |
|
|
|
|
SSH-1.5-OpenSSH-1.2.3 |
|
F |
|
|
F |
F |
|
|
SSH-1.99-2.3.1 |
F |
F |
F |
F |
F |
F |
F |
|
SSH-1.99-OpenSSH_2.1.1p1 (1, 2) |
F |
F |
F |
F |
F |
F |
F |
|
SSH-1.99-OpenSSH_2.2.0p1 (1, 2) |
|
W |
|
|
|
F |
F |
|
SSH-1.99-OpenSSH_2.2.0p1 ( 2) |
|
F |
|
|
|
F |
F |
|
SSH-1.99-OpenSSH_2.2.0p1 ( 1 ) |
|
W |
|
|
|
F |
F |
|
SSH-1.99-OpenSSH_2.9p2 (1,2) |
Q |
Q |
Q |
Q |
Q |
Q |
Q |
|
SSH-1.99-OpenSSH_2.9p2 ( 2) |
C |
C |
C |
C |
C |
C |
C |
|
SSH-1.99-OpenSSH_2.9p2 ( 1) |
Q |
Q |
Q |
Q |
Q |
Q |
Q |
|
SSH-1.99-OpenSSH_3.0.2p1 (1, 2) |
Q |
Q |
Q |
Q |
Q |
Q |
Q |
|
SSH-1.5-1.3.3 Solaris |
Q |
Q |
Q |
Q |
Q |
Q |
Q |
F = Failed
W = Worked
Q = Quit, wouldn’t try
C = Crashed exploit code
All of the servers in the table were running on a Red Hat Linux 7.0 system. It is not impossible that some of the failures noted in the table are related to the OS and libraries on the system and not only on the version of SSH installed.
One thing that was curious was that we could not get the protocol 2 attacks (6 and 7) to work against the specific version listed for the attack (OpenSSH_2.2.0p1). We don’t know if it was some combination of system and server that was different from the intruder’s or if the attacks listed in the code were more wishful thinking on the intruder’s part. It does appear that the attack is only against the SSH-1 protocol part of OpenSSH as the attack code crashed when fall back to the SSH-1 protocol was disabled.
When run, the exploit code prints the following reports on the terminal.
[root@arianna ss]# ./x10 -t1 192.168.1.120
password:
Target: Small - SSH-1.5-1.2.26
Attacking: 192.168.1.120:22
Testing if remote sshd is vulnerable # ATTACH NOWYES #
Finding h - buf distance (estimate)
(1 ) testing 0x00000004 # SEGV #
(2 ) testing 0x0000c804 # FOUND #
Found buffer, determining exact diff
Finding h - buf distance using the teso method
(3 ) binary-search: h: 0x083fb7fc, slider: 0x00008000 # SEGV #
(4 ) binary-search: h: 0x083f77fc, slider: 0x00004000 # SURVIVED #
(5 ) binary-search: h: 0x083f97fc, slider: 0x00002000 # SURVIVED #
(6 ) binary-search: h: 0x083fa7fc, slider: 0x00001000 # SEGV #
(7 ) binary-search: h: 0x083f9ffc, slider: 0x00000800 # SEGV #
(8 ) binary-search: h: 0x083f9bfc, slider: 0x00000400 # SEGV #
(9 ) binary-search: h: 0x083f99fc, slider: 0x00000200 # SURVIVED #
(10) binary-search: h: 0x083f9afc, slider: 0x00000100 # SEGV #
(11) binary-search: h: 0x083f9a7c, slider: 0x00000080 # SEGV #
(12) binary-search: h: 0x083f9a3c, slider: 0x00000040 # SEGV #
(13) binary-search: h: 0x083f9a1c, slider: 0x00000020 # SEGV #
(14) binary-search: h: 0x083f9a0c, slider: 0x00000010 # SURVIVED #
(15) binary-search: h: 0x083f9a14, slider: 0x00000008 # SURVIVED #
Bin search done, testing result
Finding exact h - buf distance
(16) trying: 0x083f9a14 # SURVIVED #
Exact match found at: 0x000065ec
Looking for exact buffer address
Finding exact buffer address
(17) Trying: 0x080865ec # SURVIVED #
Finding distance till stack buffer
(18) Trying: 0xb7f81400 # SEGV #
(19) Trying: 0xb7f81054 # SEGV #
(20) Trying: 0xb7f80ca8 # SEGV #
(21) Trying: 0xb7f808fc # SEGV #
(22) Trying: 0xb7f80550 # SEGV #
(23) Trying: 0xb7f801a4 # SEGV #
(24) Trying: 0xb7f7fdf8 # SEGV #
(25) Trying: 0xb7f7fa4c # SEGV #
(26) Trying: 0xb7f7f6a0 # SEGV #
(27) Trying: 0xb7f7f2f4 # SEGV #
(28) Trying: 0xb7f7ef48 # SEGV #
(29) Trying: 0xb7f7eb9c # SEGV #
(30) Trying: 0xb7f7e7f0 # SEGV #
(31) Trying: 0xb7f7e444 # SEGV #
(32) Trying: 0xb7f7e098 # SURVIVED # verifying
(33) Trying: 0xb7f7e098 # SEGV # OK
Finding exact h - stack_buf distance
(34) trying: 0xb7f7de98 slider: 0x0200# SURVIVED #
(35) trying: 0xb7f7dd98 slider: 0x0100# SURVIVED #
(36) trying: 0xb7f7dd18 slider: 0x0080# SEGV #
(37) trying: 0xb7f7dd58 slider: 0x0040# SEGV #
(38) trying: 0xb7f7dd78 slider: 0x0020# SURVIVED #
(39) trying: 0xb7f7dd68 slider: 0x0010# SEGV #
(40) trying: 0xb7f7dd70 slider: 0x0008# SEGV #
(41) trying: 0xb7f7dd74 slider: 0x0004# SURVIVED #
(42) trying: 0xb7f7dd72 slider: 0x0002# SEGV #
Final stack_dist: 0xb7f7dd74
EX: buf: 0x080835ec h: 0x0807d000 ret-dist: 0xb7f7dcfa
ATTACH NOW
Changing MSW of return address to: 0x0808
Crash, finding next return address
Changing MSW of return address to: 0x0809
Crash, finding next return address
Changing MSW of return address to: 0x080a
Crash, finding next return address
EX: buf: 0x080835ec h: 0x0807d000 ret-dist: 0xb7f7dcf6
ATTACH NOW
Changing MSW of return address to: 0x0808
Crash, finding next return address
Changing MSW of return address to: 0x0809
Crash, finding next return address
Changing MSW of return address to: 0x080a
Crash, finding next return address
EX: buf: 0x080835ec h: 0x0807d000 ret-dist: 0xb7f7dcfc
ATTACH NOW
Changing MSW of return address to: 0x0808
Crash, finding next return address
Changing MSW of return address to: 0x0809
No Crash, might have worked
Reply from remote: CHRIS CHRIS
***** YOU ARE IN *****
localhost.localdomain
Linux localhost.localdomain 2.2.16-22 #1 Tue Aug 22 16:49:06 EDT 2000 i686 unknown
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
This was an attack on an SSH 1.2.26 server using the 1.2.26 attack. The password is for making the exploit code work. The exploit first connects to the remote system, gets the version of sshd that is running, and decides if it is going to attack. All the items in the table above that are marked Q = Quit are situations where it decided to not attack the system.
Next, it starts a binary search for a buffer. It appears that it sends a packet to the system and if the packet causes the server to fail (SEGV) it didn’t find the buffer. If the server stays alive (SURVIVED) then it found the buffer. It refines its search until it finally locates the start of the buffer.
After finding the first buffer, it searches for and finds a “stack buffer”. After finding both buffers, it starts attacking the system. In this case, it took three tries to break into the system and get a root shell. In the cases in the chart where the attacks failed, some attacks failed looking for the buffers and some failed in the attack phase.
SSH CRC32 Compensation Attack Detector vulnerability is only associated with sshd server daemons that implement the SSH-1 protocol. This includes sshd version 1.x stand alone daemons and sshd version 2.x and later daemons that enable drop back to SSH-1 protocols. None of the exploits we tested appeared to have any affect on machines running purely SSH-2 protocols. This vulnerability only applies to ssh servers, it does not affect ssh client programs.
To protect yourself from this vulnerability, you must not only install SSH-2 protocol daemons but you must also disable the drop back to SSH-1 protocols. Systems that are currently being compromised are neglecting this second step!
For F-Secure and ssh.com versions of sshd, remove the SSH-1 protocol daemon from the system and set the following tag in the /etc/ssh2/sshd2_config file.
Ssh1Compatibility no
For OpenSSH, the SSH-1 protocols are part of the SSH-2 daemon and cannot be removed from the system. However, they can be disabled by setting the following tag in the /etc/ssh/sshd_config file.
Protocol 2
If you don’t know which version of the sshd daemon you are running, there are two ways to find out: connecting to the daemon, and examining the sshd file.
If the sshd daemon is loaded and running you can get its connection string by telneting to the ssh port (22). The connection string first shows the ssh protocol being used followed by the program version. Press return to close the connection. Telneting to the ssh port can be done remotely or locally (shown below). For remote connections, use the machine’s name or IP address instead of “localhost” in the telnet command.
[root@arianna /root]# telnet localhost 22
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
SSH-2.0-OpenSSH_2.9p2
To tell if drop back to the SSH-1 protocol is enabled in SSH-2 systems, examine the SSH protocol returned by the daemon. If the SSH protocol is 2.0 as shown above, drop back to SSH-1 is not enabled. If drop back to SSH-1 is enabled, the SSH protocol changes to 1.99 as shown below.
[root@arianna ssh]# telnet localhost 22
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
SSH-1.99-OpenSSH_2.9p2
If the system is configured to only use the SSH-1 protocol, the protocol version is 1.5 as shown below.
[root@arianna /root]# telnet localhost 22
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
SSH-1.5-OpenSSH_2.9p2
Another way to see the connection string is to connect to the server using an ssh client with verbose mode turned on. To turn on verbose mode in a command line version of ssh, use the –v switch; in the current gui versions, choose Edit, Settings and check the Verbose mode box on the Appearance tab. The connection string appears in the debug messages when you attempt to connect to the server as shown below.
debug: Wrapping...
debug: Remote version: SSH-1.5-OpenSSH_2.9p2
debug: Remote server talks SSH-1.5 protocol.
Note that you do not need to be able to login to an ssh server to get this information, you need only attempt to login.
If the sshd daemon is not running you can examine the sshd file itself to see what its program version is. From within the system, find the sshd daemon program (usually in /usr/local/sbin or /usr/sbin), do a “strings” on it, and pipe the results through “more”. As you scroll through the strings, watch for the one that contains the program version as shown below.
[root@arianna /root]# strings /usr/sbin/sshd | more
/lib/ld-linux.so.2
__gmon_start__
libpam.so.0
_DYNAMIC
pam_getenvlist
pam_end
pam_chauthtok
pam_authenticate
pam_close_session
_init
pam_setcred
pam_open_session
pam_set_item
pam_acct_mgmt
.
.
.
RSA key generation complete.
OpenSSH_2.9p2
SSH-%d.%d-%.100s
Could not write ident string to %s.
.
.
.
Over the last few weeks, we have seen many systems broken into and multiple claims and rumors about exploitation programs that can break into ssh version 2.x and version 3.x server daemons. As best we can tell, the breakins to SSH-2 systems are actually caused by the daemon’s ability to drop back to SSH protocol 1 for clients that do not handle protocol 2. Systems with only SSH-2 daemons on them and systems that have disabled drop back to SSH-1 are not vulnerable to this attack. Users should protect their systems by converting completely to SSH-2 protocol systems and by eliminating or disabling access to daemons implementing the SSH-1 protocol.
If you are unable to convert completely to SSH protocol 2 because of legacy applications that must use protocol 1, you should upgrade your sshd server to a version that is not vulnerable to the CRC32 Compensation Attack Detector vulnerability and use the hosts.allow file to limit the addresses that can connect to the server. F-Secure patched this problem in version 1.3.11 (build 2) and OpenSSH patched it in version 2.3.0 but we have been unable to test this fact as the exploit code will not run against these versions. The most current version (May 2002) of the F-Secure protocol 1 server is 1.3.11 and of OpenSSH is 3.2.1 (3.1 if you are not using Kerberos authentication). These servers should be upgraded to protocol 2 as soon as the legacy capability is no longer needed. We reiterate that the best solution is to completely retire all SSH protocol 1 servers and move to protocol 2, as protocol 2 is significantly stronger and protocol 1 is only being minimally supported.
E-mail: doecirc@doecirc.energy.gov
World Wide Web: http://www.doecirc.energy.gov/