How can I secure my IPN from bieng spoofed or secured? - node.js

I have an IPN for Paypal.
I have a simple NodeJS server using the express framework.
I have a simple post wrapper for the handler url of the PayPal IPN.
I have a simple check for IP address to check if the POST request came from PayPal.
My problem is that if someone spoofs the IP Address and sends POST Requests to the IPN Handler, they can effect my back-end system as the IPN handler has functions that are determined from the POST data.
How can I make this more secure?
Thanks.

Preventing IP spoofing isn't something you can do server side. What you could do potentially is implement mechanisms to asses whether or not an IP is valid and see where it potentially comes from. Afterwards you could limit the IP's themselves to whatever is acceptable for you solution.
The spoofing part is client-side, meaning that if the client uses a Proxy for example he could spoof the IP through that and you wouldn't be able to tell straight away.
Check out this short article for a bit of general idea (https://www.kaspersky.com/resource-center/threats/ip-spoofing)

IPN is a very old, very clunky service. You probably shouldn't be using it. There are invariably superior and more reliable ways to accomplish whatever it is you are trying to do with PayPal, including synchronous server-side capture or, only when necessary for certain asynchronous notifications, Webhooks
But if, for some strange reason, you insist on integrating such an old service as a payment dependency, its architecture has a built in verification step where you post the IPN message back to PayPal to have it verified. See https://developer.paypal.com/docs/api-basics/notifications/ipn/IPNIntro/#ipn-protocol-and-architecture

Related

Nodejs Express, How to rate limit each user of my website when calling my API?

I have cors installed and only my website is whitelisted, how reliable is this? Can bad actors still call my api if they are not calling it from my website?
Next I want to rate limit each user on my website, (the users are not registered or signed in),
I want to restrict each user to make no more than 1 request per second.
How can each user be identified? and then how can each user be limited?
Too many separate questions packaged together here. I'll tackle the ones I can:
I have cors installed and only my website is whitelisted, how reliable is this? Can bad actors still call my api if they are not calling it from my website?
CORS only works with cooperating clients. That means browsers. Your API can be used by anybody else with a scripting tool or any programming language or even a tool like CURL. So, CORS does not prevent bad actors at all. The only thing it prevents is people embedding calls to your API in their own web page Javascript. It doesn't prevent anyone from accessing your API programmatically from whatever tool they want. And, they could even use your API in their own web-site via a proxy. It's not much protection.
How can each user be identified? and then how can each user be limited?
Rate limiting works best when there's an authentication credential with each request because that allows you to uniquely identify each request and/or ban or delay credentials
that misbehave. If there are no credentials, you can try to cookie them to track a given user, but cookies can be blocked or thrown away even in browsers to defeat that. So, without any sort of auth credential, you're stuck with just the requesting IP address. For some users (like home users), that's probably sufficient. But, for corporate users, many, many users may present as the same corporate IP address (due to how their NAT or proxy works), thus you can't tell one user at a major company from another purely by IP address. If you had a lot of users from one company simultaneously using the site, you could falsely trigger rate limiting.

How to make Node API only accessible by web app?

I'm developing a web app with React and an GraphQL API with Node.js / Express. I would like to make the API more secure so that its harder for API requests that don't come from the web app on the browser to get data. I know how to do it with registered users. But how to make the non-registered user still be able to access some basic data needed for the app?
Is it possible to put some kind of key in the web app - so the API call can't be replicated for others through sniffing the network dev tool in browser and replicating in Postman? Does SSL/TLS also secure requests in that browser tool? Or use like a "standard" user for non-registered visitors?
Its a serverside web app with next.js
I know theres no 100% secure api but maybe its possible to make it harder for unauthorized access.
Edit:
I'm not sure if this is a problem about CSRF because Its not about accessing user data or changing data through malicious websites etc. But its about other people trying to use the website data (all GET requests to API) and can easily build there own web app on top of my api. So no one can easily query my api through simple Postman requests.
The quick answer is no you can't.
If you trying to prevent what can be describe as legit users form accessing your api you can't really do it. they can always fake the same logic and hit your webpage first before abusing the api. if this is what your trying to prevent your best bet is to add rate limiting to the api to prevent a single user from making too many request to your api (I'm the author of ralphi and
express-rate-limit is very popular).
But if you are actually trying to prevent another site form leaching of you and serving content to their users it is actually easier to solve.
Most browsers send Referrer header with the request you can check this header and see that requests are actually coming from users on your own site (this technique is called Leech Protection).
Leaching site can try and proxy request to your api but since they all going to come from the same IP they will hit your rate limiting and he can only serve a few users before being blocked.
One thing the Leecher site can do is try to cache your api so he wont have to make so many requests. if this is a possible case you are back to square one and you might need to manually block his IP once you notice such abuse. I would also check if it's legal cause he might be breaking the law.
Another option similar to Referrer is to use samesite cookies. they will only sent if the request is coming directly from your site. they are probably more reliable than the Referrer but not all browsers actually respect them.

How to create private api that can only be accessed by the front-end?

I've been looking over the web for a little while but couldn't grasp the concept of making private API only between front-end and back-end. what I essentially want to do is to have an API that's only accessible through the front-end, not through curl, postman or anything else.
I have the following setup:
App is hosted on Heroku, backend is in nodejs
I use https connection that I self-generated via let's encrypt tool.
I have a public API atm that returns a string 'Hello world'
Currently, you can access it either via front-end or by going to www.example.com/api/test but what I would like to do is not allow the user to manually visit the link or use curl or postman to get that but instead only make it accessible through the front-end.
The front-end is written in Angular 2 (if it matters at all)
Note, that I am not planning to have any user sign in on the website, I simply want to restrict access to the API to outside world so that only my front-end can get it.
UPDATE USE CASE
The use case in the future is simple. I have a basic sign up form which asks for email address and a text description. I then use nodemailer on the backend to send that information to the gmail using POST request from Angular 2. I access the data sent through req.on('data') and req.on('end') and process it. My fear is how do I make sure I am not gonna get spammed through that API and receive 10k emails hence my wish to somehow make the API only accessible through the front-end.
While you cannot prevent a REST service from being called by the whole internet, you can still prevent spamming :
Your service requiring authentication or not, it's always the same mechanism, using a captcha ( the most important part ) and rate-limiting your API.
1. CAPTCHA :
The best way to ensure that the client making the request to a server is driven by a human-being is a captcha.
CAPTCHA :
A CAPTCHA (a backronym for "Completely Automated Public Turing test to tell Computers and Humans Apart") is a type of challenge-response test used in computing to determine whether or not the user is human.
You can find plenty of services, or libraries that will create captchas, like Google's reCAPTCHA.
2. rate limiting :
For a public service, you can rate-limit access by IP : if the same IP makes 10, 100, or even 1000 requests (depending on the purpose of that service), that's a bit suspicious, so you can refuse to serve him, by sending an error status, and logging that unfair behavior to the application logs. So the sysadmin can ban the IP at the firewall level with a tool like fail2ban.
For an authenticated service, well that's the same except you might also want to rate-limit the API based on the IP and on its identity, and might not want to ban an authenticated user...
Note that you don't really have to handle the rate-limit yourself, for a public API, meaning that preventing the same IP to make 1000 POST request to the same url in 10 seconds is something that can and should be done by a sysadmin.

Securing a payment gateway POST

I'm setting up a payment gateway on our site that we can post information to via php (so all information is hidden from prying eyes) which will post to authorize.net, post back to our gateway and post back to our current page. The purpose for this is to give us a streamlined method of processing payments and easier debugging.
I have an auth key that is required to be posted to our gateway for the transaction to be processed. Is it worth it for me to secure a list of approved URLs to accept posts from, or is that too easily manipulated?
Do you have any other ideas on what I should focus on in regards to securing my gateway?
update
This gateway has a login/key pair used for authorize.net that it submits to. I have a 64 digit md5 encoded key that I use for domain.com to communicate with gateway.domain.com which happens of course over SSL. I'm inquiring as to whether that key is enough. Given, anyone with that key could run a transaction, but why would they... it would only be giving us money.
A list of approved URLs will do very little to protect your gateway:
curl -H "Referrer: http://happy.example.com" -D "pay_to=evil#example.com&amount=$100,000" http://example.com/gateway.php
You should take a look at using something like OAuth, where each request contains a unique token that only an authorized actor could provide.
Also remember that POSTing data only provides the illusion of security. It's easy (nay, trivial) to see what data is posted.
Oh, and this should be a no-brainer, but make sure you're using SSL.

pass secure information from one server to another

The situation is this:
A payment is made to one server, and on completion, it must notify another server securely. What I am trying to do is actually quite similar to a notify_url of a payment service. I.E. paypal receives a payment, and then notifies the origin through a long URL.
How does one verify the data being passed. Any useful libraries? Any links to get me started?
Thanks!
HMAC is a good way to ensure that the URL has not been generated by an unauthorized party or tampered with in any way. Here is a simple tutorial.
If the URL (or the content it returns) contains any sensitive information, then you'll also want to make sure that the recipient server is SSL enabled.
And for a further layer of security, you could hard-code the recipient server to reject any connections that aren't from the IP address(es) of your known sender(s).

Resources