Greetings. I attempted to submit this once before, both via mail to
perlbug@perl.com and as an article in comp.lang.perl. I haven't
seen a response in either place, nor do I see my item chronicled in
the perl bugs database, so on the off chance that it got lost
somehow, I am submitting it again. Hope this isn't too pesky of
me. I know you're all quite busy and not being paid for any of this,
but I would appreciate at least an acknowledgement of receipt.
Thanks.
***
Brief summary: If you run a perl script while logged in as root,
and the script changes effective uid to something else, perl engages
its tainting mechanism, making everything difficult. Ironically,
the script was changing its uid in an attempt to be more secure and
prevent unintended alteration of protected files.
Here's my original message, describing this in more detail, and the
changes I propose to correct it:
----
I have a script which actually functions as an internet server,
listening on a privleged tcp/ip port. This script is started up at
system boot, and runs as root (actually as root, not under setuid to
root).
Because I want to try and guard against potential hacking attempts
(even though it's _extremely_ unlikely anyone could get this server
to do anything bad), I try and be a good citizen by having the script
change its effective uid to something *less* privileged. It runs in
this state most (99%) of the time; it only runs as root for the few
lines of code needed to establish the socket and bind it to the
privileged port.
This all worked under perl4, or at least under the version of perl4 I
was running (I didn't have the source code for our perl4 installation,
so I don't know what options might have been used to build it). Under
perl5, however, perl detects that, during most of the running of the
software, the real uid and the effective uid are different. It thus
wrongly concludes that I'm running it as a setuid script, and applies
the various "tainting" rules, which result in my inability to do such
mundane things as change directories. Ironically, perl tells me it
can't do this because my script is insecure, when in fact I took extra
steps to make sure the code was *more* secure.
I have fixed this in my version of perl, and I'm wondering if this fix
makes sense for the world or not. I don't see any way this could be a
problem, but then I don't know enough about unix security to be sure
there wouldn't be other side-effects of this. What I have done is
change the code which determines whether tainting is in effect. There
are about six lines scattered throughout the perl5 source that all
read:
tainting |= (euid != uid || egid != gid);
I have changed these to read:
tainting |= (uid && (euid != uid || egid != gid));
which exempts you from tainting if your real uid is actually root.
This lets you set euid (or egid) to something else without prejudice,
if you're doing so to *reduce* your privilege level rather than
increase it.
Does this seem reasonable? If it is, should I send the modified
source code somewhere? Let me know.
----
Footnote: The perl4 version where this worked was 4.036. My perl5
installation is current revision and patch level, 5.001m. Here's
my "myconfig" output:
Summary of my perl5 (patchlevel 1) configuration:
Platform:
osname=svr4, osver=, archname=i386-svr4
uname='unix_sv taz 4.2 1.1.3 i386 386at '
hint=previous
Compiler:
cc='/bin/cc', optimize='-O', ld='/bin/cc'
cppflags='-I/usr/include -I/usr/ucbinclude -DDEBUGGING'
ccflags ='-I/usr/include -I/usr/ucbinclude -DDEBUGGING'
ldflags ='-L/usr/ccs/lib -L/usr/ucblib'
stdchar='unsigned char', d_stdstdio=define, usevfork=false
voidflags=15, castflags=0, d_casti32=define, d_castneg=define
intsize=4, alignbytes=4, usemymalloc=y, randbits=15
Libraries:
so=so
libpth=/lib /usr/lib /usr/ccs/lib /usr/ucblib
libs=-lsocket -lnsl -ldbm -ldl -lld -lm -lc -lcrypt -lucb -lx
libc=/usr/ccs/lib/libc.so
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef
cccdlflags='-Kpic', ccdlflags=' ', lddlflags='-G -L/usr/ccs/lib
-L/usr/ucblib'
Thanks.
-Tony Camas
Boston Automation, Inc.
tony@bosauto.com
phone: 617-523-3999
fax: 617-523-3788
perlbug@perl.com and as an article in comp.lang.perl. I haven't
seen a response in either place, nor do I see my item chronicled in
the perl bugs database, so on the off chance that it got lost
somehow, I am submitting it again. Hope this isn't too pesky of
me. I know you're all quite busy and not being paid for any of this,
but I would appreciate at least an acknowledgement of receipt.
Thanks.
***
Brief summary: If you run a perl script while logged in as root,
and the script changes effective uid to something else, perl engages
its tainting mechanism, making everything difficult. Ironically,
the script was changing its uid in an attempt to be more secure and
prevent unintended alteration of protected files.
Here's my original message, describing this in more detail, and the
changes I propose to correct it:
----
I have a script which actually functions as an internet server,
listening on a privleged tcp/ip port. This script is started up at
system boot, and runs as root (actually as root, not under setuid to
root).
Because I want to try and guard against potential hacking attempts
(even though it's _extremely_ unlikely anyone could get this server
to do anything bad), I try and be a good citizen by having the script
change its effective uid to something *less* privileged. It runs in
this state most (99%) of the time; it only runs as root for the few
lines of code needed to establish the socket and bind it to the
privileged port.
This all worked under perl4, or at least under the version of perl4 I
was running (I didn't have the source code for our perl4 installation,
so I don't know what options might have been used to build it). Under
perl5, however, perl detects that, during most of the running of the
software, the real uid and the effective uid are different. It thus
wrongly concludes that I'm running it as a setuid script, and applies
the various "tainting" rules, which result in my inability to do such
mundane things as change directories. Ironically, perl tells me it
can't do this because my script is insecure, when in fact I took extra
steps to make sure the code was *more* secure.
I have fixed this in my version of perl, and I'm wondering if this fix
makes sense for the world or not. I don't see any way this could be a
problem, but then I don't know enough about unix security to be sure
there wouldn't be other side-effects of this. What I have done is
change the code which determines whether tainting is in effect. There
are about six lines scattered throughout the perl5 source that all
read:
tainting |= (euid != uid || egid != gid);
I have changed these to read:
tainting |= (uid && (euid != uid || egid != gid));
which exempts you from tainting if your real uid is actually root.
This lets you set euid (or egid) to something else without prejudice,
if you're doing so to *reduce* your privilege level rather than
increase it.
Does this seem reasonable? If it is, should I send the modified
source code somewhere? Let me know.
----
Footnote: The perl4 version where this worked was 4.036. My perl5
installation is current revision and patch level, 5.001m. Here's
my "myconfig" output:
Summary of my perl5 (patchlevel 1) configuration:
Platform:
osname=svr4, osver=, archname=i386-svr4
uname='unix_sv taz 4.2 1.1.3 i386 386at '
hint=previous
Compiler:
cc='/bin/cc', optimize='-O', ld='/bin/cc'
cppflags='-I/usr/include -I/usr/ucbinclude -DDEBUGGING'
ccflags ='-I/usr/include -I/usr/ucbinclude -DDEBUGGING'
ldflags ='-L/usr/ccs/lib -L/usr/ucblib'
stdchar='unsigned char', d_stdstdio=define, usevfork=false
voidflags=15, castflags=0, d_casti32=define, d_castneg=define
intsize=4, alignbytes=4, usemymalloc=y, randbits=15
Libraries:
so=so
libpth=/lib /usr/lib /usr/ccs/lib /usr/ucblib
libs=-lsocket -lnsl -ldbm -ldl -lld -lm -lc -lcrypt -lucb -lx
libc=/usr/ccs/lib/libc.so
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef
cccdlflags='-Kpic', ccdlflags=' ', lddlflags='-G -L/usr/ccs/lib
-L/usr/ucblib'
Thanks.
-Tony Camas
Boston Automation, Inc.
tony@bosauto.com
phone: 617-523-3999
fax: 617-523-3788