| Summary: | FreeBSD's man(1) utility vulnerable to old catman attacks | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Tim J. Robbins <tim> |
| Component: | bin | Assignee: | ru <ru> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.4-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
Tim J. Robbins
2001-12-13 07:30:00 UTC
On Thu, Dec 13, 2001 at 06:13:44PM +1100, Tim J. Robbins wrote: > > The catman system of the man(1) utility included with FreeBSD is > vulnerable to a whole bunch of attacks whereby the catpage's > contents can be controlled by an attacker. Discussions of the > problem: > http://security-archive.merton.ox.ac.uk/security-audit-199908/ > ("SGID man", Solar Designer, Sun Aug 01 1999 .. and followups) > http://security-archive.merton.ox.ac.uk/security-audit-200010/0022.html > (more problems) > > >How-To-Repeat: > There are too many ways to repeat the problem.. here's one: > $ ln -s /usr/share/man/cat1 cat1 > $ mkdir man1 > $ cd man1 > $ cat >ls.1 > oops! modified > ^D > $ cd .. > $ man -M . ls > Formatting page, please wait...Done. > oops! modified > > >Fix: > Remove the suid(!) bit from /usr/bin/man. > Unfortunately, removing SUID bit from man(1) is not possible, because it is used to create new or update obsolete catpages in %manpath%/cat%section% directories which are usually owned by the user ``man'', except private user directories. The below patch doesn't allow man(1) to use its SUID powers when the catpage's directory is accessed via symlink. Index: man.c =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/man/man/man.c,v retrieving revision 1.49 diff -u -p -r1.49 man.c --- man.c 2001/09/06 11:54:28 1.49 +++ man.c 2001/12/13 13:28:42 @@ -23,6 +23,7 @@ #include <sys/param.h> #include <ctype.h> #include <errno.h> +#include <libgen.h> #ifdef __FreeBSD__ #include <locale.h> #include <langinfo.h> @@ -1402,19 +1403,24 @@ format_and_display (path, man_file, cat_ { #ifdef SETUID - seteuid(euid); - found = make_cat_file (path, man_file, cat_file, 1); - seteuid(ruid); - - if (!found) - { - /* Try again as real user - see note below. - By running with - effective group (user) ID == real group (user) ID - except for the call above, I believe the problems - of reading private man pages is avoided. */ - found = make_cat_file (path, man_file, cat_file, 0); - } + char *cat_dir = dirname(cat_file); + struct stat sb; + if (cat_dir != NULL && lstat(cat_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) + { + seteuid(euid); + found = make_cat_file (path, man_file, cat_file, 1); + seteuid(ruid); + + if (!found) + { + /* Try again as real user - see note below. + By running with + effective group (user) ID == real group (user) ID + except for the call above, I believe the problems + of reading private man pages is avoided. */ + found = make_cat_file (path, man_file, cat_file, 0); + } + } #else found = make_cat_file (path, man_file, cat_file, 0); #endif Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age On Thu, Dec 13, 2001 at 06:13:44PM +1100, Tim J. Robbins wrote: > > The catman system of the man(1) utility included with FreeBSD is > vulnerable to a whole bunch of attacks whereby the catpage's > contents can be controlled by an attacker. Discussions of the > problem: > http://security-archive.merton.ox.ac.uk/security-audit-199908/ > ("SGID man", Solar Designer, Sun Aug 01 1999 .. and followups) > http://security-archive.merton.ox.ac.uk/security-audit-200010/0022.html > (more problems) > > >How-To-Repeat: > There are too many ways to repeat the problem.. here's one: > $ ln -s /usr/share/man/cat1 cat1 > $ mkdir man1 > $ cd man1 > $ cat >ls.1 > oops! modified > ^D > $ cd .. > $ man -M . ls > Formatting page, please wait...Done. > oops! modified > > >Fix: > Remove the suid(!) bit from /usr/bin/man. > Unfortunately, removing SUID bit from man(1) is not possible, because it is used to create new or update obsolete catpages in %manpath%/cat%section% directories which are usually owned by the user ``man'', except private user directories. The below patch doesn't allow man(1) to use its SUID powers when the catpage's directory is accessed via symlink. Index: man.c =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/man/man/man.c,v retrieving revision 1.49 diff -u -p -r1.49 man.c --- man.c 2001/09/06 11:54:28 1.49 +++ man.c 2001/12/13 13:28:42 @@ -23,6 +23,7 @@ #include <sys/param.h> #include <ctype.h> #include <errno.h> +#include <libgen.h> #ifdef __FreeBSD__ #include <locale.h> #include <langinfo.h> @@ -1402,19 +1403,24 @@ format_and_display (path, man_file, cat_ { #ifdef SETUID - seteuid(euid); - found = make_cat_file (path, man_file, cat_file, 1); - seteuid(ruid); - - if (!found) - { - /* Try again as real user - see note below. - By running with - effective group (user) ID == real group (user) ID - except for the call above, I believe the problems - of reading private man pages is avoided. */ - found = make_cat_file (path, man_file, cat_file, 0); - } + char *cat_dir = dirname(cat_file); + struct stat sb; + if (cat_dir != NULL && lstat(cat_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) + { + seteuid(euid); + found = make_cat_file (path, man_file, cat_file, 1); + seteuid(ruid); + + if (!found) + { + /* Try again as real user - see note below. + By running with + effective group (user) ID == real group (user) ID + except for the call above, I believe the problems + of reading private man pages is avoided. */ + found = make_cat_file (path, man_file, cat_file, 0); + } + } #else found = make_cat_file (path, man_file, cat_file, 0); #endif Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-security" in the body of the message On Thu, Dec 13, 2001 at 15:38:04 +0200, Ruslan Ermilov wrote: > The below patch doesn't allow man(1) to use its SUID powers > when the catpage's directory is accessed via symlink. It breaks private cat pages (symlink check must not present for them) -- Andrey A. Chernov http://ache.pp.ru/ On Thu, Dec 13, 2001 at 03:38:04PM +0200, Ruslan Ermilov wrote:
> Unfortunately, removing SUID bit from man(1) is not possible,
> because it is used to create new or update obsolete catpages
> in %manpath%/cat%section% directories which are usually owned
> by the user ``man'', except private user directories.
I think that making man sgid man instead of suid man would be a good
idea also; I remember Red Hat Linux used this same man utility in version 6.2
and they had it sgid. If an attacker gained uid man through a flaw in the
utility, they could plant a trojan horse and wait for root to run it.
I'll check out how it's been done in Redhat and see if I can come up
with a patch. I don't think this would break anything.
As for the catman issues, I think it's a flaw in the man utility that
it trusts the user running the command to format the manual pages.
I can't think of a good way to fix it.
Tim
On Thu, Dec 13, 2001 at 07:07:13PM +0300, Andrey A. Chernov wrote: > On Thu, Dec 13, 2001 at 15:38:04 +0200, Ruslan Ermilov wrote: > > > The below patch doesn't allow man(1) to use its SUID powers > > when the catpage's directory is accessed via symlink. > > It breaks private cat pages (symlink check must not present for them) > Oops, right, wrongly placed closing brace: Index: man.c =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/man/man/man.c,v retrieving revision 1.49 diff -u -p -r1.49 man.c --- man.c 2001/09/06 11:54:28 1.49 +++ man.c 2001/12/14 07:57:03 @@ -23,6 +23,7 @@ #include <sys/param.h> #include <ctype.h> #include <errno.h> +#include <libgen.h> #ifdef __FreeBSD__ #include <locale.h> #include <langinfo.h> @@ -1402,10 +1403,15 @@ format_and_display (path, man_file, cat_ { #ifdef SETUID - seteuid(euid); - found = make_cat_file (path, man_file, cat_file, 1); - seteuid(ruid); - + char *cat_dir = dirname(cat_file); + struct stat sb; + if (cat_dir != NULL && lstat(cat_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) + { + seteuid(euid); + found = make_cat_file (path, man_file, cat_file, 1); + seteuid(ruid); + } + if (!found) { /* Try again as real user - see note below. Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age On Thu, Dec 13, 2001 at 07:07:13PM +0300, Andrey A. Chernov wrote: > On Thu, Dec 13, 2001 at 15:38:04 +0200, Ruslan Ermilov wrote: > > > The below patch doesn't allow man(1) to use its SUID powers > > when the catpage's directory is accessed via symlink. > > It breaks private cat pages (symlink check must not present for them) > Oops, right, wrongly placed closing brace: Index: man.c =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/man/man/man.c,v retrieving revision 1.49 diff -u -p -r1.49 man.c --- man.c 2001/09/06 11:54:28 1.49 +++ man.c 2001/12/14 07:57:03 @@ -23,6 +23,7 @@ #include <sys/param.h> #include <ctype.h> #include <errno.h> +#include <libgen.h> #ifdef __FreeBSD__ #include <locale.h> #include <langinfo.h> @@ -1402,10 +1403,15 @@ format_and_display (path, man_file, cat_ { #ifdef SETUID - seteuid(euid); - found = make_cat_file (path, man_file, cat_file, 1); - seteuid(ruid); - + char *cat_dir = dirname(cat_file); + struct stat sb; + if (cat_dir != NULL && lstat(cat_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) + { + seteuid(euid); + found = make_cat_file (path, man_file, cat_file, 1); + seteuid(ruid); + } + if (!found) { /* Try again as real user - see note below. Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-security" in the body of the message On Fri, Dec 14, 2001 at 11:57:55AM +1100, Tim J. Robbins wrote: > On Thu, Dec 13, 2001 at 03:38:04PM +0200, Ruslan Ermilov wrote: > > > Unfortunately, removing SUID bit from man(1) is not possible, > > because it is used to create new or update obsolete catpages > > in %manpath%/cat%section% directories which are usually owned > > by the user ``man'', except private user directories. > > I think that making man sgid man instead of suid man would be a good > idea also; I remember Red Hat Linux used this same man utility in version 6.2 > and they had it sgid. If an attacker gained uid man through a flaw in the > utility, they could plant a trojan horse and wait for root to run it. > > I'll check out how it's been done in Redhat and see if I can come up > with a patch. I don't think this would break anything. > Our man(1) uses its SUID bit only to write to catpages. > As for the catman issues, I think it's a flaw in the man utility that > it trusts the user running the command to format the manual pages. > I can't think of a good way to fix it. > Yeah, having in mind the other breakage, that the user is allowed to supply his own ${GROFF_TMAC_PATH}, I think it would be a good idea to disable this feature of man(1) to create catpages, like it's done in OpenBSD and probably NetBSD. Catpages are optional, and if you have enough disk space, you can set MANBUILDCAT=YES in your /etc/make.conf, and have ``make world'' build and install then for you. Also, we have a ${weekly_catman_enable} feature in periodic.conf(5). Removing catpaging feature of man(1) would allow us to drop its SUIDness completely. If there are no serious objections, I'm volunteering to do this job after a 4.5-RELEASE. Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age On Fri, Dec 14, 2001 at 11:57:55AM +1100, Tim J. Robbins wrote: > On Thu, Dec 13, 2001 at 03:38:04PM +0200, Ruslan Ermilov wrote: > > > Unfortunately, removing SUID bit from man(1) is not possible, > > because it is used to create new or update obsolete catpages > > in %manpath%/cat%section% directories which are usually owned > > by the user ``man'', except private user directories. > > I think that making man sgid man instead of suid man would be a good > idea also; I remember Red Hat Linux used this same man utility in version 6.2 > and they had it sgid. If an attacker gained uid man through a flaw in the > utility, they could plant a trojan horse and wait for root to run it. > > I'll check out how it's been done in Redhat and see if I can come up > with a patch. I don't think this would break anything. > Our man(1) uses its SUID bit only to write to catpages. > As for the catman issues, I think it's a flaw in the man utility that > it trusts the user running the command to format the manual pages. > I can't think of a good way to fix it. > Yeah, having in mind the other breakage, that the user is allowed to supply his own ${GROFF_TMAC_PATH}, I think it would be a good idea to disable this feature of man(1) to create catpages, like it's done in OpenBSD and probably NetBSD. Catpages are optional, and if you have enough disk space, you can set MANBUILDCAT=YES in your /etc/make.conf, and have ``make world'' build and install then for you. Also, we have a ${weekly_catman_enable} feature in periodic.conf(5). Removing catpaging feature of man(1) would allow us to drop its SUIDness completely. If there are no serious objections, I'm volunteering to do this job after a 4.5-RELEASE. Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-security" in the body of the message Responsible Changed From-To: freebsd-bugs->ru I'm working on this. State Changed From-To: open->feedback In FreeBSD 5.0-CURRENT, man(1) is no longer installed setuid ``man''. State Changed From-To: feedback->closed After some years of thinking I decided that trusting the user to save formatted catpages is a misfeature. As such, this PR is closed with SETUID code still in the sources but inactive. |