Re: Preventing changes on the
by grep (Monsignor) on Feb 18, 2002 at 18:55 UTC
|
I commend you on pointing out your 'Security by Obscurity', and you wanting it fixed. The best thing I can recommend is going through Ovid's Web Programming Using Perl course. It handles most of your security concerns as far as programming goes. There are just too many things to point out here in a post on perlmonks. Ovid even covers wog's excellent point (++) that HTTP_REFEFER can be spoofed (along with about everything else).
Then you have the fun task of locking down (hardening) your box.
I would recommend looking at:
- Bastille
- Security Focus
grep
| [reply] |
Re: Preventing changes on the
by wog (Curate) on Feb 18, 2002 at 18:55 UTC
|
You cannot solve this by making HTTP_REFERER checks. HTTP_REFERER can be spoofed. In fact, almost everything that goes into your script can be spoofed, which is why the answer to your question is "no". The way to solve your problem is by not accepting a user without more authentication. | [reply] |
Re: Preventing changes on the
by dmmiller2k (Chaplain) on Feb 18, 2002 at 19:41 UTC
|
Although it is simply adding another layer to your existing Security by Obscurity (and therefore not the entire solution to your problem), you might at least consider accepting only POST-type requests in your script. That is, instead of accessing the script by this hyperlink URL:
http://www.foo.com/cgi-bin/foo.pl?user=foolish&id=2
you use a form with all hidden fields and a button (which may be a bitmap):
<FORM METHOD=POST>
<INPUT TYPE=HIDDEN NAME='user' VALUE='foolish'>
<INPUT TYPE=HIDDEN NAME='id' VALUE='2'>
<!-- use THIS: -->
<INPUT TYPE=SUBMIT VALUE='Button Title'>
<!-- OR THIS: -->
<INPUT TYPE=IMAGE SRC='/images/button_img.jpg' onClick='submit()'>
</FORM>
Update: This won't prevent users from seeing what parameters your script takes (and their values), but rejecting GET requests will at least make it harder to fake them.
dmm
If you GIVE a man a fish you feed him for a day
But, TEACH him to fish and you feed him for a lifetime
| [reply] [d/l] [select] |
|
| [reply] |
|
This is true. I did not intend to suggest that this (and this alone) was a solution to the problem, but it makes it that much more difficult to accomplish (weeding out the "casual" spoofers, as it were). I agree that other security measures are also necessary; for instance, also incorporating HTTP_REFERRER checks and using session cookies, etc.
| [reply] |
Re: Preventing changes on the
by Speedy (Monk) on Feb 19, 2002 at 01:30 UTC
|
What if you trapped all calls to the page that did not have the proper query string by printing out an error page for each URL that did not match; something like:
#/usr/bin/perl
use CGI qw(:standard);
use strict;
my $q=new CGI;
# Check values from the query string
unless ($q->param('user') eq 'foolish' && $q->param('id') eq '2') {
print $q->header, $q->start_html(-title=>'Page not found');
print h2("This page was not found"), $q->end_html;
exit;
}
# Real page code follows
This only works if the script were the first page called from a blank location line by a user. If you use the query string user=foolish&id=2 in a redirect, hidden value, or any other programmatic call to the script, the keys can easily be seen by anyone running the scripts. Then I think you will need one of the more hard-core authentication methods recommended above.
Live in the moment | [reply] [d/l] |
|
| [reply] |
|
You are right. A more complicated scheme would be required for multiple user-id passwords. One method could be to store these user-id pairs in advance in a hash data file, say ../data/user_id, then check the incoming user-id pair against values in the existing hash. For example:
#/usr/bin/perl
use CGI qw(:standard);
use GDBM_File;
use strict;
my $q=new CGI;
# Assume an existing saved hash %user_id with 'user' as the key and '
+id' as the value
# created earlier by $user_id{"$user"} = $id and stored in ../data/us
+er_id
my $verify = "../data/user_id";
tie %user_id, 'GDBM_File', $verify, O_RDWR, 0666 or die "Can't tie $ve
+rify:$!";
my $user = $q->param('user');
my $id = $q->param('id');
# Check values from the query string against values in hash
unless (exists $user_id{"$user"} && $user_id{"$user"} = $id) {
print $q->header, $q->start_html(-title=>'Page not found');
print h2("This page was not found"), $q->end_html;
exit;
}
untie %user_id;
# Real page code follows
By now one has other worries, like being sure the hash is locked while a tie is taking place, about how to update and delete values from the hash, about passing a name-password without security, etc.
Better advice might be to learn about SSL and OS/Web Server authentication for the particular target platform.
| [reply] [d/l] |