The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> PHP Development
|
Securing a folder that updates the database
Discuss Securing a folder that updates the database in the PHP Development forum on Dev Shed. Securing a folder that updates the database PHP Development forum discussing coding practices, tips on PHP, and other PHP-related topics. PHP is an open source scripting language that has taken the web development industry by storm.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

January 4th, 2012, 07:35 PM
|
 |
A Change of Season
|
|
|
|
|
Securing a folder that updates the database
Hello forum;
I need to confirm I am doing the right thing here.
I have a folder called "ipn". The folder is only used when Pay pal calls it (That's just poor English). In other words, its not allowed to access any of the pages in this directly from the address bar (ie. www.domain.com/ipn/update_customer.php is not allowed).
Files in this folder update the database based on the $_GET values received from Pay pal:
For example:
PHP Code:
//Check and validating the $_GET values....
//.....
//If all good, then:
$qupdate="UPDATE customers_credits SET status = 'active', history = '".$history."' WHERE id = '".$clean_data_get['id']."'";
And this is what I send to Pay pal:
Code:
<input type="hidden" name="notify_url" value="http://www.domain.com/ipn/voucher_ipn_res.php?id=<?php echo $_GET['id'];?>" />
Here is my solution (which seems to be working just fine):
I create a .htaccess file in that folder with this content:
Code:
Order Deny,Allow
Deny from All
Allow from paypal.com
I appreciate if you point the security holes in that.
Thanks
__________________
Devshed people, please fix the spell check:
System is temporarily busy. Please try again in a few seconds.
Last edited by zxcvbnm : January 5th, 2012 at 05:43 PM.
|

January 4th, 2012, 08:40 PM
|
 |
Still alive
|
|
Join Date: Mar 2007
Location: Washington, USA
|
|
|
That's about it, really. But are there multiple files in that folder? The IPN script itself should be safe by virtue of how it works: it verifies the request against PayPal's servers and doesn't continue if it gets a bad response.
Otherwise I could be pedantic about the Order directive, but I don't feel like it. (It's fine.)
|

January 4th, 2012, 08:58 PM
|
 |
A Change of Season
|
|
|
|
Quote: | Originally Posted by requinix That's about it, really. But are there multiple files in that folder? The IPN script itself should be safe by virtue of how it works: it verifies the request against PayPal's servers and doesn't continue if it gets a bad response.
Otherwise I could be pedantic about the Order directive, but I don't feel like it. (It's fine.) |
Thanks yes there is only this file in the folder.
|

January 5th, 2012, 07:17 AM
|
|
Contributing User
|
|
Join Date: May 2011
Location: United Kingdom
Posts: 40
  
Time spent in forums: 7 h 52 m 5 sec
Reputation Power: 4
|
|
|
It would be possible to perform an attack at the DNS level to modify your hosts resolution of paypal.com to that of the attacker.
|

January 5th, 2012, 07:39 AM
|
 |
Square Peg in a Round Hole
|
|
Join Date: Oct 2007
Location: North Yorkshire, UK
|
|
|
I've you've coded up your ipn script properly then the world and his wife you view it and you'd still be safe.
Did you start your ipn script by copying the php sample code from paypal?
|

January 5th, 2012, 06:13 PM
|
 |
A Change of Season
|
|
|
|
Quote: | Originally Posted by Northie I've you've coded up your ipn script properly then the world and his wife you view it and you'd still be safe.
|
Hey this is strange English, pretty sure you have a good point but I don't understand.
Quote: | Originally Posted by Northie
Did you start your ipn script by copying the php sample code from paypal?
|
The ipn/update_customer.php script is just a simple database update script like this:
PHP Code:
$sql = "SELECT id FROM orders WHERE id=:id AND status=:status";
$args = array('id'=>$_GET['id'], 'status'=>'pending' );
//Chris probably won't like this but:
$number_of_rows = DB::Load()->Execute($sql,$args)->returnNumAffectedRows();
if($number_of_rows==1)
{
//$sql = "UPDATE...";
$args =...;
$execute...
}
else
{
//invalid
}
|

January 6th, 2012, 02:29 AM
|
 |
Square Peg in a Round Hole
|
|
Join Date: Oct 2007
Location: North Yorkshire, UK
|
|
Quote: | Originally Posted by zxcvbnm Hey this is strange English, pretty sure you have a good point but I don't understand. |
sorry, that should have been
Quote: | Originally Posted by Northie If you've coded up your ipn script properly then the world and his wife could view it and you'd still be safe. |
Quote: | Originally Posted by zxcvbnm The ipn/update_customer.php script is just a simple database update script like this: ... |
There's your problem, you're doing no validation checks with paypal. The code you've written should live deep inside an "if" statement.... read on for more, and some sample code
In an ipn call, paypal calls a script on your server. You are supposed to send these post values back to paypal in server-generated post request and read the response from it. Paypal's response to this post tells you if the transaction is legitimate, or not. Paypal knows if they, themselves, made the request to your ipn script and responds accordingly when asked to do so.
paypal sample code php code here:
https://cms.paypal.com/cms_content/.../IPN_PHP_41.txt
As for protecting your folder so that just paypal can access it - try this: The paypal sandbox will allow me to test any IPN script i know about, the request will come from a paypal.com domain
Last edited by Northie : January 6th, 2012 at 02:36 AM.
|

January 6th, 2012, 09:14 AM
|
|
Contributing Badly User
|
|
Join Date: Mar 2007
Posts: 143
  
Time spent in forums: 1 Day 18 h 32 m 38 sec
Reputation Power: 9
|
|
|
I am sure there is a system check that is available to you, as a part of your integrity checks.
Not 100% sure but i would think paypal has a call you can make to find out which system made the call to your server, live or sandbox.
as pointed out you can make a call to any ipn script with the sandbox, so there must be a system type call you can make.
__________________
If i went into too much detail or assumed this was what you meant, well thats just how i thought you wanted it
|

January 18th, 2012, 06:48 PM
|
 |
A Change of Season
|
|
|
|
Quote: | Originally Posted by Northie
There's your problem, you're doing no validation checks with paypal. The code you've written should live deep inside an "if" statement.... read on for more, and some sample code
In an ipn call, paypal calls a script on your server. You are supposed to send these post values back to paypal in server-generated post request and read the response from it. Paypal's response to this post tells you if the transaction is legitimate, or not. Paypal knows if they, themselves, made the request to your ipn script and responds accordingly when asked to do so.
paypal sample code php code here:
https://cms.paypal.com/cms_content/.../IPN_PHP_41.txt
As for protecting your folder so that just paypal can access it - try this: The paypal sandbox will allow me to test any IPN script i know about, the request will come from a paypal.com domain |
Hello;
I am a bit closer to your solution. I used the following code and the Sandbox says IPN successfully sent but I get the Invalid email. In other words in the ipn.php the check with Paypal is NOT verified. Please see below:
PHP Code:
<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($req)."\r\n\r\n";
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp)
{
// HTTP ERROR
}
else
{
fputs ($fp, $header.$req);
while(!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
// PAYMENT VALIDATED & VERIFIED!
$email = $_POST['payer_email'];
mail($email, $subject, $message, $headers);
// PAYMENT VALIDATED & VERIFIED!
}
elseif(strcmp ($res, "INVALID") == 0)
{
$email = $_POST['payer_email'];
foreach($_POST as $var)
{
$message .= "\r\n".$var;
}
mail($email, 'Invalid', $message, $headers);
}
}
fclose ($fp);
}
?>
And I keep getting an email with the title Invalid with the follwoing content:
Code:
1
instant
16:27:50 Jan 18, 2012 PST
Completed
confirmed
verified
John
Smith
pmdg3@yahoo.com
TESTBUYERID01
John Smith
United States
US
95131
CA
San Jose
123, any street
seller@paypalsandbox.com
seller@paypalsandbox.com
TESTSELLERID1
US
something
AK-1234
1
3.04
2.02
USD
0.44
12.34
9.34
web_accept
50119027
2.1
xyz123
windows-1252
Ay6yLHy3emJ0Ljt4I6eJB1vMeiv7AN8R9NE95JCSLrf.qgUlNmZn9Hu8
So basically this part of the code does not meet the criteria:
if (strcmp ($res, "VERIFIED") == 0)
What do you think is wrong?
Merci
|

January 19th, 2012, 06:30 AM
|
 |
Square Peg in a Round Hole
|
|
Join Date: Oct 2007
Location: North Yorkshire, UK
|
|
|
Paypal is always a pain.
When testing your ipn script from paypals developer/sandbox then the domain to which you open a socket to needs to be the sandbox domain/url not the normal one!
|

November 20th, 2012, 06:57 PM
|
 |
A Change of Season
|
|
|
|
In case anyone runs into this thread, note that Paypal has a new php listener. So do not use the code above, instead use the new version:
PHP Code:
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
} else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|