preventing the passing of parameters with the URL

I've got a script that I want to prevent people from trying to hack into.  It processes an HTML form, I take the input using the param method.  The form is freely accessible by everybody, but I want to make sure that the only input the script can get is from the select boxes on the form.  How can I prevent people from trying to pass values with the URL, or how can I detect it if it happens, and handle it in the script?  Or is ther another way?
ardasheksAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozoCommented:
Don't let your script accept any values that cannot be selected from your form.
Users can always generate a request containing any values they want.
0
djsansuiCommented:
I think what your trouble is is that you are using the "get" method.  this makes the script get the values from the string in the URL such as script.pl?value=forty-two

You should use the post method for your form, it is more secure because the user cannot see the data that is being passed to the script, the data is not saved in the browser's history folder, and there is no way for someone to pass other values to the script from the URL.  The perl code to get data from the post form method is this:

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
    ($name, $value) = split(/=/, $pair);
    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    $FORM{$name} = $value;
}

The other thing you should do is to prevent users from copying your HTML form and making their own.  This is accomplished by one of two methods.  One, as Ozo suggested, have any content that you want to limit as radio buttons, checkboxes or drop-down menus, and then within the scipt, check that the value matches one of the possibilities that you want to limit it to.  The other way to do it is to check that the $ENV{'HTTP_REFERER'} exists and is the location where your form is.

If you use these methods in conjunction with each other, you will effectively eliminate your hacking worries.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ozoCommented:
Users can generate post requests too.  You cannot be assured that any parameters you see came from your form.  But if you reject anything that wasn't on your form then users cannot do anything that they could not have done from your form.
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

kesonlineCommented:
Actually, I think you can do some sort of referer check to make sure it's coming from your page's address...rusty on Perl, I'll dig it up.
0
ozoCommented:
There's HTTP_REFERER (which is part of CGI, not part of Perl)
But users can send whatever they want for that too.
0
kesonlineCommented:
True, but much more of a pain to do. In the end, there's not much of a way. Perhaps you could use a hidden JavaScript to encrypt the values before sending or something such as that. Unfortuantely, I have no idea how to hide JavaScript, but I know it can be done.
0
ozoCommented:
If you send JavaScript to the user, the user can capture it and run it.
A one-way encryption may be able to give you the required security, but I don't see the point.
It makes more sense to me to distrust the source of any request, and simply not let the CGI program do anything that could not be legitimately done from the form.
0
ozoCommented:
One simple form of one-way encryption is table lookup.
If the CGI program has a list of select box values in the form,
the request need only tell the CGI which items in the list were selected,
and if the CGI only accepts items in the list, then it can only accept values that come from the form.
0
ardasheksAuthor Commented:
OK, what I'm hearing is

1) The only way to make sure that the parameters I get are not dangerous is to validate them in the CGI script.

2) Check the referrer to make sure the parameter came from my location.

Re #1:
GEEZ, I've got a select list with all the countries of the world, and
another that's almost as long!  Might be longer, actually. *So I gotta test for each one of those strings?*  Yikes!


Re #2:
It would make my form more useful if one or two of the parameters could be typed in by the user.  For instance, "city".  There are a heck of alot of cities.  That's one heck of a long select list..... maybe I could check for the most common type of hacking that would be done through that field (whatever that is).
0
ozoCommented:
#1, you must have a list of countries to generate the select boxes on the form.  You can use the same list to check the value you receive.

#2 Why do you care if anyone submits a non-city?   Depending on what you're doing with the value, it may be sufficient to check that it looks like a name, and not a command to format your disk and mail your password file to the user.
If you need to spellcheck for typos, or verify that the city matches the country, you may need to check a database anyway.
0
djsansuiCommented:
#1  This is how you can do it.  You can use this for whatever testing you want, if it isn't an acceptable answer, it will stop the script, and give an error.

@countries = ("place1",
"place2",
"place3");  #and so on, with all the country names,
                    #not hard at all.

$go = 0;

YA:foreach $i (@countries) { #check if it is an acceptable answer
 if ($country eq $i) { #make $country whatever variable you're using for it
  $go = 1;
  last YA;
 }
}

if ($go == 0) {&error;}
else {print "good";}

sub error {
print "bad country";
die;
}
0
ozoCommented:
#An easier way could be
@countries{
"place1" .. "place3",
} = ();

if( exists $countries{$country} ){
   print "good";
}else{
   &error
}
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.