Possible security flaws
am 04.05.2004 19:01:39 von Jan Eden
Hi all,
could you point out the possible security problems with the following desig=
n (planned)?
I have a database on my ISP's server which is accessible via a read-only an=
d a read/write account.
Now the CGI scripts I wrote to handle the database call the following subro=
utine from a module:
sub mysql_config {
my $mode =3D shift;
my ($server, $db, $username, $password);
if ($mode eq 'local') {
# local configuration
$server =3D 'localhost'; # The database server
$db =3D '************'; # The name of our database.
$username =3D '********' ;# the username=20
$password =3D '************' ;# the password
# editor configuration
} elsif ($mode eq 'editor') {
# pair.com configuration (write)
$server =3D '***********'; # The database server
$db =3D '*******'; # The name of our database
$username =3D '***********' ;# the username for reading/writing=20
$password =3D '*************' ;# the password
} else {
# read-only configuration
$server =3D '**********'; # The database server
$db =3D '******'; # The name of our database
$username =3D '************' ;# the username for reading=20
$password =3D '*********' ;# the password
}
return ($server, $db, $username, $password);
}
So if I call the script via the net in 'editor' mode, I have write access. =
But my editing script utilizes a user check like this:
sub user_check {
my ($user_id, $user_name_input, $user_password_input, $mode) =3D @_;
my ($server, $db, $username, $password) =3D mysql_config($mode);
my $dbh =3D DBI->connect("dbi:mysql:$db:$server", $username, $password,=
{ RaiseError =3D> 1 });
my $query =3D "SELECT user_name, user_password FROM users WHERE user_id=
=3D $user_id";
my $sth =3D $dbh->prepare($query);
$sth->execute();
my ($user_name, $user_password) =3D $sth->fetchrow_array;
$sth->finish();
return 1 if $user_name_input eq $user_name && $user_password_input eq $=
user_password;
return 0;
}
If no username/password are given (or if the wrong values are entered), the=
editing script generates an identification page, otherwise (if user_check =
returns 1), the editing form with the values of the page is printed out.
At which point is this setup vulnerable? So far, I only used local editing,=
and I still bear in mind that there's evil out there. ;-)
Thanks,
Jan
--=20
These are my principles and if you don't like them... well, I have others. =
- Groucho Marx
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=3Dgcdmp-msql-mysql-modules @m.gmane.org
Re: Possible security flaws
am 04.05.2004 19:25:51 von apv
I think you should try to avoid ever putting passwords (or usernames)
into scripts directly. MySQL gives a great alternative for loading the
information, the config file. You can have the DB in it too. This is
just one approach, of course.
So, your:
if ($mode eq 'local') {
# local configuration
$server = 'localhost'; # The database server
$db = '************'; # The name of our database.
$username = '********' ;# the username
$password = '************' ;# the password
# editor configuration
can become something like:
my $file_root = '/www/etc';
my %mysq_cnf = ( local => "$file_root/.local_mysql.cnf'.
etc => ... )
where the file, /www/etc/.local_mysql.cnf, outside the htdocs root, has
perms set for the webserver alone to readonly like:
-r-------- 1 nobody nobody 607 Apr 30 23:03 .local_mysql.cnf
file containing something like:
[client]
host=localhost
database=cargobeep
password=cantguessthis
# user is understood to be "nobody" so need not be entered
then you can load it, this way, i think (untested code):
my $connect_file = $mysq_cnf{$mode};
my $dbh = DBI->connect("DBI:mysql;" .
"mysql_read_default_file=$connect_file;"
);
-asdlkajsdfkljfey
On Tuesday, May 4, 2004, at 10:01 AM, Jan Eden wrote:
> Hi all,
>
> could you point out the possible security problems with the following
> design (planned)?
>
> I have a database on my ISP's server which is accessible via a
> read-only and a read/write account.
>
> Now the CGI scripts I wrote to handle the database call the following
> subroutine from a module:
>
> sub mysql_config {
> my $mode = shift;
> my ($server, $db, $username, $password);
> if ($mode eq 'local') {
> # local configuration
> $server = 'localhost'; # The database server
> $db = '************'; # The name of our database.
> $username = '********' ;# the username
> $password = '************' ;# the password
> # editor configuration
> } elsif ($mode eq 'editor') {
> # pair.com configuration (write)
> $server = '***********'; # The database server
> $db = '*******'; # The name of our database
> $username = '***********' ;# the username for reading/writing
> $password = '*************' ;# the password
> } else {
> # read-only configuration
> $server = '**********'; # The database server
> $db = '******'; # The name of our database
> $username = '************' ;# the username for reading
> $password = '*********' ;# the password
> }
> return ($server, $db, $username, $password);
> }
>
> So if I call the script via the net in 'editor' mode, I have write
> access. But my editing script utilizes a user check like this:
>
> sub user_check {
> my ($user_id, $user_name_input, $user_password_input, $mode) = @_;
> my ($server, $db, $username, $password) = mysql_config($mode);
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username,
> $password, { RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE
> user_id = $user_id";
> my $sth = $dbh->prepare($query);
> $sth->execute();
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
> return 1 if $user_name_input eq $user_name && $user_password_input
> eq $user_password;
> return 0;
> }
>
> If no username/password are given (or if the wrong values are
> entered), the editing script generates an identification page,
> otherwise (if user_check returns 1), the editing form with the values
> of the page is printed out.
>
> At which point is this setup vulnerable? So far, I only used local
> editing, and I still bear in mind that there's evil out there. ;-)
>
> Thanks,
>
> Jan
> --
> These are my principles and if you don't like them... well, I have
> others. - Groucho Marx
>
> --
> MySQL Perl Mailing List
> For list archives: http://lists.mysql.com/perl
> To unsubscribe: http://lists.mysql.com/perl?unsub=apv@sedition.com
>
>
>
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 04.05.2004 19:25:51 von apv
I think you should try to avoid ever putting passwords (or usernames)
into scripts directly. MySQL gives a great alternative for loading the
information, the config file. You can have the DB in it too. This is
just one approach, of course.
So, your:
if ($mode eq 'local') {
# local configuration
$server = 'localhost'; # The database server
$db = '************'; # The name of our database.
$username = '********' ;# the username
$password = '************' ;# the password
# editor configuration
can become something like:
my $file_root = '/www/etc';
my %mysq_cnf = ( local => "$file_root/.local_mysql.cnf'.
etc => ... )
where the file, /www/etc/.local_mysql.cnf, outside the htdocs root, has
perms set for the webserver alone to readonly like:
-r-------- 1 nobody nobody 607 Apr 30 23:03 .local_mysql.cnf
file containing something like:
[client]
host=localhost
database=cargobeep
password=cantguessthis
# user is understood to be "nobody" so need not be entered
then you can load it, this way, i think (untested code):
my $connect_file = $mysq_cnf{$mode};
my $dbh = DBI->connect("DBI:mysql;" .
"mysql_read_default_file=$connect_file;"
);
-asdlkajsdfkljfey
On Tuesday, May 4, 2004, at 10:01 AM, Jan Eden wrote:
> Hi all,
>
> could you point out the possible security problems with the following
> design (planned)?
>
> I have a database on my ISP's server which is accessible via a
> read-only and a read/write account.
>
> Now the CGI scripts I wrote to handle the database call the following
> subroutine from a module:
>
> sub mysql_config {
> my $mode = shift;
> my ($server, $db, $username, $password);
> if ($mode eq 'local') {
> # local configuration
> $server = 'localhost'; # The database server
> $db = '************'; # The name of our database.
> $username = '********' ;# the username
> $password = '************' ;# the password
> # editor configuration
> } elsif ($mode eq 'editor') {
> # pair.com configuration (write)
> $server = '***********'; # The database server
> $db = '*******'; # The name of our database
> $username = '***********' ;# the username for reading/writing
> $password = '*************' ;# the password
> } else {
> # read-only configuration
> $server = '**********'; # The database server
> $db = '******'; # The name of our database
> $username = '************' ;# the username for reading
> $password = '*********' ;# the password
> }
> return ($server, $db, $username, $password);
> }
>
> So if I call the script via the net in 'editor' mode, I have write
> access. But my editing script utilizes a user check like this:
>
> sub user_check {
> my ($user_id, $user_name_input, $user_password_input, $mode) = @_;
> my ($server, $db, $username, $password) = mysql_config($mode);
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username,
> $password, { RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE
> user_id = $user_id";
> my $sth = $dbh->prepare($query);
> $sth->execute();
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
> return 1 if $user_name_input eq $user_name && $user_password_input
> eq $user_password;
> return 0;
> }
>
> If no username/password are given (or if the wrong values are
> entered), the editing script generates an identification page,
> otherwise (if user_check returns 1), the editing form with the values
> of the page is printed out.
>
> At which point is this setup vulnerable? So far, I only used local
> editing, and I still bear in mind that there's evil out there. ;-)
>
> Thanks,
>
> Jan
> --
> These are my principles and if you don't like them... well, I have
> others. - Groucho Marx
>
> --
> MySQL Perl Mailing List
> For list archives: http://lists.mysql.com/perl
> To unsubscribe: http://lists.mysql.com/perl?unsub=apv@sedition.com
>
>
>
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 04.05.2004 23:07:26 von David Dick
if you change the following
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, { RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE user_id = $user_id";
> my $sth = $dbh->prepare($query);
> $sth->execute();
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
to be
my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, {
RaiseError => 1 });
my $query = "SELECT user_name, user_password FROM users WHERE user_id = ?";
my $sth = $dbh->prepare($query);
$sth->execute($user_id);
my ($user_name, $user_password) = $sth->fetchrow_array;
$sth->finish();
you will have a better chance of surviving a $user_id = qq[user_id] :)
even if you think there is no way $user_id could be compromised,
placeholders are still an excellent security measure.
uru
-Dave
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 04.05.2004 23:07:26 von David Dick
if you change the following
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, { RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE user_id = $user_id";
> my $sth = $dbh->prepare($query);
> $sth->execute();
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
to be
my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, {
RaiseError => 1 });
my $query = "SELECT user_name, user_password FROM users WHERE user_id = ?";
my $sth = $dbh->prepare($query);
$sth->execute($user_id);
my ($user_name, $user_password) = $sth->fetchrow_array;
$sth->finish();
you will have a better chance of surviving a $user_id = qq[user_id] :)
even if you think there is no way $user_id could be compromised,
placeholders are still an excellent security measure.
uru
-Dave
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 05.05.2004 00:17:27 von Jim
Hi,
For my personal edification, could you elaborate on
'surviving....qq[user_id]' in the following:
you will have a better chance of surviving a $user_id = qq[user_id] :)
even if you think there is no way $user_id could be compromised,
placeholders are still an excellent security measure.
Thanks,
Jim Cant
----- Original Message -----
From: "David Dick"
To: "Jan Eden"
Cc:
Sent: Tuesday, May 04, 2004 5:07 PM
Subject: Re: Possible security flaws
>
> if you change the following
>
> > my $dbh = DBI->connect("dbi:mysql:$db:$server", $username,
$password, { RaiseError => 1 });
> > my $query = "SELECT user_name, user_password FROM users WHERE
user_id = $user_id";
> > my $sth = $dbh->prepare($query);
> > $sth->execute();
> > my ($user_name, $user_password) = $sth->fetchrow_array;
> > $sth->finish();
>
> to be
>
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, {
> RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE user_id =
?";
> my $sth = $dbh->prepare($query);
> $sth->execute($user_id);
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
>
> uru
> -Dave
>
> --
> MySQL Perl Mailing List
> For list archives: http://lists.mysql.com/perl
> To unsubscribe: http://lists.mysql.com/perl?unsub=cant_jim@hotmail.com
>
>
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 05.05.2004 00:17:27 von Hotmail
Hi,
For my personal edification, could you elaborate on
'surviving....qq[user_id]' in the following:
you will have a better chance of surviving a $user_id = qq[user_id] :)
even if you think there is no way $user_id could be compromised,
placeholders are still an excellent security measure.
Thanks,
Jim Cant
----- Original Message -----
From: "David Dick"
To: "Jan Eden"
Cc:
Sent: Tuesday, May 04, 2004 5:07 PM
Subject: Re: Possible security flaws
>
> if you change the following
>
> > my $dbh = DBI->connect("dbi:mysql:$db:$server", $username,
$password, { RaiseError => 1 });
> > my $query = "SELECT user_name, user_password FROM users WHERE
user_id = $user_id";
> > my $sth = $dbh->prepare($query);
> > $sth->execute();
> > my ($user_name, $user_password) = $sth->fetchrow_array;
> > $sth->finish();
>
> to be
>
> my $dbh = DBI->connect("dbi:mysql:$db:$server", $username, $password, {
> RaiseError => 1 });
> my $query = "SELECT user_name, user_password FROM users WHERE user_id =
?";
> my $sth = $dbh->prepare($query);
> $sth->execute($user_id);
> my ($user_name, $user_password) = $sth->fetchrow_array;
> $sth->finish();
>
> uru
> -Dave
>
> --
> MySQL Perl Mailing List
> For list archives: http://lists.mysql.com/perl
> To unsubscribe: http://lists.mysql.com/perl?unsub=cant_jim@hotmail.com
>
>
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 05.05.2004 09:50:16 von Jan Eden
Thanks Dave and apv,
David Dick wrote on 05.05.2004:
>if you change the following
>
>>my $dbh =3D DBI->connect("dbi:mysql:$db:$server", $username,
>>$password, { RaiseError =3D> 1 }); my $query =3D "SELECT user_name,
>>user_password FROM users WHERE user_id =3D $user_id"; my $sth =3D
>>$dbh->prepare($query); $sth->execute(); my ($user_name,
>>$user_password) =3D $sth->fetchrow_array; $sth->finish();
>
>to be
>
>my $dbh =3D DBI->connect("dbi:mysql:$db:$server", $username, $password,
> { RaiseError =3D> 1 }); my $query =3D "SELECT user_name, user_password
>FROM users WHERE user_id =3D ?"; my $sth =3D $dbh->prepare($query);
>$sth->execute($user_id); my ($user_name, $user_password) =3D
>$sth->fetchrow_array; $sth->finish();
>
>you will have a better chance of surviving a $user_id =3D qq[user_id]
>:) even if you think there is no way $user_id could be compromised,
>placeholders are still an excellent security measure.
I will change my script accordingly.
- Jan
--=20
There are 10 kinds of people: those who understand binary, and those who d=
on't
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=3Dgcdmp-msql-mysql-modules @m.gmane.org
Re: Possible security flaws
am 05.05.2004 09:50:16 von Jan Eden
Thanks Dave and apv,
David Dick wrote on 05.05.2004:
>if you change the following
>
>>my $dbh =3D DBI->connect("dbi:mysql:$db:$server", $username,
>>$password, { RaiseError =3D> 1 }); my $query =3D "SELECT user_name,
>>user_password FROM users WHERE user_id =3D $user_id"; my $sth =3D
>>$dbh->prepare($query); $sth->execute(); my ($user_name,
>>$user_password) =3D $sth->fetchrow_array; $sth->finish();
>
>to be
>
>my $dbh =3D DBI->connect("dbi:mysql:$db:$server", $username, $password,
> { RaiseError =3D> 1 }); my $query =3D "SELECT user_name, user_password
>FROM users WHERE user_id =3D ?"; my $sth =3D $dbh->prepare($query);
>$sth->execute($user_id); my ($user_name, $user_password) =3D
>$sth->fetchrow_array; $sth->finish();
>
>you will have a better chance of surviving a $user_id =3D qq[user_id]
>:) even if you think there is no way $user_id could be compromised,
>placeholders are still an excellent security measure.
I will change my script accordingly.
- Jan
--=20
There are 10 kinds of people: those who understand binary, and those who d=
on't
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=3Dgcdmp-msql-mysql-modules @m.gmane.org
Re: Possible security flaws
am 05.05.2004 14:35:00 von David Dick
G'day Jim,
Jim wrote:
> Hi,
>
> For my personal edification, could you elaborate on
> 'surviving....qq[user_id]' in the following:
>
> you will have a better chance of surviving a $user_id = qq[user_id] :)
> even if you think there is no way $user_id could be compromised,
> placeholders are still an excellent security measure.
>
ok, when the following two statements are executed..
my $user_id = "user_id";
my $sql =
"SELECT user_name, user_password FROM users WHERE user_id = $user_id";
$sql now contains the following...
SELECT user_name, user_password FROM users WHERE user_id = user_id
which of course is always true (if any records at exist in the users
table). Therefore if the attacker can make $user_id hold qq[user_id]
then the attacker can always get into the application. Placeholders
automatically quote everything correctly, so with placeholders, $sql
would hold ...
SELECT user_name, user_password FROM users WHERE user_id = 'user_id'
which would correctly deny access.
Uru
-Dave
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 05.05.2004 14:35:00 von David Dick
G'day Jim,
Jim wrote:
> Hi,
>
> For my personal edification, could you elaborate on
> 'surviving....qq[user_id]' in the following:
>
> you will have a better chance of surviving a $user_id = qq[user_id] :)
> even if you think there is no way $user_id could be compromised,
> placeholders are still an excellent security measure.
>
ok, when the following two statements are executed..
my $user_id = "user_id";
my $sql =
"SELECT user_name, user_password FROM users WHERE user_id = $user_id";
$sql now contains the following...
SELECT user_name, user_password FROM users WHERE user_id = user_id
which of course is always true (if any records at exist in the users
table). Therefore if the attacker can make $user_id hold qq[user_id]
then the attacker can always get into the application. Placeholders
automatically quote everything correctly, so with placeholders, $sql
would hold ...
SELECT user_name, user_password FROM users WHERE user_id = 'user_id'
which would correctly deny access.
Uru
-Dave
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: Possible security flaws
am 06.05.2004 08:06:40 von Jan Eden
Hi Dave,
David Dick wrote on 05.05.2004:
>G'day Jim,
>
>Jim wrote:
>>Hi,
>>
>>For my personal edification, could you elaborate on
>>'surviving....qq[user_id]' in the following:
>>
>>you will have a better chance of surviving a $user_id =3D qq[user_id]
>>:) even if you think there is no way $user_id could be compromised,
>>placeholders are still an excellent security measure.
>>
>
>ok, when the following two statements are executed..
>
>my $user_id =3D "user_id"; my $sql =3D "SELECT user_name, user_password
>FROM users WHERE user_id =3D $user_id";
>
>$sql now contains the following...
>
>SELECT user_name, user_password FROM users WHERE user_id =3D user_id
>
>which of course is always true (if any records at exist in the users
>table). Therefore if the attacker can make $user_id hold
>qq[user_id] then the attacker can always get into the application.=20
>Placeholders automatically quote everything correctly, so with
>placeholders, $sql would hold ...
>
>SELECT user_name, user_password FROM users WHERE user_id =3D 'user_id'
>
>which would correctly deny access.
That's a good explanation in the light of which I think your advice - while=
still a good one in general - does not apply to my setup.
I do not check for the existence of a certain user_id, i.e. I do not check =
if the SELECT statement evaluates to true.
In fact, I do not take a user_id from the user at all. Instead, the user ha=
s to enter a name and a password when trying to access a restricted page. F=
or each restricted page (and for write access in general), there is a user_=
id hardcoded into this page's data set. My script reads the page data from =
the database (including the user_id) and passes it to the user_check sub, t=
ogether with the name and password the user entered.
In the next step, the user_id is used to construct the SELECT statement, wh=
ich returns a user name and a password. These two pieces of information are=
compared to the ones the user entered. Only if the two pairs are identical=
, access is granted.
I guess this process is also vulnerable, but entering qq{user_name} or qq{u=
ser_password} should not break it. I also filter the CGI parameter through =
a regex which only allows \w characters.
Thanks again for your suggestion,
Jan
--=20
How many Microsoft engineers does it take to screw in a lightbulb? None. Th=
ey just redefine "dark" as the new standard.
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=3Dgcdmp-msql-mysql-modules @m.gmane.org
Re: Possible security flaws
am 06.05.2004 08:06:40 von Jan Eden
Hi Dave,
David Dick wrote on 05.05.2004:
>G'day Jim,
>
>Jim wrote:
>>Hi,
>>
>>For my personal edification, could you elaborate on
>>'surviving....qq[user_id]' in the following:
>>
>>you will have a better chance of surviving a $user_id =3D qq[user_id]
>>:) even if you think there is no way $user_id could be compromised,
>>placeholders are still an excellent security measure.
>>
>
>ok, when the following two statements are executed..
>
>my $user_id =3D "user_id"; my $sql =3D "SELECT user_name, user_password
>FROM users WHERE user_id =3D $user_id";
>
>$sql now contains the following...
>
>SELECT user_name, user_password FROM users WHERE user_id =3D user_id
>
>which of course is always true (if any records at exist in the users
>table). Therefore if the attacker can make $user_id hold
>qq[user_id] then the attacker can always get into the application.=20
>Placeholders automatically quote everything correctly, so with
>placeholders, $sql would hold ...
>
>SELECT user_name, user_password FROM users WHERE user_id =3D 'user_id'
>
>which would correctly deny access.
That's a good explanation in the light of which I think your advice - while=
still a good one in general - does not apply to my setup.
I do not check for the existence of a certain user_id, i.e. I do not check =
if the SELECT statement evaluates to true.
In fact, I do not take a user_id from the user at all. Instead, the user ha=
s to enter a name and a password when trying to access a restricted page. F=
or each restricted page (and for write access in general), there is a user_=
id hardcoded into this page's data set. My script reads the page data from =
the database (including the user_id) and passes it to the user_check sub, t=
ogether with the name and password the user entered.
In the next step, the user_id is used to construct the SELECT statement, wh=
ich returns a user name and a password. These two pieces of information are=
compared to the ones the user entered. Only if the two pairs are identical=
, access is granted.
I guess this process is also vulnerable, but entering qq{user_name} or qq{u=
ser_password} should not break it. I also filter the CGI parameter through =
a regex which only allows \w characters.
Thanks again for your suggestion,
Jan
--=20
How many Microsoft engineers does it take to screw in a lightbulb? None. Th=
ey just redefine "dark" as the new standard.
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=3Dgcdmp-msql-mysql-modules @m.gmane.org
Re: [perl-mysql] Re: Possible security flaws
am 06.05.2004 13:54:45 von Dave Cash
On Thu, 6 May 2004, Jan Eden wrote:
> Hi Dave,
>
> David Dick wrote on 05.05.2004:
>
> >G'day Jim,
> >
> >Jim wrote:
> >>Hi,
> >>
> >>For my personal edification, could you elaborate on
> >>'surviving....qq[user_id]' in the following:
> >>
> >>you will have a better chance of surviving a $user_id = qq[user_id]
> >>:) even if you think there is no way $user_id could be compromised,
> >>placeholders are still an excellent security measure.
> >>
> >
> >ok, when the following two statements are executed..
> >
> >my $user_id = "user_id"; my $sql = "SELECT user_name, user_password
> >FROM users WHERE user_id = $user_id";
> >
> >$sql now contains the following...
> >
> >SELECT user_name, user_password FROM users WHERE user_id = user_id
> >
> >which of course is always true (if any records at exist in the users
> >table). Therefore if the attacker can make $user_id hold
> >qq[user_id] then the attacker can always get into the application.
> >Placeholders automatically quote everything correctly, so with
> >placeholders, $sql would hold ...
> >
> >SELECT user_name, user_password FROM users WHERE user_id = 'user_id'
> >
> >which would correctly deny access.
>
> That's a good explanation in the light of which I think your
> advice - while still a good one in general - does not apply to my
> setup.
>
> I do not check for the existence of a certain user_id, i.e. I do
> not check if the SELECT statement evaluates to true.
>
> In fact, I do not take a user_id from the user at all. Instead,
> the user has to enter a name and a password when trying to access
> a restricted page. For each restricted page (and for write access
> in general), there is a user_id hardcoded into this page's data
> set. My script reads the page data from the database (including
> the user_id) and passes it to the user_check sub, together with
> the name and password the user entered.
If by "there is a user_id hardcoded into this page's data set" you
mean the user's user_id is stored in an HTML hidden field or in a
QUERY_STRING somewhere, it's worth mentioning that these two methods
of data persistence can fairly trivially be exploited. One need
only prepare an application-valid QUERY_STRING or POST content
string with a different value for user_id to potentially access
(depending on what other security measures have or have not been
taken) an account owned by someone else.
> In the next step, the user_id is used to construct the SELECT
> statement, which returns a user name and a password. These two
> pieces of information are compared to the ones the user entered.
> Only if the two pairs are identical, access is granted.
>
> I guess this process is also vulnerable, but entering
> qq{user_name} or qq{user_password} should not break it. I also
> filter the CGI parameter through a regex which only allows \w
> characters.
I'm not sure if you're rolling your own or using a CPAN solution,
but in case you don't know about it, CGI::Untaint is a good module
for both untainting and validating data your script gets via the
CGI.
Dave
/L\_/E\_/A\_/R\_/N\_/T\_/E\_/A\_/C\_/H\_/L\_/E\_/A\_/R\_/N\
Dave Cash Power to the People!
Frolicking in Fields of Garlic Right On-Line!
dave@gnofn.org Dig it all.
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org
Re: [perl-mysql] Re: Possible security flaws
am 06.05.2004 13:54:45 von Dave Cash
On Thu, 6 May 2004, Jan Eden wrote:
> Hi Dave,
>
> David Dick wrote on 05.05.2004:
>
> >G'day Jim,
> >
> >Jim wrote:
> >>Hi,
> >>
> >>For my personal edification, could you elaborate on
> >>'surviving....qq[user_id]' in the following:
> >>
> >>you will have a better chance of surviving a $user_id = qq[user_id]
> >>:) even if you think there is no way $user_id could be compromised,
> >>placeholders are still an excellent security measure.
> >>
> >
> >ok, when the following two statements are executed..
> >
> >my $user_id = "user_id"; my $sql = "SELECT user_name, user_password
> >FROM users WHERE user_id = $user_id";
> >
> >$sql now contains the following...
> >
> >SELECT user_name, user_password FROM users WHERE user_id = user_id
> >
> >which of course is always true (if any records at exist in the users
> >table). Therefore if the attacker can make $user_id hold
> >qq[user_id] then the attacker can always get into the application.
> >Placeholders automatically quote everything correctly, so with
> >placeholders, $sql would hold ...
> >
> >SELECT user_name, user_password FROM users WHERE user_id = 'user_id'
> >
> >which would correctly deny access.
>
> That's a good explanation in the light of which I think your
> advice - while still a good one in general - does not apply to my
> setup.
>
> I do not check for the existence of a certain user_id, i.e. I do
> not check if the SELECT statement evaluates to true.
>
> In fact, I do not take a user_id from the user at all. Instead,
> the user has to enter a name and a password when trying to access
> a restricted page. For each restricted page (and for write access
> in general), there is a user_id hardcoded into this page's data
> set. My script reads the page data from the database (including
> the user_id) and passes it to the user_check sub, together with
> the name and password the user entered.
If by "there is a user_id hardcoded into this page's data set" you
mean the user's user_id is stored in an HTML hidden field or in a
QUERY_STRING somewhere, it's worth mentioning that these two methods
of data persistence can fairly trivially be exploited. One need
only prepare an application-valid QUERY_STRING or POST content
string with a different value for user_id to potentially access
(depending on what other security measures have or have not been
taken) an account owned by someone else.
> In the next step, the user_id is used to construct the SELECT
> statement, which returns a user name and a password. These two
> pieces of information are compared to the ones the user entered.
> Only if the two pairs are identical, access is granted.
>
> I guess this process is also vulnerable, but entering
> qq{user_name} or qq{user_password} should not break it. I also
> filter the CGI parameter through a regex which only allows \w
> characters.
I'm not sure if you're rolling your own or using a CPAN solution,
but in case you don't know about it, CGI::Untaint is a good module
for both untainting and validating data your script gets via the
CGI.
Dave
/L\_/E\_/A\_/R\_/N\_/T\_/E\_/A\_/C\_/H\_/L\_/E\_/A\_/R\_/N\
Dave Cash Power to the People!
Frolicking in Fields of Garlic Right On-Line!
dave@gnofn.org Dig it all.
--
MySQL Perl Mailing List
For list archives: http://lists.mysql.com/perl
To unsubscribe: http://lists.mysql.com/perl?unsub=gcdmp-msql-mysql-modules@m .gmane.org