7698881 2001-12-17 13:48 -0800 /443 rader/ Stephan Holtwisch <sh@immutec.com>
Sänt av: joel@lysator.liu.se
Bilagans filnamn: "SA-MAGIC-001-02.txt.asc"
Importerad: 2001-12-19 19:56 av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <20209>
Ärende: MAGIC Enterprise Multiple Vulnerabilities
------------------------------------------------------------
From: Stephan Holtwisch <sh@immutec.com>
To: bugtraq@securityfocus.com
Message-ID: <3C1E6813.50809@immutec.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
immutec Security Advisory
ID: SA-MAGIC-001
Date: 2001/12/17
Version: 0.2
Magic Enterprise multiple vulnerabilities
Affected Software/System:
=========================
Vendor : Magic Software (http://www.magicsoftware.com)
Product : Magic Enterprise Edition
Version : 8.30-5 and prior, 9.x not fully tested
Platform : Solaris, Linux, AIX, HP/UX, SCO, Digital Unix, AS/400, NT
Vulnerability Types:
====================
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.
Vendor Response:
================
Vendor contacted at 11.12.2001 according to 'Full Disclosure Policy
2.0', however we got no appropriate response.
Solution/Fix:
=============
none yet
Contact:
========
immutec GmbH
Mendelstr. 11
48149 Muenster
Germany
info@immutec.com
http://www.immutec.com
Phone: ++49 (0) 251/980-1230
Fax: ++49 (0) 251/980-1231
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.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (IRIX64)
Comment: For info see http://www.gnupg.org
iEYEARECAAYFAjweY2kACgkQhMXODxDcN5JXRQCeK9Zcp0bEXjCtWPJ9Ey+kLt3V
kD8AoJtJYNLDRgjaP2YOO5wCk+G6+Sbl
=5bBe
-----END PGP SIGNATURE-----
(7698881) /Stephan Holtwisch <sh@immutec.com>/(Ombruten)