TUCoPS :: Web :: General :: web4937.htm

Magic Enterprise multiple vulnerabilities
19th Dec 2001 [SBWID-4937]
COMMAND

	Magic Enterprise multiple vulnerabilities

SYSTEMS AFFECTED

	Magic Enterprise Edition 8.30-5 and prior, 9.x not fully tested

PROBLEM

	In immutec Security Advisory SA-MAGIC-001, multiple vulnerabilities  are
	explained about Magic Enterprise Edition :
	 Memory Corruption       : remote/local

	 Shell Command Execution : local

	 Temporary File Handling : local

	 Insecure Permissions    : local (filesystem)

	

	 Product Description:

	 ====================

	

	The Magic Enterprise Edition Version 8  is  a  multi-platform,  flexible
	application  which  supports  well  known  web  browsers,  web  servers,
	application servers and  databases.  Magic  v8  gives  a  developer  the
	ability  to  create  portable  and  scalable   client-/server-based   or
	web-based applications.
	

	Magic is used by important eCommerce sites, payment systems, banks,  big
	automobile companies and even on government servers.
	

	

	 Vulnerability Description:

	 ==========================

	

	Serveral security holes were found in Magic Enterprise  Edition  Version
	8 (Solaris) while doing a penetration test  for  a  customer.  In  depth
	analysis was performed for the Linux version. Version 9  was  not  fully
	tested, but at least some issues were also verified for Version 9.
	

	  a.)  Memory Corruption: remote

	

	The CGI executable \'mgrqcgi\' is used as a kind of  gateway  to  handle
	different tasks.
	  

	mgrqcgi reads different  variables  from  the  QUERY_STRING  environment
	variable, which is set by the HTTP server.
	

	The names of the variables:
	

	    + APPNAME

	    + PRGNAME

	    + ARGUMENTS

	    + PageID

	    + mgaction

	    + H_ShopID

	    + H_SID

	    + H_WID

	    + H_INF

	    + and much more

	

	

	The variable data is copied into local  variables  using  the  non-bound
	checking library function strcpy(3). This  can  be  easily  verified  by
	triggering the overflow using a standart web  browser.  Overwriting  the
	memory for APPNAME bytewise results in overwriting PRGNAME  input  until
	an internal server error occurs.
	

	Attached ltrace output (comments included in []):
	

	

	    [...]

	 

	    17:00:03.769509 [08049794] getenv(\"REQUEST_METHOD\") = \"GET\"

	    17:00:03.769680 [080497ae] strcmp(\"GET\", \"POST\")  = -9

	    17:00:03.769817 [080497ce] strcmp(\"GET\", \"GET\")   = 0

	

	

	    [QUERY_STRING read and splitted up]

	

	    17:00:03.769942 [08049915] getenv(\"QUERY_STRING\") =

	    \"APPNAME=test&PRGNAME=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAA\"

	    17:00:03.770687 [08049b81] strchr(\"APPNAME=test&PRGNAME=AAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"

	    ,\'=\') = \"=test&PRGNAME=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAA\"

	    17:00:03.772443 [08049bb7] strchr(\"test&PRGNAME=AAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",

	    \'&\') = \"&PRGNAME=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAA\"

	    17:00:03.773713 [08049df3] malloc(8)              = 0x08077458

	    17:00:03.773811 [08049d30] realloc(NULL, 8)       = 0x08077468

	    17:00:03.773929 [08049df3] malloc(6)              = 0x08077478

	

	

	    [variable name seperated from variable data]

	

	    17:00:03.774025 [08049b81] strchr(\"PRGNAME=AAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",

	    \'=\') = \"=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AA\"

	    17:00:03.776353 [08049bb7] strchr(\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAA\",

	    \'&\') = NULL

	    17:00:03.777015 [08049bf0] strlen(0xbffffa2a, 0x080498f8, 0x40014ce4,

	    0x08077458, 0x080613d8) = 200

	    17:00:03.777157 [08049df3] malloc(8)              = 0x08077488

	    17:00:03.777253 [08049d30] realloc(0x08077468, 16) = 0x08077498

	    17:00:03.777974 [08049df3] malloc(202)            = 0x080774b0

	    17:00:03.778077 [0804acdf] malloc(32)             = 0x08077580

	    17:00:03.778191 [0804acf4] memset(0x08077580, \'\\000\', 32) = 0x08077580

	

	

	    [variable name made upper case]

	

	    17:00:03.778302 [0804dcec] toupper(\'A\')           = \'A\'

	    17:00:03.778413 [0804dcfd] toupper(\'C\')           = \'C\'

	    17:00:03.778521 [0804dd1c] toupper(\'A\')           = \'A\'

	    17:00:03.778785 [0804dd2d] toupper(\'C\')           = \'C\'

	    17:00:03.778892 [0804dcec] toupper(\'A\')           = \'A\'

	    17:00:03.778999 [0804dcfd] toupper(\'A\')           = \'A\'

	    17:00:03.779107 [0804dcec] toupper(\'P\')           = \'P\'

	    17:00:03.779213 [0804dcfd] toupper(\'P\')           = \'P\'

	    17:00:03.779320 [0804dcec] toupper(\'P\')           = \'P\'

	    17:00:03.779427 [0804dcfd] toupper(\'P\')           = \'P\'

	    17:00:03.779534 [0804dcec] toupper(\'N\')           = \'N\'

	    17:00:03.779641 [0804dcfd] toupper(\'N\')           = \'N\'

	    17:00:03.779748 [0804dcec] toupper(\'A\')           = \'A\'

	    17:00:03.779854 [0804dcfd] toupper(\'A\')           = \'A\'

	    17:00:03.779962 [0804dcec] toupper(\'M\')           = \'M\'

	    17:00:03.780068 [0804dcfd] toupper(\'M\')           = \'M\'

	    17:00:03.780175 [0804dcec] toupper(\'E\')           = \'E\'

	    17:00:03.780300 [0804dcfd] toupper(\'E\')           = \'E\'

	    17:00:03.780408 [0804dd1c] toupper(\'\\000\')        = \'\\000\'

	    17:00:03.780517 [0804dd2d] toupper(\'\\000\')        = \'\\000\'

	

	

	    [APPNAME content copied into stack memory WITHOUT length checking]

	

	    17:00:03.780626 [0804ae56] strcpy(0xbfffee68, \"test\") = 0xbfffee68

	

	

	    [variable name to upper case]

	

	    17:00:03.835647 [0804dcec] toupper(\'P\')           = \'P\'

	    17:00:03.835828 [0804dcfd] toupper(\'C\')           = \'C\'

	    17:00:03.835936 [0804dd1c] toupper(\'P\')           = \'P\'

	    17:00:03.836043 [0804dd2d] toupper(\'C\')           = \'C\'

	    17:00:03.836150 [0804dcec] toupper(\'P\')           = \'P\'

	    17:00:03.836257 [0804dcfd] toupper(\'P\')           = \'P\'

	    17:00:03.836364 [0804dcec] toupper(\'R\')           = \'R\'

	    17:00:03.836471 [0804dcfd] toupper(\'R\')           = \'R\'

	    17:00:03.836577 [0804dcec] toupper(\'G\')           = \'G\'

	    17:00:03.836684 [0804dcfd] toupper(\'G\')           = \'G\'

	    17:00:03.837645 [0804dcec] toupper(\'N\')           = \'N\'

	    17:00:03.837766 [0804dcfd] toupper(\'N\')           = \'N\'

	    17:00:03.837873 [0804dcec] toupper(\'A\')           = \'A\'

	    17:00:03.837980 [0804dcfd] toupper(\'A\')           = \'A\'

	    17:00:03.838103 [0804dcec] toupper(\'M\')           = \'M\'

	    17:00:03.838210 [0804dcfd] toupper(\'M\')           = \'M\'

	    17:00:03.838317 [0804dcec] toupper(\'E\')           = \'E\'

	    17:00:03.838423 [0804dcfd] toupper(\'E\')           = \'E\'

	    17:00:03.838530 [0804dd1c] toupper(\'\\000\')        = \'\\000\'

	    17:00:03.838639 [0804dd2d] toupper(\'\\000\')        = \'\\000\'

	

	

	    [PRGNAME content copied into stack memory WITHOUT length checking]

	    [BUFFER OVERFLOW triggered here]

	

	    17:00:03.838748 [0804ae70] strcpy(0xbfffee48,

	    \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\")

	    = 0xbfffee48

	

	

	    [segmentation fault occuring]

	

	    17:00:03.839409 [080497f5] getenv(\"HTTP_COOKIE\")  = NULL

	    17:00:03.839545 [08049ac0] getenv(\"REMOTE_ADDR\")  = NULL

	    17:00:03.839687 [0805aff4] memset(0x08076e68, \'\\000\', 120) = 

	    0x08076e68

	    17:00:03.839801 [08053971] strcpy(0x08077334, \"otaku\") = 0x08077334

	    17:00:03.839920 [0804cdb7] malloc(1508)           = 0x080775a8

	    17:00:03.840018 [0804cad0] memcpy(0x080775b0, \"\\001\\001\", 1500) =

	    0x080775b0

	    17:00:03.840160 [08052f00] strlen(0xbfffedc8, 0x08049ab4, 0xbfffee00,

	    0xbfffedc8, 0x080775b0) = 0

	    17:00:03.840308 [08052f5b] strlen(0xbfffed48, 0x08049ab4, 0xbfffee00,

	    0xbfffed48, 0x080775b0) = 0

	    17:00:03.840440 [080519d5] memcpy(0x08076e60, \"\\001\\001\", 1500) =

	    0x08076e60

	    17:00:03.840577 [0804cef0] free(0x080775a8)       = <void>

	    17:00:03.840672 [0804b52c] memset(0xbfffeef8, \'\\000\', 16) = 0xbfffeef8

	    17:00:03.840782 [0804b54c] malloc(200)            = 0x080775a8

	    17:00:03.841364 [0804afe6] --- SIGSEGV (Segmentation fault) ---

	    17:00:03.841890 [ffffffff] +++ killed by SIGSEGV +++

	

	

	

	The GNU Debugger output:
	

	      

	    [...]

	

	    Starting program: /usr/local/httpd/cgi-bin/mgrqcgi

	    (no debugging symbols found)...(no debugging symbols found)...(no

	    debugging symbols found)...

	    (no debugging symbols found)...

	    Program received signal SIGSEGV, Segmentation fault.

	    0x0804b103 in strcpy ()

	    (gdb) info stack

	    #0  0x0804b103 in strcpy ()

	    #1  0x41414141 in ?? ()

	    #2  0x0804a440 in strcpy ()

	    #3  0x08049b18 in strcpy ()

	    #4  0x41414141 in ?? ()

	   

	    [...]

	

	

	Some characters  could  not  be  used  while  overflowing  the  internal
	buffers, because they have other meanings in  the  CGI  context  or  are
	filtered.
	

	Characters that could not be used:
	

	

	    + 0x00

	    + 0x09

	    + 0x0A

	    + 0x0B

	    + 0x0C

	    + 0x0D

	    + 0x20

	    + 0x23

	    + 0x25

	    + 0x26

	

	

	

	  b.) Memory Corruption: local

	

	The Linux RPM comes with one setuid root application:
	

	

	    + /usr/magicadm/servers/mgdispatch

	

	

	There seem to be serveral buffer overflows in the  code  of  mgdispatch.
	One example of missing bounds checking occurs very early in the  program
	code while reading an environment variable  called  MGDISPATCH_LOG.  The
	destination buffer is about 3000 bytes big, so an  attacker  has  enough
	space for stuffing the shellcode in and execute arbitrary commands.
	

	ltrace output:
	 

	

	    [...]

	

	    getenv(\"MGDISPATCH_LOG\")                          =

	    \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"...

	    strcpy(0xbfffd87c, \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"...) = 

	    0xbfffd87c

	    getenv(\"MG_DOS_CLIENTS\" <unfinished ...>

	    --- SIGSEGV (Segmentation fault) ---

	    +++ killed by SIGSEGV +++

	

	

	  The GNU Debugger output::

	

	    

	    [...]

	      

	    (gdb) r 78

	    Starting program: ./mgdispatch 78

	    (no debugging symbols found)...(no debugging symbols found)...

	    (no debugging symbols found)...(no debugging symbols found)...

	    Program received signal SIGSEGV, Segmentation fault.

	    0x4008d63b in getenv () from /lib/libc.so.6

	    (gdb) bt

	    #0  0x4008d63b in getenv () from /lib/libc.so.6

	    #1  0x0804dec8 in strcpy ()

	    #2  0x41414141 in ?? ()

	     

	    [...]

	

	

	

	  c.) Temporary File Handling

	

	Some shell script files included in the Linux RPM (probably  applies  to
	other versions as well) do insecure temporary  file  handling,  allowing
	symlink attacks, replacing information and execution of commands.
	

	This list includes shell script names and the appropriate lines:
	

	

	    + /usr/magicadm/api/mkuserproc:40:tmpfile=/tmp/mg.$$

	    + /usr/magicadm/sbin/mgrnt:42:$AWK -F= \'/^[^#]/ {if (NF > 0) print

	                                  \"export \" $1}\' $MAGIC_HOME/etc/mgenv >

	                                  /tmp/mg$$

	    + /usr/magicadm/sbin/mgrnt:43:. /tmp/mg$$

	    + /usr/magicadm/sbin/mgrnt:44:rm -f /tmp/mg$$

	    + /usr/magicadm/sbin/mgrnt:63:$AWK -F= \'/^[^#]/ {if (NF > 0)

	                                  print \"export \" $1}\' $EnvUserFile > 

	                                  /tmp/mgu$$

	    + /usr/magicadm/sbin/mgrnt:64:. /tmp/mgu$$

	    + /usr/magicadm/sbin/mgrnt:65:rm /tmp/mgu$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:51:$AWK -F= \'/^[^#]/ {if (NF >

	                                             0) print \"export \" $1}\' 

	                                             $MAGIC_HOME/etc/mgenv > 

	                                             /tmp/mg$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:52:. /tmp/mg$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:53:rm -f /tmp/mg$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:75:$AWK -F= \'/^[^#]/

	                                             {if (NF > 0) print \"export 

	                                             \" $1}\' $EnvUserFile > 

	                                             /tmp/mgu$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:76:. /tmp/mgu$$

	    + /usr/magicadm/servers/mgdatasrvr.sc:77:rm /tmp/mgu$$

	

	

	

	  d.) Insecure Permissions

	    

	The RPM  file  installs  some  files  and  directories  group  \'users\'
	writeable. This includes the Magic Admin  home  directory  /usr/magicadm
	(a magicadm account is created in /etc/passwd),  the  license  directory
	and various executables.
	

	The list of group writeable executables:
	  

	

	    + /usr/magicadm/bin/magicrnt

	    + /usr/magicadm/bin/mdinformix

	    + /usr/magicadm/bin/mdmssql

	    + /usr/magicadm/bin/mdoracle

	    + /usr/magicadm/bin/mgcircvr

	    + /usr/magicadm/bin/mgcisam

	    + /usr/magicadm/bin/mginformix

	    + /usr/magicadm/bin/mgmemory

	    + /usr/magicadm/bin/mgoracle

	    + /usr/magicadm/bin/mgtcp

	    + /usr/magicadm/broker/mgrqcmdl

	    + /usr/magicadm/broker/mgrqmrb

	    + /usr/magicadm/cgibin/mgrqcgi

	    + /usr/magicadm/servers/mgdatasrvr

	

	

	This allows an attacker to replace these writeable executeables to  gain
	higher  privileges  and  even  any  other  file   to   exploit   trusted
	information.
	

	

	  e.) Miscellaneous

	    

	The  symbols  that  are  exported  by  the  executables   and   by   the
	Magic-Request API library reveal, that there are even more  insecure  C-
	library functions like system(3), strcpy(3),  strcat(3)  and  sprintf(3)
	and alike.
	

	

	

	

	

	

	

	

	 Authors:

	 ========

	

	  Thomas Biege <tb@immutec.com>

	  Stephan Holtwisch <sh@immutec.com>

	

	

	 Disclaimer:

	 ===========

	

	This advisory does not claim to be complete or  to  be  usable  for  any
	purpose.  Especially  information  on  the  vulnerable  systems  may  be
	inaccurate or wrong. Possible supplied exploit code is not  to  be  used
	for malicious purposes, but for educational purposes only.
	

	

	 Copyrights:

	 ===========

	 

	 Copyright (c) 2001, immutec GmbH

	

	Redistribution without modification is  permitted.  Redistribution  with
	modification is  permitted  if  the  copyright  notice,  disclaimer  and
	authors notice are retained.

SOLUTION

	Nothing yet.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH