in reply to Re^11: Recalcitrant placeholders
in thread Recalcitrant placeholders

What happens if you untaint the email address?

Not what I was expecting to happen!!!
I was pretty sure that untainting the email address would have the same effect as turning off taint mode but it doesn't.

This code:

#!/usr/bin/perl -T use CGI::Carp qw(fatalsToBrowser); use warnings; use strict; use feature 'say'; use Scalar::Util qw/tainted/; use DBI; use DBI::Const::GetInfoType; my @argv; if ($ENV{'GATEWAY_INTERFACE'}) { @argv = split /&/, $ENV{'QUERY_STRING'}; } else { @argv = @ARGV; } my $db_user = 'xxx'; my $db_pass = 'xxx'; my $dbh = DBI->connect( "DBI:mysql:database=shoples1_testing;host=127.0.0.1", $db_user, $db_pass, { RaiseError=>1, AutoCommit=>1, TaintIn=>0 }); print "Content-type: text/plain\n\n"; say "Perl: $]"; say "Database: ", $dbh->get_info( $GetInfoType{SQL_DBMS_NAME} ), " ", $dbh->get_info( $GetInfoType{SQL_DBMS_VER} ); say "Driver: ", $dbh->{Driver}->{Name}; say "DBI Ver: ", $DBI::VERSION; say "DBD::mysql Ver: ", $DBD::mysql::VERSION; $dbh->do('DROP TABLE IF EXISTS Person'); $dbh->do(<<'ENDSQL'); CREATE TABLE Person ( idPerson INT, email VARCHAR(256), altEmail VARCHAR(256) ); ENDSQL $dbh->do('INSERT INTO Person (idPerson, email, altEmail) VALUES (5, ?, + "foo@bar.com");', undef, $argv[1]); die "run me with an empty string as the first argument" unless @argv && !length $argv[0]; my %data = ( email => $argv[1] ); say "Email is tainted" if tainted($data{'email'}); say "Tainted..."; say "EMAIL: $argv[1]"; if ($argv[1] =~ /^(.+\@.+\..+)$/) { $argv[1] = $1; say "Untainted..."; say "EMAIL: $argv[1]"; } my $query = $dbh->prepare("SELECT idPerson FROM Person WHERE email = ? + OR altEmail = ?"); $query->execute($data{'email'}, $data{'email'}); my ($crid) = $query->fetchrow_array; say "CRID: $crid"; my ($test) = $dbh->selectrow_array("SELECT idPerson FROM Person WHERE +email = ? OR altEmail = ?", undef, $data{'email'}, $data{'email'}); say "TEST: $test"; __END__
produces this with taint mode off:
Perl: 5.016003 Database: MySQL 10.2.39-MariaDB Driver: mysql DBI Ver: 1.643 DBD::mysql Ver: 4.050 Tainted... EMAIL: foo@bar.com Untainted... EMAIL: foo@bar.com CRID: 5 TEST: 5
and this with taint mode on:
Perl: 5.016003 Database: MySQL 10.2.39-MariaDB Driver: mysql DBI Ver: 1.643 DBD::mysql Ver: 4.050 Email is tainted Tainted... EMAIL: foo@bar.com Untainted... EMAIL: foo@bar.com CRID: 5 TEST: 0

I realise the regexp is not especially good but it is just for testing and does the job of untainting the email address. The extra say statements are added to prove that the emails address really is being untainted.

Replies are listed 'Best First'.
Re^13: Recalcitrant placeholders
by pryrt (Abbot) on Aug 05, 2021 at 23:59 UTC

    When your code is untainting $argv[1] after the tainted value has been copied into $data{'email'}, why would you expect the database interaction to change? I believe that you need to untaint $data{'email'} , since that's your input to the database.

    I switched your code over to SQLite to try it myself; unfortunately, even with the code you posted (except for the switch to SQLite), both CRID and TEST gave me 5. So I cannot test that portion for you. But if you add debug prints of the taintedness of both after you believe you are untainted, you will see

    ... snippet ... # here, you untainted the argv[1], but not the hash value! if ($argv[1] =~ /^(.+\@.+\..+)$/) { $argv[1] = $1; say "Looking while Untainted..."; say "EMAIL: $argv[1]"; say __LINE__, ": argv is ", (tainted($argv[1])?'':'not ', "tainted +"); # edit: uncomment here to untaint the hash value as well #$data{'email'} = $argv[1]; } say "argv is ", (tainted($argv[1])?'':'not ', "tainted"); say "data{email} is ", tainted($data{'email'})?'':'not ', "tainted"; ... snippet ... __END__

    With the line commented, as shown:

    C:\usr\local\share\PassThru\perl\perlmonks>perl -T pm11135636.pl "" fo +o@bar.com Content-type: text/plain Perl: 5.030000 Database: SQLite 3.26.0 Driver: SQLite DBI Ver: 1.642 DBD::SQLite Ver: 1.62 Email is tainted Tainted... EMAIL: foo@bar.com Untainted... EMAIL: foo@bar.com argv is not tainted data{email} is tainted CRID: 5 TEST: 5

    With the line uncommented, so it untaints:

    C:\usr\local\share\PassThru\perl\perlmonks>perl -T pm11135636.pl "" fo +o@bar.com Content-type: text/plain Perl: 5.030000 Database: SQLite 3.26.0 Driver: SQLite DBI Ver: 1.642 DBD::SQLite Ver: 1.62 Email is tainted Tainted... EMAIL: foo@bar.com Untainted... EMAIL: foo@bar.com argv is not tainted data{email} is not tainted CRID: 5 TEST: 5

      When your code is untainting $argv1 after the tainted value has been copied into $data{'email'}, why would you expect the database interaction to change?

      That was rather stupid of me wasn't it?!?
      No answer required...

      That's what comes of trying to do something quickly last thing at night before bed. A combination of tiredness and rushing is always bound to lead to stupid mistakes. I should know this...

      When I untaint the correct variable I get what I expected...

      Perl: 5.016003 Database: MySQL 10.2.40-MariaDB Driver: mysql DBI Ver: 1.643 DBD::mysql Ver: 4.050 Email is tainted Tainted... EMAIL: foo@bar.com Untainted... EMAIL: foo@bar.com CRID: 5 TEST: 5