PayPal IPN sends a POST request with a variable number of fields to the notify URL, in order to confirm that the POST request is legit we need to resubmit the same request along with a additional cmd=_notify-validate
field to PayPal, which then replies VERIFIED
or INVALID
.
My question is, why do we need to resend the request to PayPal? Wouldn't something like this suffice?
if (preg_match('~^(?:.+[.])?paypal[.]com$~i', gethostbyaddr($_SERVER['REMOTE_ADDR'])) > 0)
{
// request came from PayPal, it's legit.
}
Iff we can trust the server to correctly resolve IPs, I assume we can trust all requests from PayPal, no?
Instant Payment Notification (IPN) is a message service that automatically notifies merchants of events related to PayPal transactions. Merchants can use it to automate back-office and administrative functions, including automatically fulfilling orders and providing customers with order status.
Step 1: In your PayPal Account, go to my account –> profile – my setting tools – instant payment notifications – update – choose IPN settings. Step 2: Paste the notification URL given and enable the option “* Recive IPN messages”.
View IPN messages and details. Use the IPN History page on the PayPal website to view IPN messages sent to your listener URL from PayPal, and to request that messages be resent. Select the IPN messages to review. You can specify a date range, delivery status, and PayPal transaction ID.
Instant payment notification (IPN) is a method for online retailers to automatically track purchases and other server-to-server communication in real time. This allows E-commerce systems the opportunity to store payment transactions, order information and other sales internally.
This is the easiest way I have found to do it, also as per PayPal suggests. I use http_build_query() to construct the url from the post that was sent to the site from paypal. Paypal docs states that you should send this back for verification and that is what we do with file_get_contents. you will note that I use strstr to check if the word 'VERIFIED' is present and so we continue in the function, if not we return false...
$verify_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate&' . http_build_query( $_POST );
if( !strstr( file_get_contents( $verify_url ), 'VERIFIED' ) ) return false;
PayPal is simply enforcing a higher standard of security for your own site/application's benefit.
IP spoofing can easily fool your example function, as relying on REMOTE_ADDRESS
alone is quite prone to attack.
When you are working with financial transactions security is of great importance. If I can spoof an IPN request, I can trick your site/application into performing false transactions. By sending an additional request to a known and trusted location, we obtain a much higher standard of credential upon which to act. The entire original IPN request is sent in this confirmation so that PayPal may verify that all of the transaction details are in fact valid, thereby preventing a Man-in-the-Middle Attack whereby an attacker modifies details (say, changing a price or quantity) of an otherwise valid request as it is sent from PayPal to your server.
I know this question is quite old, but:
The attacker does not even need to spoof his ip or perform any sort of MITM to pass your validation:
This attack is defeated by sending a request to paypal as recommended by Lobos.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With