I have a website (PHP Laravel site) that uses Brainstree to process credit card payments. Today the site receives A LOT direct request to 1 url that passes in credit card information. It seems the hacker figures out our parameters and is using my site trying to validate their stolen credit card numbers.
Here is an example of a request.
http://mysite/renew?card_nubmer=42693111111111&ccv=014&expiration_month=11&expiration_year=2019&first_name=beqnykit&last_name=fozwgfrpn&postal_code=44101&type=visa&price=12year=1&country_name=USA¤cy=%24
It is causing the CPU usage to be 100%, slowing down my site.
Before our code was processing the request and display an error page. Now it validates the request and redirects invalid renew request to log in page. The CPU load is still 100%.
What can I do to stop this or stop the CPU load, at the least?
Enable the use of CSRF field, it's a must. You're saying you began handling the request as POST, so that's fine.
This route also has to be available for authenticated users only. Add a proper middleware if you haven't yet.
As for additional protection I would recommend to use some throttle middleware. Consider using this package or something similar. It will not allow to use the method more often than the number of times per minute you specify. https://github.com/GrahamCampbell/Laravel-Throttle
Here is the update. The hacker really analyzes the site. It create free users. Each free user uses a credit card to submit an order for a paid membership. We are a target because the amount is small. Using POST doesn't fix this hack. So we have added account activation email and recaptcha in account creation and order page. Luckily, it is stopped pretty quickly. I am just putting the info here to share experience. Thanks for all the help!
Related
Assuming a user completes their transaction successfully after being redirected to Mastercard for payment, but closes the browser before redirecting back to the vpc_ReturnURL supplied to the Omnipay driver, is there a way to handle this automatically?
The unfortunate short answer is that you can't handle it automatically directly via MiGS.
When using the 3-party version (Migs_ThreeParty), you are reliant on the end user coming back and hitting that completePurchase() method. You can set up cron jobs to detect 'abandoned' sales (which may or may not actually be abandoned) to manually reconcile in your Mastercard dashboard, but MiGS doesn't supply an option for a notifyUrl, nor any implementation of the acceptNotification() method for gateway-based notifications similar to PayPal's IPN. Sadly it also doesn't have a simple query URL for "is this transaction done yet" that you could attach to an abandoned-sale-checking cron job.
About the best you can hope for would be to talk to Mastercard and see if you can shorten the redirect time by automatically redirecting, or to have your return URL be a super-fast loading "do not close this window yet" page, which then does your completePurchase loading in the background.
Redirect/3-party gateways have this problem a lot. It is one of the reasons most merchants tend to prefer 2-party gateways (if they can be bothered with the PCI compliance) and has seen the rise of token-based gateways (so they can avoid the PCI compliance burden without the headaches of redirects).
We have an eCommerce site that is using Authorize.net as a payment gateway.
We have recently run into the issue of people submitting a payment confirmation, and then clicking submit again later on. This is resulting in a double-product situation, and/or double payment.
Some things to consider:
The payment confirmation page is a result of a PRG (Post-Redirect-Get) which is loaded before the user submits their payment
We have functionality in place that will actually act on each part of the request (see below for description of this)
This situation will only apply when Authorize.net transactions take longer than normal.
This is NOT in production yet, we are merely looking for a way to test this new functionality to prevent this behavior.
The Prevention Piece
We have a multi-step checkout form that follows the following process:
Product selection
Payment entry
Confirm Order / Submit Payment
Receipt
Each step of the process executes a call to a service that checks to see if the user has a current 'order' that has one of several statuses: started, processing or complete.
If the order is started, it will redirect them to the first page of the checkout flow.
If the order is processing, it will redirect them to a placeholder page that executes an ajax request every 2 seconds to check the status of the order. When the order is complete, they are redirected to the receipt page.
If the order is complete, they are redirected to the receipt page immediately.
The Problem
Since this functionality is really only valid when the processing transactions take a bit longer, it gives us problems testing it - for a few reasons:
Our dev server is slow, and it is more likely than not that Authorize.net will respond to our request before the page is even rendered by the application.
If we dummy the response up by using the PHP function sleep(), it blocks the thread and nothing runs, and we are in the same boat as [1].
What we hope
I do not know if there is a way to make Authorize.net respond to requests in a slower manner via some parameter, or if there is another way to accomplish this. I welcome ANY and ALL ideas!
You shouldn't be testing directly against Authnet for this. Make your own Authnet "server" and have it delay its response to you. For unit test I wrote for my Authnet library I created my own fake server which sends back the appropriate response I need to test. You can do the same and have the "server" wait as long as you need to before sending back a response. The response doesn't have to be real for you to test a delay.
I am developing a crowd-funding site (similar to Kickstarter) using the CodeIgniter framework.
I "successfully" implemented PayPal's adaptive payments using this library.
But, I'm just not sure how to correctly and securely check for succesfull/failed payments and witch data is important to save to database.
Note: it's a chained delayed payment, I am the primary receiver, and the secondary receiver is the crowd-funding project creator. The money is transferred to the secondary receiver after a predetermined period of time.
The flow I have right now goes like this:
User click to buy a reward.
I use the 'Pay' API operation to request payment (unique TrackingID included) and save the request in the database.
If the request is succesfull, I save some response data in the session (TrackingID, PayKey, amount, ...) and redirect to PayPal..
In this step the user can: accept payment, cancel, or just close the browser, so I dont really know what happens here... (recommendations?)
If the user accepts the payment, he is redirected back to my site and I use data I saved in the session to request a 'PaymentDetails' API operation to obtain information about the payment.
I save the result in database and check to see if the response 'amount' is equal to the request 'amount' (for security).
If everything went OK I update the database and connect the payment TrackingID with the user and the reward he bought.
Later (can be months later), the 'ExecutePayment' API operation is requested by an admin, and the money is transferred from us to the project creator, and we take a small fee (thats how crowd-funding works...)
Now, I'm sure I'm missing lot of things but I have no idea what:
What about the IPN API? I need it? Where it comes to play inside the flow and checks?
What I do if the user closes the browser window when he is in PayPay (out of my site).
I heard that the PayKey is valid for 3 hours, how can I 'ExecutePayment' after months?
How I handle the enormous amount of error types in the PayPal API?
Any tips or examples of others things I need to take care of? Security? Errors? Others?
Thank you very much, I really need your answer!
IPN will automatically POST data to your "listener" (which you'd need to develop) in order to automate post-payment procedures. For example, you could update a database, hit 3rd party web services, generate email receipts, etc. within IPN so that those events happen automatically any time you receive money in your PayPal account. You can also set it up to handle refunds, disputes, and other events. It's not required, but often very useful.
This is one reason IPN can be useful. IPN will be triggered whether the user makes it back to your site or not. If you're doing post-payment processing procedures within your thank you page or something like that, I'd recommend you move it into an IPN solution.
The PayKey is indeed valid for 3 hours when being used as a token. When you call Pay with an ActionType of CREATE, though, it sets up a delayed payment and the PayKey is then valid for up to 90 days.
The error information will always come back in the same format in the response. You can just log or display errors accordingly based on this standard response.
Sounds like you're pretty much on top of everything for the most part.
I have a <textarea> along with user registration information that I only want to be processed (inserted to the database) after payment (I want to keep my database clear unnecessary registrations or things like people that register but change their mind about paying for the site services)
I mean, I could use sessions but are there any other ways?
I was looking for a gateway that'll pass these variables back to me after purchase.
Or perhaps just having the gateway API.
Now, I know gateways such as paypal allow advanced processes like these but I don't want to apply to their credit checks just in case they have a reason to reject me. I don't want to depend on one gateway, is there any other gateways that guarantee not to reject my gateway needs and allow me to make advanced processes like the ones mentioned above? If anyone knows about gateways that don't need credit-type checks to be accepted I would appreciate if one could be suggested.
Note: I know some people will suggest to keep the registration data since it's only a few kilobytes even if people won't use the site or pay for the services. Call me OCD but I like my database clean and to only have relevant users/data. I will end up doing this in the end if I don't find a solution that suits my needs, so please, don't suggest it. Thanks.
If you want to use simple form based integration, you aren't going to get around having rows in your table before the users has been processed, unless you want people stealing your service. The fact you want your "database clean" is naive. Just put a registered flag and delete periodically if you are really that OCD.
You must create a auth token (random unique string), and update the database of the current user that that token belongs to that user. You then pass the user to the payment gateway and also pass along the token you have assigned to that user.
The gateway will send the user back to a url of your choosing, along with the token you have assigned to that user. At this point you update the table for that user with that token.
Only you and the gateway know about the token, the user only sees it if they get a successful charge.
If you don't do this, anyone can find the url the gateway sends on successful charge, and just load it themselves, giving them free service.
Alternatively, you can use deeper integration, were you do a web service call to the payment gateway, if it succeeds, you update your row, if it fails, you don't. This subjects you to onerous PCI compliance regulations. Trust me you don't want to delve into that. Just avoid it and do not let your systems see any CC information.
I'm going to use one of the payment gateways and so users from my site will be redirected to gateway hosted page to provide all the CC details. Gateway will return results to the page which I specify (lets call it paymentProcessed.php). But now my worry is that:
someone might fake it. What I mean is that someone might be redirected to payment gateway, then instead of paying, will return results to my site paymentProcessed.php page with confirmation that all has been payed. This confirmation will be send by the user itself via normal POST, and my site then will deliver products to the user although there was no actually payment done. What is the common practice to avoid this kind of situation?
Someone is redirected to gateway hosted page, pays, redirects back to my site and session he was logged in with has expired. Usually I rely on sessions to see if user should be allowed access to certain parts of the site, but now do I need to implement some other sort of check for confirmation page? For now I was thinking of storing order id and randomly generated value in database, when user redirected pass it to gateway (together with total, total would be passed to gateway and then back so I could confirm that proper amount was paid). Then when confirmation comes together with order id, my randomly generated value (and total) instead of relying on session like I usually do for normal shopping cart pages, I should check this value with matching order id and change status of order as needed. What is the common practice to deal with that kind of problem?
What other possible issues I should think about?
I tried to explain as clearly as possible and I hope all above makes sense. please let me know if I need to clarify something though. btw I code in php/mysql
It's actually easier and more secure then you realize. When using a hosted payment page, like Authorize.Net's SIM API, a hash of some sort is included that only you and the processor know about. It is impossible to fake as generating it requires private information only you and the processor have. So all you need to do is verify that the hash sent to your return page by the payment processor matches the one you have for the transaction. If it does, you can be 100% sure the transaction has not been spoofed.
Sessions tend to last longer then a trip to a remotely checkout form usually takes to complete and the session does last even though a user leaves your site. But, if you are concerned about a session expiring before they return to your site, simply store the session information in a database and use a cookie to track the user. Then when they come back use the cookie to identify them and retrieve their session information from your database.
UPDATE:
Here's how you can make your session cookie last longer with PHP:
// Makes the cookie last two hours. Make it a higher number to last longer.
session_set_cookie_params(7200);
session_start();
I've implemented some payment gateways already, one thing in common with all of them is that card processor will always return the transaction status for you, some of them use a weak redirect relaying on users to accomplish, others allows you to use their webservice to authenticate transactions. Either way you will need to get processor docs to know how to authenticate the transaction on your side.
Now about the other odds to avoid sessions from expiring you might want to store all transaction data on a table, you can also have sessions to speed up the process, but you don't need to go much further to see issues with relaying only on sessions:
What if the user gets disconnected in the middle of process?
Some CC processors force you to open a popup to process, what if the user closes it?
What if the server crashes?
What if the payment method failed and user wants to retry with another type of payment?
Now some random thoughts about payment gateway implementation:
Some processors delay to authenticate the purchase, they will return to your site that the payment has been accepted but you will have to use their webservice to check the final status;
Some processors require you to capture the purchase, meaning that even if it was approved you can void or finalize it later, this is good to avoid carders from purchasing things off your site, you can check user's info to make sure it's all good them capture or void the purchase avoiding a chargeback.
If your credit card processor gives you access to a webservice or they do server to server purchase authentication this will require a valid ssl certificate, so be aware.
That's all i can recall by now.