I'm designing a very small ecommerce script. I have already made it and it does its purpose very well, but I know it is not secure.
Basically all I did was make an html form, and upon posting it collects the data and bundles it into an email, which is then sent to someone.
The biggest problem I see is that all of the data entered is posted to the URL bar when the user clicks submit. How can I secure my script?
You can find an example of the script here:
http://www.compassrad.com/sections/pay/pay.php
Feel free to enter fake data and submit it, it is just email to me for now.
Thanks.
Securing My Script
Moderator: General Moderators
Change the form method from GET to POST, that will take care of the long URL and also cause more browsers to warn before resubmitting on a page reload/back/forward click... But that has nothing to do with security...
SSL is a must, but that will only secure the connection between your customer an the webserver.
Your responsibility is to make sure that what goes on in your script is safe, and it is difficult to comment on that as you post no code... The security is not just how the data is received and handled, but also how it is stored and transfered from there and how you retrieve and vie the information.
Basically, ANYTHING used in a database query, filename, mailed-ToOrFrom-email-address MUST be validated for syntax. Make sure no-one can sneak in some funny stuff like javascript, vbscript or sql-code.. Always use mysql_espace_string() for any strings inserted in a mysql-database, always check for < and > and such in any field that should not have any, always use htmlspecialchars to translate things when showing it.. NEVER store a CC-number in cleartext on file or database, nor send in cleartext by email!! Any home made bitshuffling encryption is not good enough, any same-key reversible encryption is not good enough if you are in a shared-hosting environment, (so MySQL encode() makes no security), if possible run the CC-handlingscripts suExec as your own user with file permission set private, any storage or email transportation should be encrypted with a public/private key system, such as GnuPG, the private key must never even be near or on the server nor transported by cleartext email or ftp etc.. If you are doing online/direct merchant gateway you have to use SSL with it, but most (all?) wont let you do it otherwise anyway..
All this may sound paranoid, but to me its like a lottery, it is not a great chance of being hacked, BUT IF you where "lucky" and someone got a couple hundred CC-numbers and charged a couple hundred thousands on them.. how would you explain to VISA/MC/AMEX/The-Merchant-Bank that you didnt secure this or that because you didn't know how or didn't have time? To me, compromise is not an option when it is easy and within acceptable cost to fix!
I have had several customers asking me if they can have a system that remembers the customers CC-numbers so they can do express checkout.... If you are in a shared-hosting environment and doing direct/online gateway transactions that is most likely not possible (I guess some Gateways may have some options to use a ref-id or something, but the ones I worked with, mostly AUthorize.Net (AIM) and Surepay (Classic), does not offer any such thing, and there is no way you can safely store a decryptable code on a server with other users..
SSL is a must, but that will only secure the connection between your customer an the webserver.
Your responsibility is to make sure that what goes on in your script is safe, and it is difficult to comment on that as you post no code... The security is not just how the data is received and handled, but also how it is stored and transfered from there and how you retrieve and vie the information.
Basically, ANYTHING used in a database query, filename, mailed-ToOrFrom-email-address MUST be validated for syntax. Make sure no-one can sneak in some funny stuff like javascript, vbscript or sql-code.. Always use mysql_espace_string() for any strings inserted in a mysql-database, always check for < and > and such in any field that should not have any, always use htmlspecialchars to translate things when showing it.. NEVER store a CC-number in cleartext on file or database, nor send in cleartext by email!! Any home made bitshuffling encryption is not good enough, any same-key reversible encryption is not good enough if you are in a shared-hosting environment, (so MySQL encode() makes no security), if possible run the CC-handlingscripts suExec as your own user with file permission set private, any storage or email transportation should be encrypted with a public/private key system, such as GnuPG, the private key must never even be near or on the server nor transported by cleartext email or ftp etc.. If you are doing online/direct merchant gateway you have to use SSL with it, but most (all?) wont let you do it otherwise anyway..
All this may sound paranoid, but to me its like a lottery, it is not a great chance of being hacked, BUT IF you where "lucky" and someone got a couple hundred CC-numbers and charged a couple hundred thousands on them.. how would you explain to VISA/MC/AMEX/The-Merchant-Bank that you didnt secure this or that because you didn't know how or didn't have time? To me, compromise is not an option when it is easy and within acceptable cost to fix!
I have had several customers asking me if they can have a system that remembers the customers CC-numbers so they can do express checkout.... If you are in a shared-hosting environment and doing direct/online gateway transactions that is most likely not possible (I guess some Gateways may have some options to use a ref-id or something, but the ones I worked with, mostly AUthorize.Net (AIM) and Surepay (Classic), does not offer any such thing, and there is no way you can safely store a decryptable code on a server with other users..
Thanks alot for your reply, just what I was looking for. Here is my code from the processing page(the page which the form action points to):
Code: Select all
<?php
include ("../header.php");
PRINT "<CENTER>";
PRINT "Hello, <b>$name</b>.";
PRINT "<BR><BR>";
PRINT "Thank you for your payment! You should receive an email confirming your payment.";
PRINT "</CENTER>";
if($CCTYPE == "001"){
$CCTYPE = "Visa";
}elseif ($CCTYPE == "002"){
$CCTYPE = "Mastercard";
}elseif ($CCTYPE == "003"){
$CCTYPE = "Discover";
}elseif ($CCTYPE == "004"){
$CCTYPE = "American Express";
}
$subject = "Online Payment";
$email_message = "This is a payment made on the Compass website.
Name: $name
Email Address: $email
Street Address: $address
Address Continued: $adress2
City: $city
State: $state
Zipcode: $zip
Telephone Number: ($daytime_tel1)$daytime_tel2-$daytime_tel3 Ext: $phoneExt1
Amount listed on invoice: $amount
Credit Card Type: $CCTYPE
Credit Card Number: $CCNUMBER1-$CCNUMBER2-$CCNUMBER3-$CCNUMBER4
Expiration Date: $exp_month/$exp_year
Feedback from customer: $note";
mail("email@google.com", $subject, $email_message, "From: "$name" <$email>\nX-Mailer: PHP/" .phpversion(), "-f$name");
include ("../footer.php");quite a bit of work left there, pretty much all your used variables would need some pampering before being used.. 
Just wanted to mention a couple of other things as well, when processing cc-numbers you may want to validate it, there are some cc-num valdiation formulas out there.. And you also want to secure the script you got there so that no-one that just enters the url of that last page gets an email an such (validate session/login and/or fields being filled out correctly, javascript validation for that is not enough). If your server has magic_quotes_gpc enabled you may want to use stripslashes() for most of them (and then extra important to use mysql_escape_string() in queries).
* good luck * :cheers:
Just wanted to mention a couple of other things as well, when processing cc-numbers you may want to validate it, there are some cc-num valdiation formulas out there.. And you also want to secure the script you got there so that no-one that just enters the url of that last page gets an email an such (validate session/login and/or fields being filled out correctly, javascript validation for that is not enough). If your server has magic_quotes_gpc enabled you may want to use stripslashes() for most of them (and then extra important to use mysql_escape_string() in queries).
* good luck * :cheers:
Thanks again for your assistance.
I hate to keep bothering you, but could you be a tad more specific about how I can secure my variables?
I'll add sessions so they can't just get an email and I'll probably do server side variable checks just in case. I'll also look for the cc-number checker.
Thanks!
I hate to keep bothering you, but could you be a tad more specific about how I can secure my variables?
I'll add sessions so they can't just get an email and I'll probably do server side variable checks just in case. I'll also look for the cc-number checker.
Thanks!
anything that is supposed to be numerics you can test with is_numeric() and cast from float to int with typecasting if needed (see the PHP manual, typecasting, (int) )
Any string variable should be treated with stripslashes() if magic_quotes_gpc is enables, which it very common..
Any string variable that will be stored or directly displayed somewhere should be checked for inlcusion of script tags, something like a case insensitive regex like /<\s*SCRIPT.*?>/ and perhaps other tags/pieces of code that could make your or other browsers do something (cross-site scripting).
Any string output on a web page, either as visible text or as parameters to other tags etc you should use htmlspecialchars() (This can also help against cross-scripting as < and > is translated to their entities..)
Any string used in a database query must be properly escaped, with mysql use mysel_escape_string() This is actually the reason that the PHP developers created magic_quotes_gpc, there was so many inexperienced people creating form-to-database scripts with not esscapes/syntax check at all, insane, opening for "SQL-Injection".. The
"Magic" escaping will escape single quotes and such, but I highly recommend actively treating the variables the right way, by first using stripslashes() to remove the magic ones, and then use mysql_escape_string() to add the proper ones for queries..
those are the most important..
secondary you want to check syntax for your application use, such as an email address (and the name) for syntax before using it in the from field... someone could with that script easily add unlimited amounts of extra headers to that email.. A regex to check all possibilities of legal email syntax is huge, but a simple one works in 99% of the cases, something like
/^[A-z0-9][A-z0-9\-_.]*@[A-z0-9]([A-z0-9\-]+\.)+[A-z]+$/
or just look around on the net for email-verifying functions..
Basically, you usually want to deny everything but the allowed syntax/content, not opposite..
Any string variable should be treated with stripslashes() if magic_quotes_gpc is enables, which it very common..
Any string variable that will be stored or directly displayed somewhere should be checked for inlcusion of script tags, something like a case insensitive regex like /<\s*SCRIPT.*?>/ and perhaps other tags/pieces of code that could make your or other browsers do something (cross-site scripting).
Any string output on a web page, either as visible text or as parameters to other tags etc you should use htmlspecialchars() (This can also help against cross-scripting as < and > is translated to their entities..)
Any string used in a database query must be properly escaped, with mysql use mysel_escape_string() This is actually the reason that the PHP developers created magic_quotes_gpc, there was so many inexperienced people creating form-to-database scripts with not esscapes/syntax check at all, insane, opening for "SQL-Injection".. The
"Magic" escaping will escape single quotes and such, but I highly recommend actively treating the variables the right way, by first using stripslashes() to remove the magic ones, and then use mysql_escape_string() to add the proper ones for queries..
those are the most important..
secondary you want to check syntax for your application use, such as an email address (and the name) for syntax before using it in the from field... someone could with that script easily add unlimited amounts of extra headers to that email.. A regex to check all possibilities of legal email syntax is huge, but a simple one works in 99% of the cases, something like
/^[A-z0-9][A-z0-9\-_.]*@[A-z0-9]([A-z0-9\-]+\.)+[A-z]+$/
or just look around on the net for email-verifying functions..
Basically, you usually want to deny everything but the allowed syntax/content, not opposite..