| 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 '^]'.