PayPal returnURL security - security

Summary: I want to use the returnUrl as a proof that the transaction has been accepted by PayPal.
I'm implementing a very basic purchase workflow based on PayPal.
Everything works nice, the User clicks on pay, the User goes to PayPal, PayPal sends the User to my returnURL... and I'm accepting the payment in this last step.
I know I would have to implement an IPN endpoint and accept the payment there, but this project is very basic and I'm too old or too lazy to implement all this asynchronous behavior which can be a hell of edge-cases.
Would be nice if I would just make the returnUrl more confident, difficult to fake.
I was thinking that there would be the possibility that in the returnURL there would be included a checksum signature based in a secret key stored in the PayPal account and in the actual transaction token
I don't know if this exists, I didn't find any of this into the documentation, any suggestion to make the returnUrl more confident is welcome.
Also if someone thinks I'm completely wrong and the returnUrl is never gonna be a proof that the transaction has been accepted please express your self.

When you're just doing the return URL you need to post to PayPal again to verify the transaction using your PDT token.
Say your return URL is Thanks.aspx:
"From the code-behind of Thanks.aspx, you'll parse the tx value and make an HTTP POST to https://www.paypal.com/cgi-bin/webscr with the following parameters: cmd=_notify-synch&tx=[TransactionID]&at=[PDTIdentityToken]."
This will respond with whether or not that request was valid.
The problem is that this page isn't guaranteed to get hit. The user could close their browser, or their internet could get cut off, or anything else.
The IPN will be getting hit from PayPals servers, and you really can't beat that.
It's pretty easy to set up, but I suggest reading through this document which will explain the PDT and IPN methods, and gives an easy way to figure out what you need.
http://www.codeproject.com/Articles/42894/Introduction-to-PayPal-for-C-ASP-NET-developers?msg=4382854#xx4382854xx

After completing an installation for Express Checkout I realised how it could be exploited.
Even though I am creating a unique invoice number and returning to mark that as paid, I found that it could still be exploited by a user changing the invoice parameter in the return link. Of course there were already checks to ensure that any invoice could only be paid once, but I needed to make it hack proof.
So what I finished up doing was adding some extra checks to ensure that the invoice in question was the last invoice assigned to that user. Yes, the same session ID is maintained aven after a visit to Paypal and back.

Related

Is there another way to embed the recipient view in app with URL which has much longer valid time?

From the official doc:
https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient/
Returns a URL that enables you to embed the recipient view of the DocuSign UI in your applications.
The URL is time-limited
The URL returned by this method is valid for one use, and you must use or display it within a couple of minutes after it is generated. After the recipient is redirected to the recipient view, they must interact with the DocuSign system periodically or their session will time out.
I am trying to make a envelope and get a URL embed the recipient view in my app? But from the doc, EnvelopeViews:createRecipient would only a URL which have a couple minutes lifetime.
I want the URL to be valid for much longer time. I want to store URL in DB for future use.
It would be better that I can configure expiration date.
Is there another way for DocuSign API which can meet my need ?
First off, these restrictions you mention are security related. And are there to ensure that the URL is not accidently exposed to the wrong person. This is just one of many defense mechanisms making DocuSign super secure.
The best thing to do is generate the URL only when your user is ready to sign. Storing it in DB is not good practice for many reasons. You can store envelopeId in your DB and make the API call only when needed to generate the URL.
For more details please find article on this exact topic:
https://www.docusign.com/blog/developers/long-lived-embedded-signing-urls

PayPal and Microsoft WebAPI: best security approach

I'm creating a WebApi project that aims to handle payments in my project.
Actually, my approach is like:
CreatePaymentMethod(creates the payment, contact paypal and redirect the user to the payment page. If payment is done, redirect to PaymentApprovalMethod)
PaymentApprovalMethod (confirm the payment on my system, allowing the user to access the content)
What I'm wondering is... What if an users directly creates a message to invoke the PaymentApprovalMethod?
Suppose:
- CreatePaymentMethod is called, user sniffs with Fiddler the Transaction ID of the redirect
- Creates and adhoc call of the PaymentApprovalMethod like.
I see two possibles scenario to handle this situation:
Restrict (I don't know how) the calling of PaymentApprovalMethod to the messages from Paypal only
Cross Check the payment inside the PaymentApprovaMethod (ok, user, you said the transaction ID 123 is done, I'll contact paypal to verify this before trust this call)
The second one seems more safe but also more "time / resource" problematic..
Do I'm missing something? Is there something else I can do to avoid this problem?
Take a look at Instant Payment Notification (IPN). PayPal's system will POST transaction data to a listener script that you setup for all transactions on your account, be it a payment, refund, dispute, cleared payment (from pending), etc. You can use this to completely automate many post-payment procedures.
Part of your IPN listener will include a call back to PayPal's server to verify that the data actually came from them. You can then log IPN's separately, and only process verified IPN's, which means you know somebody didn't just POST directly to it on their own.
Some people do go a step further and only accept traffic to that script from PayPal's IP addresses, however, they do change their addresses quite a bit and I think that just becomes a hassle. The verification has always been enough for me.
IPN is definitely what I would recommend for you.

Can SagePay's callback be validated to prevent hacking?

SagePay's form callback can be hacked by re-using the success URL that the user is directed to upon a successful transaction. This can create all sorts of problems with duplicate transactions, fake transactions etc.
You can check for a duplicate VPSTxId, but these can be generated anew by hacking around the crypt parameter of the callback URL.
The crypt parameter can also be manipulated to generate a different "Amount" field.
I have not tested what other field values can be changed by hacking the callback URL crypt parameter.
Is there any way (as per PayPal's IPN validation) of doing a double-check callback to SagePay to ensure that the transaction is new and unique?
Thanks for your post. In general we encourage clients to use Server integration where they can. We also constantly monitor transactions for suspicious behaviour and proactively contact our customers if we suspect any malicious activity.
We recommend customers make sure that they’re using the latest version of our integration protocol which is currently v3. Get the latest integration documents.
As Dan suggests you could use the Reporting and Admin API to validate that a transaction does indeed exist on the Sage Pay side but having an additional validation mechanism (like PayPal's IPN) is something we will actively explore.
If you'd like us to update you on this, then please get in contact with our customer services team at support#sagepay.com or 0845 111 44 55.
Sage Pay Support
You should always redirect a user from a success URL.
I personally use a fulfil page (success url), and a thank you page. On the fulfil page, you should obviously only ever process a transaction once (based on the transaction id), and you can store crypt sent with a transaction. The crypt will have to be valid and is only possible to encrypt if you have the encryption key.
So hacking would be extremely difficult unless you are being very security lax, and the hacker would have to know your encryption key to even begin trying to hack it.
Alternatively, you should use the server integration, so that the communications are server-server, not client-server. There is little difference between form and server.
10 immutable laws of security
http://technet.microsoft.com/library/cc722487.aspx

Posting transactions to PayPal and security

PayPal has a method where we can post our transaction to PayPal via a form.
Isn't it possible for someone to construct our form and post to PayPal over and over again?
I know no real harm can happen as they would have to enter their CC information on PayPal to continue, but they could cause a lot of trouble by posting hundreds of fake transactions.
Is there any way to prevent this type of situation?
Does PayPal have anything that tells it to only accept form posts from certain sites/pages?
If you mean their NVP API, then PayPal's documentation tells you how they avoid that problem (known as a "replay attack", because an attacker is replaying the same data sent by the legitimate user). The posting application must send a username, password and signature, which the developers must not disclose to anyone and which is sent over secure transport as part of the API procedure. An attacker trying to pose as the developer does not know the username, password or signature and cannot submit false requests to PayPal.
That doesn't stop the attacker from misusing the input of the application (i.e. the browser page seen by application users, which causes the application to make PayPal requests), that bit being up to you :-).

What are best practices for activation/registration/password-reset links in emails with nonce

Applications send out emails to verify user accounts or reset a password. I believe the following is the way it should be and I am asking for references and implementations.
If an application has to send out a link in an email to verify the user's address, according to my view, the link and the application's processing of the link should have the following characteristics:
The link contains a nonce in the request URI (http://host/path?nonce).
On following the link (GET), the user is presented a form, optionally with the nonce.
User confirms the input (POST).
The server receives the request and
checks input parameters,
performs the change,
and invalidates the nonce.
This should be correct per HTTP RFC on Safe and Idempotent Methods.
The problem is that this process involves one additional page or user action (item 3), which is considered superfluous (if not useless) by a lot of people. I had problems presenting this approach to peers and customers, so I am asking for input on this from a broader technical group. The only argument I had against skipping the POST step was a possible pre-loading of the link from the browser.
Are there references on this subject that might better explain the idea and convince even a non-technical person (best practices from journals, blogs, ...)?
Are there reference sites (preferably popular and with many users) that implement this approach?
If not, are there documented reasons or equivalent alternatives?
Thank you,
Kariem
Details spared
I have kept the main part short, but to reduce too much discussion around the details which I had intentionally left out, I will add a few assumptions:
The content of the email is not part of this discussion. The user knows that she has to click the link to perform the action. If the user does not react, nothing will happen, which is also known.
We do not have to indicate why we are mailing the user, nor the communication policy. We assume that the user expects to receive the email.
The nonce has an expiration timestamp and is directly associated with the recipients email address to reduce duplicates.
Notes
With OpenID and the like, normal web applications are relieved from implementing standard user account management (password, email ...), but still some customers want 'their own users'
Strangely enough I haven't found a satisfying question nor answer here yet. What I have found so far:
Answer by Don in HTTP POST with URL query parameters — good idea or not?
Question from Thomas -- When do you use POST and when do you use GET?
This question is very similar to Implementing secure, unique “single-use” activation URLs in ASP.NET (C#).
My answer there is close to your scheme, with a few issues pointed out - such as short period of validity, handling double signups, etc.
Your use of a cryptographic nonce is also important, that many tend to skip over - e.g. "lets just use a GUID"...
One new point that you do raise, and this is important here, is wrt the idempotency of GET.
Whilst I agree with your general intent, its clear that idempotency is in direct contradiction to one-time links, which is a necessity in some situations such as this.
I would have liked to posit that this doesn't really violate the idempotentness of the GET, but unfortunately it does... On the other hand, the RFC says GET SHOULD be idempotent, its not a MUST. So I would say forgo it in this case, and stick to the one-time auto-invalidated links.
If you really want to aim for strict RFC compliance, and not get into non-idempotent(?) GETs, you can have the GET page auto-submit the POST - kind of a loophole around that bit of the RFC, but legit, and you dont require the user to double-optin, and you're not bugging him...
You dont really have to worry about preloading (are you talkng about CSRF, or browser-optimizers?)... CSRF is useless because of the nonce, and optimizers usually wont process javascript (used to auto-submit) on the preloaded page.
About password reset:
The practice of doing this by sending an email to the user's registered email address is, while very common in practice, not good security. Doing this fully outsources your application security to the user's email provider. It does not matter how long passwords you require and whatever clever password hashing you use. I will be able to get into your site by reading the email sent out to the user, given that I have access to the email account or am able to read the unencrypted email anywhere on its way to the user (think: evil sysadmins).
This might or might not be important depending on the security requirements of the site in question, but I, as a user of the site, would at least want to be able to disable such a password reset function since I consider it unsafe.
I found this white paper that discusses the topic.
The short version of how to do it in a secure way:
Require hard facts about the account
username.
email address.
10 digit account number or other information
like social security number.
Require that the user answers at least three predefined questions (predefined by you,
don't let the user create his own questions) that can not be trivial. Like "What's
your favorite vacation spot", not "What's your favorite color".
Optionally: Send a confirmation code to a predefined email address or cell number (SMS) that the user has to input.
Allow the user to input a new password.
I generally agree with you with some modification suggested below.
User registers at your site providing an email.
Verification email is sent to the users account with two links:
a) One link with the GUID to verify the registration b) One link with the GUID to reject the verification
When they visit the verification url from their email they are automatically verified and the verification guid is marked as such in your system.
When they visit the rejection url from their email they are automatically removed from the queue of possible verifications but more importantly you can tell the user that you are sorry for the email registration and give them further options such as removing their email from your system. This will stop any custom service type complaints about someone entering my email in your system...blah blah blah.
Yes, you should assume that when they click the verification link that they are verified. Making them click a second button in a page is a bit much and only needed for double opt in style registration where you plan to spam the person that registered. Standard registration/verification schemes don't usually require this.

Resources