|
Packit |
dfe23c |
NAME
|
|
Packit |
dfe23c |
Taint::Runtime - Runtime enable taint checking
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
SYNOPSIS
|
|
Packit |
dfe23c |
### sample "enable" usage
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
#!/usr/bin/perl -w
|
|
Packit |
dfe23c |
use Taint::Runtime qw(enable taint_env);
|
|
Packit |
dfe23c |
taint_env();
|
|
Packit |
dfe23c |
# having the keyword enable in the import list starts taint
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
### sample $TAINT usage
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
#!/usr/bin/perl -w
|
|
Packit |
dfe23c |
use Taint::Runtime qw($TAINT taint_env);
|
|
Packit |
dfe23c |
$TAINT = 1;
|
|
Packit |
dfe23c |
taint_env();
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
# taint is now enabled
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
if (1) {
|
|
Packit |
dfe23c |
local $TAINT = 0;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
# do something we trust
|
|
Packit |
dfe23c |
}
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
# back to an untrustwory area
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
### sample functional usage
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
#!/usr/bin/perl -w
|
|
Packit |
dfe23c |
use strict;
|
|
Packit |
dfe23c |
use Taint::Runtime qw(taint_start is_tainted taint_env
|
|
Packit |
dfe23c |
taint untaint
|
|
Packit |
dfe23c |
taint_enabled);
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
### other operations here
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_start(); # taint should become active
|
|
Packit |
dfe23c |
taint_env(); # %ENV was previously untainted
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
print taint_enabled() ? "enabled\n" : "not enabled\n";
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
my $var = taint("some string");
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
print is_tainted($var) ? "tainted\n" : "not tainted\n";
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
$var = untaint($var);
|
|
Packit |
dfe23c |
# OR
|
|
Packit |
dfe23c |
untaint \$var;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
print is_tainted($var) ? "tainted\n" : "not tainted\n";
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
DESCRIPTION
|
|
Packit |
dfe23c |
First - you probably shouldn't use this module to control taint. You
|
|
Packit |
dfe23c |
should probably use the -T switch on the commandline instead. There are
|
|
Packit |
dfe23c |
a somewhat limited number of legitimate use cases where you should use
|
|
Packit |
dfe23c |
this module instead of the -T switch. Unless you have a specific and
|
|
Packit |
dfe23c |
good reason for not using the -T option, you should use the -T option.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
Taint is a good thing. However, few people (that I work with or talk to
|
|
Packit |
dfe23c |
or discuss items with) use taint even though they should. The goal of
|
|
Packit |
dfe23c |
this module isn't to use taint less, but to actually encourage its use
|
|
Packit |
dfe23c |
more. This module aims to make using taint as painless as possible (This
|
|
Packit |
dfe23c |
can be an argument against it - often implementation of security implies
|
|
Packit |
dfe23c |
pain - so taking away pain might lessen security - sort of).
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
In general - the more secure your script needs to be - the earlier on in
|
|
Packit |
dfe23c |
your program that tainting should be enabled. For most setuid scripts,
|
|
Packit |
dfe23c |
you should enable taint by using the -T switch. Without doing so you
|
|
Packit |
dfe23c |
allow for a non-root user to override @INC which allows for them to put
|
|
Packit |
dfe23c |
their own module in the place of trusted modules. This is bad. This is
|
|
Packit |
dfe23c |
very bad. Use the -T switch.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
There are some common places where this module may be useful, and where
|
|
Packit |
dfe23c |
most people don't use it. One such place is in a web server. The -T
|
|
Packit |
dfe23c |
switch removes PERL5LIB and PERLLIB and '.' from @INC (or remove them
|
|
Packit |
dfe23c |
before they can be added). This makes sense under setuid. The use of the
|
|
Packit |
dfe23c |
-T switch in a CGI environment may cause a bit of a headache. For new
|
|
Packit |
dfe23c |
development, CGI scripts it may be possible to use the -T switch and for
|
|
Packit |
dfe23c |
mod_perl environments there is the PerlTaint variable. Both of these
|
|
Packit |
dfe23c |
methods will enable taint and from that point on development should be
|
|
Packit |
dfe23c |
done with taint.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
However, many (possibly most) perl web server implentations add their
|
|
Packit |
dfe23c |
own paths to the PERL5LIB. All CGI's and mod_perl scripts can then have
|
|
Packit |
dfe23c |
access. Using the -T switch throws a wrench into the works as suddenly
|
|
Packit |
dfe23c |
PERL5LIB disappears (mod_perl can easily have the extra directories
|
|
Packit |
dfe23c |
added again using <perl>push @INC, '/our/lib/dir';</perl>). The company
|
|
Packit |
dfe23c |
I work for has 200 plus user visible scripts mixed with some mod_perl.
|
|
Packit |
dfe23c |
Currently none of the scripts use taint. We would like for them all to,
|
|
Packit |
dfe23c |
but it is not feasible to make the change all at once. Taint::Runtime
|
|
Packit |
dfe23c |
allows for moving legacy scripts over one at a time.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
Again, if you are using setuid - don't use this script.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
If you are not using setuid and have reasons not to use the -T and are
|
|
Packit |
dfe23c |
using this module, make sure that taint is enabled before processing any
|
|
Packit |
dfe23c |
user data. Also remember that BECAUSE THE -T SWITCH WAS NOT USED %ENV IS
|
|
Packit |
dfe23c |
INITIALLY NOT MARKED AS TAINTED. Call taint_env() to mark it as tainted
|
|
Packit |
dfe23c |
(especially important in CGI scripts which all read from
|
|
Packit |
dfe23c |
$ENV{'QUERY_STRING'}).
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
If you are not using the -T switch, you most likely should use the
|
|
Packit |
dfe23c |
following at the very top of your script:
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
#!/usr/bin/perl -w
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use strict;
|
|
Packit |
dfe23c |
use Taint::Runtime qw(enable taint_env);
|
|
Packit |
dfe23c |
taint_env();
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
Though this module allows for you to turn taint off - you probably
|
|
Packit |
dfe23c |
shouldn't. This module is more for you to turn taint on - and once it is
|
|
Packit |
dfe23c |
on it probably ought to stay on.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
NON-EXPORTABLE XS FUNCTIONS
|
|
Packit |
dfe23c |
The following very basic functions provide the base functionality.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
_taint_start()
|
|
Packit |
dfe23c |
Sets PL_tainting
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
_taint_stop()
|
|
Packit |
dfe23c |
Sets PL_tainting
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
_taint_enabled()
|
|
Packit |
dfe23c |
View of PL_tainting
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
_tainted()
|
|
Packit |
dfe23c |
Returns a zero length tainted string.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
$TAINT VARIABLE
|
|
Packit |
dfe23c |
The variable $TAINT is tied to the current state of taint. If $TAINT is
|
|
Packit |
dfe23c |
set to 0 taint mode is off. When it is set to 1 taint mode is enabled.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
if (1) {
|
|
Packit |
dfe23c |
local $TAINT = 1;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
# taint is enabled
|
|
Packit |
dfe23c |
}
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
EXPORT FUNCTIONS
|
|
Packit |
dfe23c |
enable/disable
|
|
Packit |
dfe23c |
Not really functions. If these keywords are in the import list,
|
|
Packit |
dfe23c |
taint will be either enabled or disabled.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_start
|
|
Packit |
dfe23c |
Start taint mode. $TAINT will equal 1.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_stop
|
|
Packit |
dfe23c |
Stop taint mode. $TAINT will equal 0.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_env
|
|
Packit |
dfe23c |
Convenience function that taints the keys and values of %ENV. If the
|
|
Packit |
dfe23c |
-T switch was not used - you most likely should call this as soon as
|
|
Packit |
dfe23c |
taint mode is enabled.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint
|
|
Packit |
dfe23c |
Taints the passed in variable. Only works on writeable scalar
|
|
Packit |
dfe23c |
values. If a scalar ref is passed in - it is modified. If a scalar
|
|
Packit |
dfe23c |
is passed in (non ref) it is copied, modified and returned. If a
|
|
Packit |
dfe23c |
value was undefined, it becomes a zero length defined and tainted
|
|
Packit |
dfe23c |
string.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint(\$var_to_be_tainted);
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
my $tainted_copy = taint($some_var);
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
For a stronger taint, see the Taint module by Dan Sulgalski which is
|
|
Packit |
dfe23c |
capable of tainting most types of data.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
untaint
|
|
Packit |
dfe23c |
Untaints the passed in variable. Only works on writeable scalar
|
|
Packit |
dfe23c |
values. If a scalar ref is passed in - it is modified. If a scalar
|
|
Packit |
dfe23c |
is passed in (non ref) it is copied, modified and returned. If a
|
|
Packit |
dfe23c |
value was undefined it becomes an untainted undefined value.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
Note: Just because the variable is untainted, doesn't mean that it
|
|
Packit |
dfe23c |
is safe. You really should use CGI::Ex::Validate, or
|
|
Packit |
dfe23c |
Data::FormValidator or any of the Untaint:: modules. If you are
|
|
Packit |
dfe23c |
doing your own validation, and once you have put the user data
|
|
Packit |
dfe23c |
through very strict checks, then you can use untaint.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
if ($var_to_be_untainted =~ /^[\w\.\-]{0,100}$/) {
|
|
Packit |
dfe23c |
untaint(\$var_to_be_untainted);
|
|
Packit |
dfe23c |
}
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
my $untainted_copy = untaint($some_var);
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_enabled
|
|
Packit |
dfe23c |
Boolean - Is taint on.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
tainted
|
|
Packit |
dfe23c |
Returns a zero length tainted string.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
is_tainted
|
|
Packit |
dfe23c |
Boolean - True if the passed value is tainted.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
taint_deeply
|
|
Packit |
dfe23c |
Convenience function that attempts to deply recurse a structure and
|
|
Packit |
dfe23c |
mark it as tainted. Takes a hashref, arrayref, scalar ref, or scalar
|
|
Packit |
dfe23c |
and recursively untaints the structure.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
For a stronger taint, see the Taint module by Dan Sulgalski which is
|
|
Packit |
dfe23c |
capable of tainting most types of data.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
TURNING TAINT ON
|
|
Packit |
dfe23c |
(Be sure to call taint_env() after turning taint on the first time)
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
#!/usr/bin/perl -T
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Taint::Runtime qw(enable);
|
|
Packit |
dfe23c |
# this does not create a function called enable - just starts taint
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Taint::Runtime qw($TAINT);
|
|
Packit |
dfe23c |
$TAINT = 1;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Taint::Runtime qw(taint_start);
|
|
Packit |
dfe23c |
taint_start;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
TURNING TAINT OFF
|
|
Packit |
dfe23c |
use Taint::Runtime qw(disable);
|
|
Packit |
dfe23c |
# this does not create a function called disable - just stops taint
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Taint::Runtime qw($TAINT);
|
|
Packit |
dfe23c |
$TAINT = 0;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Taint::Runtime qw(taint_stop);
|
|
Packit |
dfe23c |
taint_stop;
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
CREDITS
|
|
Packit |
dfe23c |
C code was provided by "hv" on perlmonks. This module wouldn't really be
|
|
Packit |
dfe23c |
possible without insight into the internals that "hv" provided. His post
|
|
Packit |
dfe23c |
with the code was shown in this node on perlmonks:
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
http://perlmonks.org/?node_id=434086
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
The basic premise in that node was the following code:
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
use Inline C => 'void _start_taint() { PL_tainting = 1; }';
|
|
Packit |
dfe23c |
use Inline C => 'SV* _tainted() { PL_tainted = 1; return newSVpvn("", 0); }';
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
In this module, these two lines have instead been turned into XS for
|
|
Packit |
dfe23c |
runtime speed (and so you won't need Inline and Parse::RecDescent).
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
Note: even though "hv" provided the base code example, that doesn't mean
|
|
Packit |
dfe23c |
that he necessarily endorses the idea. If there are disagreements,
|
|
Packit |
dfe23c |
quirks, annoyances or any other negative side effects with this module -
|
|
Packit |
dfe23c |
blame me - not "hv."
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
THANKS
|
|
Packit |
dfe23c |
Thanks to Alexey A. Kiritchun for pointing out untaint failure on
|
|
Packit |
dfe23c |
multiline strings.
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
AUTHOR
|
|
Packit |
dfe23c |
Paul Seamons (2005)
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
C stub functions by "hv" on perlmonks.org
|
|
Packit |
dfe23c |
|
|
Packit |
dfe23c |
LICENSE
|
|
Packit |
dfe23c |
This module may be used and distributed under the same terms as Perl
|
|
Packit |
dfe23c |
itself.
|
|
Packit |
dfe23c |
|