COMMAND

    Oracle

SYSTEMS AFFECTED

    Oracle 8.03, 8.0.4, 8.0.5, and 8.1.5

PROBLEM

    Dan Sugalski found following.  If you're running Oracle 8.0.5 on a
    Unix box,  do *not*  install and  configure the  Intellegent Agent
    option.  If  you have, find  the bin/oratclsh file  and REMOVE THE
    SUID BIT!  oratclsh is a Tcl app that provides full access to Tcl.
    It's also installed as   suid root. Running oratclsh gives  anyone
    with even  the most  modest Tcl  knowledge the  ability to execute
    arbitrary Tcl commands *while running as root*!  This includes the
    exec command,  which spawns  off a  subshell (as  root) to run any
    command on the system. Anyone  with half a brain is  exactly three
    commands away from full root access.  Anyone with a whole brain is
    exactly *one* command away from full root access.

    This hole has been verified on both Linux and Solaris with  Oracle
    8.0.4|5, DU 8.0.5.1,  8.0.3 on Solaris,  Oracle8i 8.1.5 Solaris  7
    Oracle 8i 8.0.5 on AIX 4.3.1.0 running on a RS/6000 F50, etc.

    While on Linux version of oracle  to 8.0.5.1 the suid bit was  not
    set, and the ownership  of oratclsh was oracle.oracle,  on Digital
    Unix oratclsh  was still  suid root  so at  least on this platform
    8.0.5.1 did not solve the problem.

SOLUTION

    Intellegent Agent only  needs to be  *installed* (and the  root.sh
    part of the setup  run) to open this  hole.  The agent  does *not*
    need to be started--just installed.  This will be fixed in  future
    releases (8.0.6, etc.).  On current releases one should just chown
    the $ORACLE_HOME/bin/oratclsh  to oracle  (or whoever  the install
    userid is); on  Linux and Solaris  that will also  remove the suid
    bit.

    The following patch  was sent from  Oracle regarding the  oratclsh
    setuid vulnerability.   If you're  an Oracle  Metalink member  you
    can get  this patch  off their  website; if  not then  here it is.
    Note that  this removes  oratclsh completely,  and removes  setuid
    bits from a whole bunch of other executables.  This patch will  be
    part of 8.0i (8.1.6) and 8.0 (8.0.6) as next releases.

    #!/bin/sh
    #
    #    NAME
    #       setuid_patch.sh
    #
    #    DESCRIPTION
    #       Provided as a patch to 8.0.X and 8.1.5 to fix bugs 701297, 714293.
    #       These bugs introduce a security hole by changing the permissions
    #       to affect the effective user id for executables which should not
    #       be set this way.
    #
    #    PRECONDITIONS
    #       if ORACLE_HOME is not set, doesn't exist, or points to an
    #       invalid location, script exits.
    #
    #    HOW TO USE
    #       This script must be run as the oracle user who installed the 8.0.3
    #       8.0.4, 8.0.5 or 8.1.5 software.
    #
    #       To run, change directories into the the directory that contains this
    #       file.
    #       % cd <patch_location_directory>
    #
    #       Add execute permission to the patch.
    #       % chmod 744 setuid_patch.sh
    #
    #       Then, invoke the script.
    #       % ./setuid_patch.sh
    #
    #   MODIFIED   (MM/DD/YY)
    #       menash  5/3/99  Initial creation

    ##---------------------
    ## VARIABLE DEFINITIONS

    #-----------------------------
    # potentially platform specific variables

    CHMOD="/bin/chmod"
    FIND="/bin/find"
    CHMOD_S="$CHMOD -s"   # remove set id bit
    RM_F="/bin/rm -f"
    LS_L="/bin/ls -l"
    LS_N="/bin/ls -n"     # gives uid number for owner
    SED="/bin/sed"
    AWK="/bin/awk"
    GREP="/bin/grep"
    GREP_C="$GREP -c"
    GREP_V="$GREP -v"
    MV="/bin/mv"
    TMP_DIR="/tmp"

    EXECS_TO_UNSET="lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO"
    EXECS_NOT_TO_UNSET="oracle dbsnmp"
    EXECS_TO_REMOVE="oratclsh osh"
    LIKELY_SUFFIXES="0 O"
    ROOT_SH_815="$ORACLE_HOME/root.sh"
    ROOT_SH_805="$ORACLE_HOME/orainst/root.sh"


    if [ x${ORACLE_HOME} = x ] -o [ ${ORACLE_HOME} = "" ] ; then
	    echo "ORACLE_HOME is either unset or empty."
	    echo "Exiting ..."
	    exit 1
    fi

    #--------------
    # usage message

    SCRIPTNAME=setuid_patch.sh
    USAGE="Usage: $SCRIPTNAME [-h]"
    if [ $# -gt 1 ] ; then
      echo
      echo $USAGE
      exit 2
    fi


    ##-----------#
    ## FUNCTIONS #
    ##-----------#

    # ----------
    # setuid_off

    # Assumes executable is in $ORACLE_HOME/bin
    #
    # Usage: setuid_off <executable>
    #------------

    setuid_off () {

	    exe=$1
	    full_path_exe=$ORACLE_HOME/bin/$exe
	    if [ -r $full_path_exe ] ; then
	      perm=`$LS_L $full_path_exe | $SED 's;r-.*;;'`
	      if [ $perm = "-rws" ] ; then
		 $CHMOD_S $full_path_exe
		 echo "  removing set-ID from $full_path_exe"
	      fi
	    fi
    }

    #-----------
    # remove_exe
    # Assumes executable is in $ORACLE_HOME/bin
    # Removes if owned by root, otherwise, calls setuid_off

    # Usage: remove_exe <executable>
    remove_exe () {

	    full_path_exe=$ORACLE_HOME/bin/$1
	    if [ -r $full_path_exe ] ; then
	      owner=`$LS_N $full_path_exe | $AWK '{print $3}'`
	      if [ $owner = "0" ] ; then
		 $RM_F $full_path_exe
		 echo "   removing $full_path_exe..."
	      else
		 setuid_off $1
	      fi
	    fi
    }

    #-----------
    # search_for_others
    #
    # Finds other executables n $ORACLE_HOME/bin which have 4000, 6000,
    # or 2000 permissions except for those we expects, and warns the
    # us er that they should be removed manually

    # Usage: search_for_others

    search_for_others () {

	    all_others="`$FIND $ORACLE_HOME/bin -perm -2000`"
	    others=""
	    if [ x"${all_others}" != x ] ; then
	      for other in $all_others; do
		 match="false"
		 for exe in $EXECS_NOT_TO_UNSET; do
		     if [ $other = $ORACLE_HOME/bin/$exe ] ; then
			match="true"
		     fi
		 done
		 if [ $match = "false" ] ; then
		     others="$others $other"
		 fi
	      done
	      if [ x"${others}" != x ] ; then
		 echo "The following executables remain with set-ID."
		 echo "You may need to change the permissions manually:"
		 for executable in $others; do
		     echo "  $executable"
		 done
	      fi
	    fi

    }

    #--------
    # remove_from_root_sh

    # For each parameter it is passed, remove_from_root_sh removes all
    # lines with references to that string.

    # Usage: remove_from_root_sh [ string1, string2, etc. ]

    remove_from_root_sh () {

	    strings=$*
	    tmp_file="root.sh.$$"
	    $RM_F $TMP_DIR/$tmp_file
	    for string in $strings; do
	      if [ `$GREP_C $string $ROOT_SH` != "0" ] ; then
		echo "  removing $string from $ROOT_SH"
	      fi
	      $GREP_V $string $ROOT_SH > $TMP_DIR/$tmp_file
	      $MV $TMP_DIR/$tmp_file $ROOT_SH
	    done

    }

    ################
    # MAIN EXECUTION
    ################

    # Turn setuid bit off for the appropriate executables and their
    # likely backups

    for exe in $EXECS_TO_UNSET; do
	setuid_off $exe
	for suf in $LIKELY_SUFFIXES; do
	    setuid_off $exe$suf
	done
    done

    # Remove files entirely which should be removed

    for exe in $EXECS_TO_REMOVE; do
	remove_exe $exe
    done

    # Determine version -- 8.0.5 or 8.1.5
    # Backup existing root.sh into root.sh.old, removing references
    # to EXECS_TO_REMOVE
    if [ -r $ROOT_SH_805 ] ; then
	ROOT_SH=$ROOT_SH_805
    else
	if [ -r $ROOT_SH_815 ] ; then
	    ROOT_SH=$ROOT_SH_815
	else
	    echo "No root.sh found in $ORACLE_HOME"
	fi
    fi

    if [ x${ROOT_SH} != x ] ; then
	remove_from_root_sh $EXECS_TO_REMOVE
    fi

    # Check one last time to see if any setuid executables are left

    search_for_others