Discussion:
NSE: RMI Dumpregistry
Martin Holst Swende
2010-06-19 22:31:33 UTC
Permalink
Hi list,

I have (inspired by [1]) implemented an nse script which connects to a
Java RMI Registry and dump out the names of all bound objects. It then
loops over those names and performs lookup, which retrieves some more
info, namely the class hash, the implemented interfaces and superclass
hierarchy.

I imagine this can be quite useful since it may tell quite a bit about
the application - depending on how it uses the registry. For example, if
the app uses JMX (Java Management eXtensions) which is a kind of
framework to administer any java application remotely, the registry will
contain a "jmxconnector" object. There may be quite a handful of
applications which could be fingerprinted by the object names in the
registry, but I have not performed extensive testing on that.

Also, if the objects are of a public type, i.e you can download the
class-files from somewhere, it is a giveaway that it is possible to
explore the app further using native java RMI instead, and interact
directly with the application. If they are proprietary or hidden, the
interface name or object name may still provide useful input for
fingerprinting.

The script uses a library for RMI, which is included in the attachment.
I have written quite a lot of documentation inside the library, so I'll
keep it short here. It can invoke simple methods over RMI, and one thing
I think would be very nice to use it for as a next project, is to write
a bruteforcer for jmx. It seems to be pretty simple (the network dump I
looked at while connecting to a JMX console with JConsole showed the
password in plain text - so it seems to not even to be a
challenge-response process). It should also be possible to use the
library to skip the registry-lookup and connect directly to other
stuff, if you know what the application is (and know what object id's
are addressable and how their method signature look) - e.g write another
script to interact with Neo4j or some other RMI based java app.

Files are attached, but also available from
http://martin.swende.se/hgwebdir.cgi/nsescripts/

1:
http://aboulton.blogspot.com/2009/04/security-assessing-java-rmi-slides.html

Regards,
Martin Holst Swende
ps. One problem I run into pretty often is that RMI is often not
detected, since different apps tend to open ports on different places.
They are usually only found using --version-all, so it makes it
difficult to run the script. Would it be possible to include the
rmi-payload less restrictively?
David Fifield
2010-08-03 18:18:28 UTC
Permalink
Post by Martin Holst Swende
I have (inspired by [1]) implemented an nse script which connects to a
Java RMI Registry and dump out the names of all bound objects. It then
loops over those names and performs lookup, which retrieves some more
info, namely the class hash, the implemented interfaces and superclass
hierarchy.
I imagine this can be quite useful since it may tell quite a bit about
the application - depending on how it uses the registry. For example, if
the app uses JMX (Java Management eXtensions) which is a kind of
framework to administer any java application remotely, the registry will
contain a "jmxconnector" object. There may be quite a handful of
applications which could be fingerprinted by the object names in the
registry, but I have not performed extensive testing on that.
Also, if the objects are of a public type, i.e you can download the
class-files from somewhere, it is a giveaway that it is possible to
explore the app further using native java RMI instead, and interact
directly with the application. If they are proprietary or hidden, the
interface name or object name may still provide useful input for
fingerprinting.
The script uses a library for RMI, which is included in the attachment.
I have written quite a lot of documentation inside the library, so I'll
keep it short here. It can invoke simple methods over RMI, and one thing
I think would be very nice to use it for as a next project, is to write
a bruteforcer for jmx. It seems to be pretty simple (the network dump I
looked at while connecting to a JMX console with JConsole showed the
password in plain text - so it seems to not even to be a
challenge-response process). It should also be possible to use the
library to skip the registry-lookup and connect directly to other
stuff, if you know what the application is (and know what object id's
are addressable and how their method signature look) - e.g write another
script to interact with Neo4j or some other RMI based java app.
Files are attached, but also available from
http://martin.swende.se/hgwebdir.cgi/nsescripts/
Forgive me for taking so long to respond to this. I like the script and
library. Here are the results of my testing. I tried running the test
RMI server from
http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html,
but apparently all that is needed is to run the rmiregistry command.

First, here is running against localhost, with the rmiregistry from Java
IcedTea 1.6.0.

Initiating NSE at 12:04
NSE: NSE Script Threads (1) running:
NSE: Starting rmi-dumpregistry against 127.0.0.1:1099.
NSE: RMI:RMI-Ack received (host 127.0.0.1, port: 54010)
NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: RMI:Ignoring responsetype: 77
NSE: RMI:Reading ordinary object
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.MarshalException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.RemoteException"
NSE: RMI:Field description: name: detail, type: Ljava/lang/Throwable;
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.io.IOException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Exception"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Throwable"
NSE: RMI-ERR:Not implemented, readTypeString(TC_REFERENCE)
NSE: RMI:Field description: name: false, type: primitive type: ()
NSE: RMI:Field description: name: L, type: primitive type: (~)
NSE: RMI-ERR:ERROR; not impl: UNKNOWN
NSE: RMI:TC_classdesc is other 100
NSE: Finished rmi-dumpregistry against 127.0.0.1:1099.


Here it is, with a packet trace, running against the rmiregistry that
comes with Debian Etch. From the exception messages that version
detection causes, it appears to be the one from libgcj.

Initiating NSE at 12:10
NSE: NSE Script Threads (2) running:
NSE: Starting rmi-dumpregistry against 192.168.0.2:1099.
NSE: Starting skypev2-version against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 4a 52 4d 49 00 02 4b JRMI K

NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | 00000000: 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 30 0d 0a GET / HTTP/1.0
00000010: 0d 0a

NSE: TCP 192.168.0.21:34165 < 192.168.0.2:1099 | 00000000: 4e 00 09 6c 6f 63 61 6c 68 6f 73 74 00 00 04 4b N localhost K

NSE: RMI:RMI-Ack received (host localhost, port: 1099)
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 00 09 31 32 37 2e 30 2e 30 2e 31 00 00 00 00 127.0.0.1

NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 50 80 00 00 05 77 22 00 00 00 00 00 00 00 00 00 P w"
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020: 01 44 15 4d c9 d4 e6 3b df D M ;

NSE: Finished rmi-dumpregistry against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CLOSE
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CLOSE
NSE: Finished skypev2-version against 192.168.0.2:1099.
Completed NSE at 12:10, 30.01s elapsed
Nmap scan report for 192.168.0.2
Host is up, received arp-response (0.00032s latency).
Scanned at 2010-08-03 12:08:08 MDT for 163s
PORT STATE SERVICE REASON VERSION
1099/tcp open unknown syn-ack
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port1099-TCP:V=5.35DC18%I=7%D=8/3%Time=4C585B19%P=i686-pc-linux-gnu%r(J
SF:avaRMI,10,"N\0\tlocalhost\0\0\x04K");
Post by Martin Holst Swende
ps. One problem I run into pretty often is that RMI is often not
detected, since different apps tend to open ports on different places.
They are usually only found using --version-all, so it makes it
difficult to run the script. Would it be possible to include the
rmi-payload less restrictively?
If it's limited to a few dozen common ports, we can just enumerate all
of them specifically. If it really varies a lot, and rmiregistry is
really common, then we can reduce the rarity.

David Fifield
Martin Holst Swende
2010-08-08 19:17:41 UTC
Permalink
Post by David Fifield
Post by Martin Holst Swende
I have (inspired by [1]) implemented an nse script which connects to a
Java RMI Registry and dump out the names of all bound objects. It then
loops over those names and performs lookup, which retrieves some more
info, namely the class hash, the implemented interfaces and superclass
hierarchy.
I imagine this can be quite useful since it may tell quite a bit about
the application - depending on how it uses the registry. For example, if
the app uses JMX (Java Management eXtensions) which is a kind of
framework to administer any java application remotely, the registry will
contain a "jmxconnector" object. There may be quite a handful of
applications which could be fingerprinted by the object names in the
registry, but I have not performed extensive testing on that.
Also, if the objects are of a public type, i.e you can download the
class-files from somewhere, it is a giveaway that it is possible to
explore the app further using native java RMI instead, and interact
directly with the application. If they are proprietary or hidden, the
interface name or object name may still provide useful input for
fingerprinting.
The script uses a library for RMI, which is included in the attachment.
I have written quite a lot of documentation inside the library, so I'll
keep it short here. It can invoke simple methods over RMI, and one thing
I think would be very nice to use it for as a next project, is to write
a bruteforcer for jmx. It seems to be pretty simple (the network dump I
looked at while connecting to a JMX console with JConsole showed the
password in plain text - so it seems to not even to be a
challenge-response process). It should also be possible to use the
library to skip the registry-lookup and connect directly to other
stuff, if you know what the application is (and know what object id's
are addressable and how their method signature look) - e.g write another
script to interact with Neo4j or some other RMI based java app.
Files are attached, but also available from
http://martin.swende.se/hgwebdir.cgi/nsescripts/
Forgive me for taking so long to respond to this. I like the script and
library. Here are the results of my testing. I tried running the test
RMI server from
http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html,
but apparently all that is needed is to run the rmiregistry command.
First, here is running against localhost, with the rmiregistry from Java
IcedTea 1.6.0.
Initiating NSE at 12:04
NSE: Starting rmi-dumpregistry against 127.0.0.1:1099.
NSE: RMI:RMI-Ack received (host 127.0.0.1, port: 54010)
NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: RMI:Ignoring responsetype: 77
NSE: RMI:Reading ordinary object
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.MarshalException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.RemoteException"
NSE: RMI:Field description: name: detail, type: Ljava/lang/Throwable;
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.io.IOException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Exception"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Throwable"
NSE: RMI-ERR:Not implemented, readTypeString(TC_REFERENCE)
NSE: RMI:Field description: name: false, type: primitive type: ()
NSE: RMI:Field description: name: L, type: primitive type: (~)
NSE: RMI-ERR:ERROR; not impl: UNKNOWN
NSE: RMI:TC_classdesc is other 100
NSE: Finished rmi-dumpregistry against 127.0.0.1:1099.
Here it is, with a packet trace, running against the rmiregistry that
comes with Debian Etch. From the exception messages that version
detection causes, it appears to be the one from libgcj.
Initiating NSE at 12:10
NSE: Starting rmi-dumpregistry against 192.168.0.2:1099.
NSE: Starting skypev2-version against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 4a 52 4d 49 00 02 4b JRMI K
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | 00000000: 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 30 0d 0a GET / HTTP/1.0
00000010: 0d 0a
NSE: TCP 192.168.0.21:34165 < 192.168.0.2:1099 | 00000000: 4e 00 09 6c 6f 63 61 6c 68 6f 73 74 00 00 04 4b N localhost K
NSE: RMI:RMI-Ack received (host localhost, port: 1099)
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 00 09 31 32 37 2e 30 2e 30 2e 31 00 00 00 00 127.0.0.1
NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 50 80 00 00 05 77 22 00 00 00 00 00 00 00 00 00 P w"
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020: 01 44 15 4d c9 d4 e6 3b df D M ;
NSE: Finished rmi-dumpregistry against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CLOSE
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CLOSE
NSE: Finished skypev2-version against 192.168.0.2:1099.
Completed NSE at 12:10, 30.01s elapsed
Nmap scan report for 192.168.0.2
Host is up, received arp-response (0.00032s latency).
Scanned at 2010-08-03 12:08:08 MDT for 163s
PORT STATE SERVICE REASON VERSION
1099/tcp open unknown syn-ack
SF-Port1099-TCP:V=5.35DC18%I=7%D=8/3%Time=4C585B19%P=i686-pc-linux-gnu%r(J
SF:avaRMI,10,"N\0\tlocalhost\0\0\x04K");
Just running the rmiregistry would suffice, however, it would not
produce anything useful since the objective is to dump out the names of
the objects in there. I am not sure about the errors above, but there
are several parts of RMI which are not implemented, also Patrik Karlsson
pointed out to me that I had left the socket timout to 0.5 s (what I use
when developing locally).

My implementation of java deserialization was based on OpenJdk
implementation, and I tried to keep the structure as close to the
original implementation as possible. However, the resulting library is
not very beautiful code (the java serialization parts), and it turned
out that Patrik had a java deserialization library "lying around" (which
you may have seen in his latest mail). I will make necessary changes and
change my RMI-library to use that (or a modified version of it) instead,
since it is written in a very nice OO-fashion and is not as messy as the
openjdk based version. Also, I think it is more complete.

After my changes, I will perform testing with the same setup you used also.
Post by David Fifield
Post by Martin Holst Swende
ps. One problem I run into pretty often is that RMI is often not
detected, since different apps tend to open ports on different places.
They are usually only found using --version-all, so it makes it
difficult to run the script. Would it be possible to include the
rmi-payload less restrictively?
If it's limited to a few dozen common ports, we can just enumerate all
of them specifically. If it really varies a lot, and rmiregistry is
really common, then we can reduce the rarity.
It is not rmiregistry I am talking about, specifically, but RMI services
in general. There are loads of rmi services - databases, fat clients,
backup systems, consoles etc, and they are found on a lot of different
ports (the registry are probably just a handful of ports).

It would be interesting to make a test.
1. Scan (-sV) a random port on a random host.
2. Each time an open unidentified port turns out, do "-sV --version-all"
on it.
3. Each time one port goes from unidentified to identified by
--version-all, add a point on the scoreboard for that service-probe (or
service, perhaps).
4. Continue until a list has stabilised - if any services are very much
ahead of the rest, those should get lower rarity.

My guess is that rmi would pop up close to the top. Has anyone done
testing like this?

/Martin
Post by David Fifield
David Fifield
_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://seclists.org/nmap-dev/
David Fifield
2010-08-09 03:05:17 UTC
Permalink
Post by Martin Holst Swende
Post by David Fifield
Forgive me for taking so long to respond to this. I like the script and
library. Here are the results of my testing. I tried running the test
RMI server from
http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html,
but apparently all that is needed is to run the rmiregistry command.
First, here is running against localhost, with the rmiregistry from Java
IcedTea 1.6.0.
Initiating NSE at 12:04
NSE: Starting rmi-dumpregistry against 127.0.0.1:1099.
NSE: RMI:RMI-Ack received (host 127.0.0.1, port: 54010)
NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: RMI:Ignoring responsetype: 77
NSE: RMI:Reading ordinary object
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.MarshalException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.rmi.RemoteException"
NSE: RMI:Field description: name: detail, type: Ljava/lang/Throwable;
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.io.IOException"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Exception"
NSE: RMI:Reading TC_CLASSDESC
NSE: RMI:Classname: "java.lang.Throwable"
NSE: RMI-ERR:Not implemented, readTypeString(TC_REFERENCE)
NSE: RMI:Field description: name: false, type: primitive type: ()
NSE: RMI:Field description: name: L, type: primitive type: (~)
NSE: RMI-ERR:ERROR; not impl: UNKNOWN
NSE: RMI:TC_classdesc is other 100
NSE: Finished rmi-dumpregistry against 127.0.0.1:1099.
Here it is, with a packet trace, running against the rmiregistry that
comes with Debian Etch. From the exception messages that version
detection causes, it appears to be the one from libgcj.
Initiating NSE at 12:10
NSE: Starting rmi-dumpregistry against 192.168.0.2:1099.
NSE: Starting skypev2-version against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CONNECT
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 4a 52 4d 49 00 02 4b JRMI K
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | 00000000: 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 30 0d 0a GET / HTTP/1.0
00000010: 0d 0a
NSE: TCP 192.168.0.21:34165 < 192.168.0.2:1099 | 00000000: 4e 00 09 6c 6f 63 61 6c 68 6f 73 74 00 00 04 4b N localhost K
NSE: RMI:RMI-Ack received (host localhost, port: 1099)
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 00 09 31 32 37 2e 30 2e 30 2e 31 00 00 00 00 127.0.0.1
NSE: RMI:Registry connection OK nil
NSE: RMI:Invoking object 0, hash 44154dc9d4e63bdf, opNum 1, args nil
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | 00000000: 50 80 00 00 05 77 22 00 00 00 00 00 00 00 00 00 P w"
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020: 01 44 15 4d c9 d4 e6 3b df D M ;
NSE: Finished rmi-dumpregistry against 192.168.0.2:1099.
NSE: TCP 192.168.0.21:34165 > 192.168.0.2:1099 | CLOSE
NSE: TCP 192.168.0.21:34166 > 192.168.0.2:1099 | CLOSE
NSE: Finished skypev2-version against 192.168.0.2:1099.
Completed NSE at 12:10, 30.01s elapsed
Nmap scan report for 192.168.0.2
Host is up, received arp-response (0.00032s latency).
Scanned at 2010-08-03 12:08:08 MDT for 163s
PORT STATE SERVICE REASON VERSION
1099/tcp open unknown syn-ack
SF-Port1099-TCP:V=5.35DC18%I=7%D=8/3%Time=4C585B19%P=i686-pc-linux-gnu%r(J
SF:avaRMI,10,"N\0\tlocalhost\0\0\x04K");
Just running the rmiregistry would suffice, however, it would not
produce anything useful since the objective is to dump out the names of
the objects in there. I am not sure about the errors above, but there
are several parts of RMI which are not implemented, also Patrik Karlsson
pointed out to me that I had left the socket timout to 0.5 s (what I use
when developing locally).
My implementation of java deserialization was based on OpenJdk
implementation, and I tried to keep the structure as close to the
original implementation as possible. However, the resulting library is
not very beautiful code (the java serialization parts), and it turned
out that Patrik had a java deserialization library "lying around" (which
you may have seen in his latest mail). I will make necessary changes and
change my RMI-library to use that (or a modified version of it) instead,
since it is written in a very nice OO-fashion and is not as messy as the
openjdk based version. Also, I think it is more complete.
After my changes, I will perform testing with the same setup you used also.
Okay, I will consider this deferred until you test with Patrik's library
(and I catch up with all of Patrik's submissions).
Post by Martin Holst Swende
Post by David Fifield
Post by Martin Holst Swende
ps. One problem I run into pretty often is that RMI is often not
detected, since different apps tend to open ports on different places.
They are usually only found using --version-all, so it makes it
difficult to run the script. Would it be possible to include the
rmi-payload less restrictively?
If it's limited to a few dozen common ports, we can just enumerate all
of them specifically. If it really varies a lot, and rmiregistry is
really common, then we can reduce the rarity.
It is not rmiregistry I am talking about, specifically, but RMI services
in general. There are loads of rmi services - databases, fat clients,
backup systems, consoles etc, and they are found on a lot of different
ports (the registry are probably just a handful of ports).
It would be interesting to make a test.
1. Scan (-sV) a random port on a random host.
2. Each time an open unidentified port turns out, do "-sV --version-all"
on it.
3. Each time one port goes from unidentified to identified by
--version-all, add a point on the scoreboard for that service-probe (or
service, perhaps).
4. Continue until a list has stabilised - if any services are very much
ahead of the rest, those should get lower rarity.
My guess is that rmi would pop up close to the top. Has anyone done
testing like this?
I'm not aware of any test like this. Perhaps we should reduce the rarity
of the JavaRMI probe, which is currently at 8. Making it 7 or lower
would cause it to run by default. Even with that, it would help to make
a larger list of common RMI ports, so that the RMI probe can be
prioritized for them. Right now we only have the ports

ports 706,1098,1099,1981

David Fifield
Martin Holst Swende
2010-09-30 21:42:31 UTC
Permalink
Hi list,

I have now rewritten and expanded large parts of the rmi registry
dumper. I took some inspiration from Patriks OO-approach to java
classes/fields, but most of the codebase is still based on the OpenJDK
implementation. Some additions that have been made
- Better protocol support, now parses out the ip:port to the actual objects
- Catches 'custom data' , which actually discloses the classpath in some
cases
- Tested a lot against rmi registrys I found out on the series of tubes

This script could do with some more polishing, but that's mostly
documentation and decreasing verbosity. I think it is robust enough for
testing, and for that reason I let the output be pretty verbose, so I
can interpret any errors that occurs. In the final version, some of the
debugging-info should be removed.

Scripts are attached, but the latest can also be cloned or downloaded
from http://martin.swende.se/hgwebdir.cgi/nsescripts/

Some example outputs below.

Example output against a jmx-enable application:


PORT STATE SERVICE REASON
1099/tcp open rmi syn-ack
| rmi-dumpregistry:
| jmxrmi
| javax.management.remote.rmi.RMIServerImpl_Stub
| @127.0.1.1:40353
| extends
| java.rmi.server.RemoteStub
| extends
|_ java.rmi.server.RemoteObject


Example output against a 'proprietary' java app using rmi for distribution:
PORT STATE SERVICE REASON
1099/tcp open rmi syn-ack
| rmi-dumpregistry:
| secretobject
| implements java.rmi.Remote, VulnerableServerIF,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:59119
| extends
| java.rmi.server.RemoteObject
| mrtickle
| implements java.rmi.Remote, VulnerableServerIF,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:59119
| extends
| java.rmi.server.RemoteObject
| HiddenObject
| implements java.rmi.Remote, VulnerableServerIF,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:59119
| extends
|_ java.rmi.server.RemoteObject
Final times for host: srtt: 63 rttvar: 2829 to:

And finally, an anonymized output of a coldfusion-application I found on
the net, which discloses the classpath:

@output
PORT STATE SERVICE REASON
1099/tcp open rmi syn-ack
| rmi-dumpregistry:
| cfassembler/default
| coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
| @192.168.15.55:1371
| extends
| java.rmi.server.RemoteStub
| extends
| java.rmi.server.RemoteObject
| Custom data
| Classpath
| file:/C:/CFusionMX7/runtime/../lib/ant-launcher.jar
| file:/C:/CFusionMX7/runtime/../lib/ant.jar
| file:/C:/CFusionMX7/runtime/../lib/axis.jar
| file:/C:/CFusionMX7/runtime/../lib/backport-util-concurrent.jar
| file:/C:/CFusionMX7/runtime/../lib/bcel.jar
| file:/C:/CFusionMX7/runtime/../lib/cdo.jar
| file:/C:/CFusionMX7/runtime/../lib/cdohost.jar
| file:/C:/CFusionMX7/runtime/../lib/cf4was.jar
| file:/C:/CFusionMX7/runtime/../lib/cf4was_ae.jar
| file:/C:/CFusionMX7/runtime/../lib/cfmx-ssl.jar
| file:/C:/CFusionMX7/runtime/../lib/cfusion.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-beanutils-1.5.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-collections-2.1.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-digester-1.3.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-digester-1.7.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-discovery-0.2.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-discovery.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-logging-1.0.2.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-logging-api-1.0.2.jar
| file:/C:/CFusionMX7/runtime/../lib/commons-net-1.2.2.jar
| file:/C:/CFusionMX7/runtime/../lib/crystal.jar
| file:/C:/CFusionMX7/runtime/../lib/flashgateway.jar
| file:/C:/CFusionMX7/runtime/../lib/flashremoting_update.jar
| file:/C:/CFusionMX7/runtime/../lib/flex-assemblerservice.jar
| file:/C:/CFusionMX7/runtime/../lib/flex-messaging-common.jar
| file:/C:/CFusionMX7/runtime/../lib/flex-messaging-opt.jar
| file:/C:/CFusionMX7/runtime/../lib/flex-messaging-req.jar
| file:/C:/CFusionMX7/runtime/../lib/flex-messaging.jar
| file:/C:/CFusionMX7/runtime/../lib/httpclient.jar
| file:/C:/CFusionMX7/runtime/../lib/ib61patch.jar
| file:/C:/CFusionMX7/runtime/../lib/ib6addonpatch.jar
| file:/C:/CFusionMX7/runtime/../lib/ib6core.jar
| file:/C:/CFusionMX7/runtime/../lib/ib6swing.jar
| file:/C:/CFusionMX7/runtime/../lib/ib6util.jar
| file:/C:/CFusionMX7/runtime/../lib/im.jar
| file:/C:/CFusionMX7/runtime/../lib/iText.jar
| file:/C:/CFusionMX7/runtime/../lib/iTextAsian.jar
| file:/C:/CFusionMX7/runtime/../lib/izmado.jar
| file:/C:/CFusionMX7/runtime/../lib/jakarta-oro-2.0.6.jar
| file:/C:/CFusionMX7/runtime/../lib/java2wsdl.jar
| file:/C:/CFusionMX7/runtime/../lib/jaxrpc.jar
| file:/C:/CFusionMX7/runtime/../lib/jdom.jar
| file:/C:/CFusionMX7/runtime/../lib/jeb.jar
| file:/C:/CFusionMX7/runtime/../lib/jintegra.jar
| file:/C:/CFusionMX7/runtime/../lib/ldap.jar
| file:/C:/CFusionMX7/runtime/../lib/ldapbp.jar
| file:/C:/CFusionMX7/runtime/../lib/log4j.jar
| file:/C:/CFusionMX7/runtime/../lib/macromedia_drivers.jar
| file:/C:/CFusionMX7/runtime/../lib/mail.jar
| file:/C:/CFusionMX7/runtime/../lib/msapps.jar
| file:/C:/CFusionMX7/runtime/../lib/pbclient42RE.jar
| file:/C:/CFusionMX7/runtime/../lib/pbembedded42RE.jar
| file:/C:/CFusionMX7/runtime/../lib/pbserver42RE.jar
| file:/C:/CFusionMX7/runtime/../lib/pbtools42RE.jar
| file:/C:/CFusionMX7/runtime/../lib/poi-2.5.1-final-20040804.jar
|
file:/C:/CFusionMX7/runtime/../lib/poi-contrib-2.5.1-final-20040804.jar
| file:/C:/CFusionMX7/runtime/../lib/ri_generic.jar
| file:/C:/CFusionMX7/runtime/../lib/saaj.jar
| file:/C:/CFusionMX7/runtime/../lib/smack.jar
| file:/C:/CFusionMX7/runtime/../lib/smpp.jar
| file:/C:/CFusionMX7/runtime/../lib/STComm.jar
| file:/C:/CFusionMX7/runtime/../lib/tools.jar
| file:/C:/CFusionMX7/runtime/../lib/tt-bytecode.jar
| file:/C:/CFusionMX7/runtime/../lib/vadmin.jar
| file:/C:/CFusionMX7/runtime/../lib/verity.jar
| file:/C:/CFusionMX7/runtime/../lib/vparametric.jar
| file:/C:/CFusionMX7/runtime/../lib/vsearch.jar
| file:/C:/CFusionMX7/runtime/../lib/wc50.jar
| file:/C:/CFusionMX7/runtime/../lib/webchartsJava2D.jar
| file:/C:/CFusionMX7/runtime/../lib/wsdl2java.jar
| file:/C:/CFusionMX7/runtime/../lib/wsdl4j-1.5.1.jar
| file:/C:/CFusionMX7/runtime/../lib/wsdl4j.jar
| file:/C:/CFusionMX7/runtime/../lib/xalan.jar
| file:/C:/CFusionMX7/runtime/../lib/xercesImpl.jar
| file:/C:/CFusionMX7/runtime/../lib/xml-apis.jar
| file:/C:/CFusionMX7/runtime/../lib/
| file:/C:/CFusionMX7/runtime/../gateway/lib/examples.jar
| file:/C:/CFusionMX7/runtime/../gateway/lib/
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/batik-awt-util.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/batik-css.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/batik-ext.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/batik-transcoder.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/batik-util.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/commons-discovery.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/commons-logging.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/concurrent.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/flex.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/jakarta-oro-2.0.7.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/jcert.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/jnet.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/jsse.jar
|
file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/oscache.jar
|_ file:/C:/CFusionMX7/runtime/../wwwroot/WEB-INF/cfform/jars/



Regards,
Martin
David Fifield
2010-11-01 20:52:02 UTC
Permalink
Post by Martin Holst Swende
Hi list,
I have now rewritten and expanded large parts of the rmi registry
dumper. I took some inspiration from Patriks OO-approach to java
classes/fields, but most of the codebase is still based on the OpenJDK
implementation. Some additions that have been made
- Better protocol support, now parses out the ip:port to the actual objects
- Catches 'custom data' , which actually discloses the classpath in some
cases
- Tested a lot against rmi registrys I found out on the series of tubes
This script could do with some more polishing, but that's mostly
documentation and decreasing verbosity. I think it is robust enough for
testing, and for that reason I let the output be pretty verbose, so I
can interpret any errors that occurs. In the final version, some of the
debugging-info should be removed.
Scripts are attached, but the latest can also be cloned or downloaded
from http://martin.swende.se/hgwebdir.cgi/nsescripts/
Sorry again for the delay. I added the library and script using the
files from your branch.

David Fifield
Martin Holst Swende
2010-11-02 14:42:24 UTC
Permalink
Post by David Fifield
Post by Martin Holst Swende
Hi list,
I have now rewritten and expanded large parts of the rmi registry
dumper. I took some inspiration from Patriks OO-approach to java
classes/fields, but most of the codebase is still based on the OpenJDK
implementation. Some additions that have been made
- Better protocol support, now parses out the ip:port to the actual objects
- Catches 'custom data' , which actually discloses the classpath in some
cases
- Tested a lot against rmi registrys I found out on the series of tubes
This script could do with some more polishing, but that's mostly
documentation and decreasing verbosity. I think it is robust enough for
testing, and for that reason I let the output be pretty verbose, so I
can interpret any errors that occurs. In the final version, some of the
debugging-info should be removed.
Scripts are attached, but the latest can also be cloned or downloaded
from http://martin.swende.se/hgwebdir.cgi/nsescripts/
Sorry again for the delay. I added the library and script using the
files from your branch.
David Fifield
No problem about the delays, I know you have a lot++ things to deal
with, and that rmi-stuff was pretty large. Is it committed already? I am
going to perform some changes and decrease the default verbosity, but
that should be pretty minimal changes and easy to review.

Also, regarding rmi - I mentioned earlier that rmi seems go undetected
pretty often; here's the reason:
* The RMI registry usually sits on a few ports, e.g 1099 and 1098.
* RMI objects,(which are typically found when querying the registry) are
located on pretty random ports, whatever the runtime chooses. That's why
the registry is needed, so other apps can lookup where they are (the
dumpregistry-script lists the host and port for each object)

Therefore, the currently defined ports in the service fingerprints
definition do a pretty good job at finding rmi registrys, but usually
misses to fingerprint other rmi services (remote objects). So, I would
suggest sending the rmi-probe more often. But I have no hard data to
about how common this is.

Also, if dumping the registry discovers that some objects in this
application are distributed to other hosts, perhaps adding these newly
discovered hosts to the list of targets would be nice? Or is that
something that should only be done by a pre-rule-"discovery"-script?
Right now, nothing about these potential new hosts/ports is stored so
other scripts can access the information.

Regards,
/Martin
David Fifield
2010-11-02 18:02:14 UTC
Permalink
Post by Martin Holst Swende
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
No problem about the delays, I know you have a lot++ things to deal
with, and that rmi-stuff was pretty large. Is it committed already? I am
going to perform some changes and decrease the default verbosity, but
that should be pretty minimal changes and easy to review.
Just tell me when you've updated your branch and I'll pull in the
changes.
Post by Martin Holst Swende
Also, regarding rmi - I mentioned earlier that rmi seems go undetected
* The RMI registry usually sits on a few ports, e.g 1099 and 1098.
* RMI objects,(which are typically found when querying the registry) are
located on pretty random ports, whatever the runtime chooses. That's why
the registry is needed, so other apps can lookup where they are (the
dumpregistry-script lists the host and port for each object)
Therefore, the currently defined ports in the service fingerprints
definition do a pretty good job at finding rmi registrys, but usually
misses to fingerprint other rmi services (remote objects). So, I would
suggest sending the rmi-probe more often. But I have no hard data to
about how common this is.
You said you tested this script on the Internet. Do you still have the
logs? If so, send a table of the ports listed by rmiregistry, sorted by
number of occurrences. That way we can see if the ports are more or less
uniformly distributed. We can also compare against the frequencies in
nmap-services to judge how common Java RMI is compared to other
services.

Also, I believe it's possible to set version information for ports other
than the one being script scanned. rmi-dumpregistry could set the
version for the other ports as if they had been version probed.
Post by Martin Holst Swende
Also, if dumping the registry discovers that some objects in this
application are distributed to other hosts, perhaps adding these newly
discovered hosts to the list of targets would be nice? Or is that
something that should only be done by a pre-rule-"discovery"-script?
Right now, nothing about these potential new hosts/ports is stored so
other scripts can access the information.
It doesn't work as a prerule script, because prerules don't have any
host or port information to work with. (It wouldn't know where the
rmiregistries are.) But it could be added to rmi-dumpregistry, sure.

David Fifield
Patrick Donnelly
2010-11-02 23:37:48 UTC
Permalink
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
There is a minor problem with the rmi library:

***@batbytes:~/nmap/svn/nmap$ ./nse_check_globals
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]

I fixed peekUnpack but don't know what to do with the second one, 'p'.
--
- Patrick Donnelly
Patrick Donnelly
2010-11-17 12:43:13 UTC
Permalink
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
       Found indexed global,'peekUnpack', at line number 198.
       Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
--
- Patrick Donnelly
Martin Holst Swende
2010-11-17 12:54:37 UTC
Permalink
Post by Patrick Donnelly
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
Poke taken :)
Sorry for the delay, will try do get some NSE-work done this weekend.
/Martin
Martin Holst Swende
2010-11-21 20:02:18 UTC
Permalink
Post by Martin Holst Swende
Post by Patrick Donnelly
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
Poke taken :)
Sorry for the delay, will try do get some NSE-work done this weekend.
/Martin
I have now made some changes to rmi-dumpregistry, so that the small bugs
with global accesses are fixed, the verbosity is
lessened and I have made some changes to the documentation - which was
not previously done according to nse-practices of triple-dash "---". There
should be a whole lot more that is shown on the nsedoc portal now.

Changes can be fetched from http://martin.swende.se/hg/nsescripts
Regards,
Martin Holst Swende
David Fifield
2010-11-22 23:23:38 UTC
Permalink
Post by Martin Holst Swende
Post by Martin Holst Swende
Post by Patrick Donnelly
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
Poke taken :)
Sorry for the delay, will try do get some NSE-work done this weekend.
/Martin
I have now made some changes to rmi-dumpregistry, so that the small bugs
with global accesses are fixed, the verbosity is
lessened and I have made some changes to the documentation - which was
not previously done according to nse-practices of triple-dash "---". There
should be a whole lot more that is shown on the nsedoc portal now.
Changes can be fetched from http://martin.swende.se/hg/nsescripts
I think your hg branch is missing some revisions from the SVN trunk.
Anyway if I try to merge the changes they don't apply cleanly:

$ hg diff -r 47:49 ~/branches/nsescripts | patch -p1
patching file nselib/rmi.lua
Hunk #7 FAILED at 177.
Hunk #8 FAILED at 229.
2 out of 33 hunks FAILED -- saving rejects to file nselib/rmi.lua.rej
patching file scripts/rmi-dumpregistry.nse
Hunk #1 FAILED at 1.
Hunk #2 succeeded at 29 (offset 3 lines).
Hunk #3 FAILED at 136.
2 out of 4 hunks FAILED -- saving rejects to file scripts/rmi-dumpregistry.nse.rej

I tried using hgsubversion to merge the changes but I couldn't find a
way to do it because the branches are unrelated.

Please incorporate the changes that have happened since the RMI code was
added and then I'll merge your changes.

David Fifield
Martin Holst Swende
2010-11-23 07:54:27 UTC
Permalink
Post by David Fifield
Post by Martin Holst Swende
Post by Martin Holst Swende
Post by Patrick Donnelly
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
Poke taken :)
Sorry for the delay, will try do get some NSE-work done this weekend.
/Martin
I have now made some changes to rmi-dumpregistry, so that the small bugs
with global accesses are fixed, the verbosity is
lessened and I have made some changes to the documentation - which was
not previously done according to nse-practices of triple-dash "---". There
should be a whole lot more that is shown on the nsedoc portal now.
Changes can be fetched from http://martin.swende.se/hg/nsescripts
I think your hg branch is missing some revisions from the SVN trunk.
$ hg diff -r 47:49 ~/branches/nsescripts | patch -p1
patching file nselib/rmi.lua
Hunk #7 FAILED at 177.
Hunk #8 FAILED at 229.
2 out of 33 hunks FAILED -- saving rejects to file nselib/rmi.lua.rej
patching file scripts/rmi-dumpregistry.nse
Hunk #1 FAILED at 1.
Hunk #2 succeeded at 29 (offset 3 lines).
Hunk #3 FAILED at 136.
2 out of 4 hunks FAILED -- saving rejects to file scripts/rmi-dumpregistry.nse.rej
I tried using hgsubversion to merge the changes but I couldn't find a
way to do it because the branches are unrelated.
Please incorporate the changes that have happened since the RMI code was
added and then I'll merge your changes.
David Fifield
I updated my nmap installation from the 5.36TEST2-source, so any changes
there are included (there was a e.g. a category-addition and your
global-access fix in the library). With hindsight, of course I should
have imported those, and then made a commit, so it would have been
easier for you to follow. Do you want me to import the changes in a
branch at rev 47 and merge with the current head?
Regards,
Martin
David Fifield
2010-11-23 17:49:02 UTC
Permalink
Post by Martin Holst Swende
Post by David Fifield
Post by Martin Holst Swende
Post by Martin Holst Swende
Post by Patrick Donnelly
Post by Patrick Donnelly
Post by David Fifield
Sorry again for the delay. I added the library and script using the
files from your branch.
[...]
Checking nselib/rmi.lua for bad global accesses
Found indexed global,'peekUnpack', at line number 198.
Found indexed global,'p', at line number 1179.
[...]
I fixed peekUnpack but don't know what to do with the second one, 'p'.
Poking this thread since this problem still exists.
Poke taken :)
Sorry for the delay, will try do get some NSE-work done this weekend.
/Martin
I have now made some changes to rmi-dumpregistry, so that the small bugs
with global accesses are fixed, the verbosity is
lessened and I have made some changes to the documentation - which was
not previously done according to nse-practices of triple-dash "---". There
should be a whole lot more that is shown on the nsedoc portal now.
Changes can be fetched from http://martin.swende.se/hg/nsescripts
I think your hg branch is missing some revisions from the SVN trunk.
$ hg diff -r 47:49 ~/branches/nsescripts | patch -p1
patching file nselib/rmi.lua
Hunk #7 FAILED at 177.
Hunk #8 FAILED at 229.
2 out of 33 hunks FAILED -- saving rejects to file nselib/rmi.lua.rej
patching file scripts/rmi-dumpregistry.nse
Hunk #1 FAILED at 1.
Hunk #2 succeeded at 29 (offset 3 lines).
Hunk #3 FAILED at 136.
2 out of 4 hunks FAILED -- saving rejects to file scripts/rmi-dumpregistry.nse.rej
I tried using hgsubversion to merge the changes but I couldn't find a
way to do it because the branches are unrelated.
Please incorporate the changes that have happened since the RMI code was
added and then I'll merge your changes.
David Fifield
I updated my nmap installation from the 5.36TEST2-source, so any changes
there are included (there was a e.g. a category-addition and your
global-access fix in the library). With hindsight, of course I should
have imported those, and then made a commit, so it would have been
easier for you to follow. Do you want me to import the changes in a
branch at rev 47 and merge with the current head?
I think I see what you did. Yes, I was confused. I copied the files and
looked at the diffs and everything looked right, so you had already done
what I was asking you to do. I guess your merge from SVN was done as
part of your r48.

I committed the new files.

David Fifield

Loading...