How to protect a private REST API in an AJAX app - javascript

I know that there are many similar questions posted, but none of them refers to an HTML/javascript app where the user can access the code.
I have a private REST API written in nodejs. It is private because its only purpose is to server my HTML5 clients apps (Chrome app and Adobe Air app). So an API key is not a good solution since any user can see the javascript code.
I want to avoid bots creating accounts on my server and consuming my resources.
Is there any way to acomplish this?

An API key is a decent solution especially if you require constraints on the API key's request origin; consider that you should only accept an API key if the originating web request comes from an authorized source, such as your private domain. If a web request comes from an unauthorized domain, you could simply deny processing the request.
You can improve the security of this mechanism by utilizing a specialized encoding scheme, such as a hash-based message authentication code (HMAC). The following resource explains this mechanism clearly:
http://cloud.dzone.com/news/using-api-keys-effectively

What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android (I'm not as familiar with how to do this on other mobile platforms), both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

Related

How to secure the source code of react native application?

I am building an application that has auth system and a lot of post requests,
I want to know how to make my backend endpoints accept only requests that are coming from my application, not from anything else like Postman.
For example, if a user submitted a registration form, a post request is sent to my backend with user info, how can I make sure this post request is coming from my application?
What I was thinking of, is saving a secret on the client’s side that is to be sent with each request to the backend, so that I can make sure the request is coming from my app.
I think SSL pinning is meant for this.
I know that anyone can access my app source code if they extract the APK file.
I want to make sure that no one can alter or steal my source code.
I read that I can make my code unreadable by Obfuscating it ( I still need to figure out how I am going to do that on my EAS build ), is this enough?
And I have to use JailMonkey to detect if the device is rooted.
I am using Expo secure store to save my sensitive info on the client side.
Is this approach good enough, is there anything I am missing?
I have zero information about security, this is just what I learned through searching.
Let me know if you have better suggestions.
Thank you in advance.
The Difference Between WHO and WHAT is Accessing the API Server
I want to know how to make my backend endpoints accept only requests that are coming from my application, not from anything else like Postman.
First, you need to understand the difference between WHO and WHAT is accessing the API Server to be in a better position to look for a solution to your problem.
I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
So think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
When you grasp this idea and it's ingrained in your mindset, then you will look into mobile API security with another perspective and be able to see attack surfaces that you never though they existed before.
Certificate Pinning and MitM Atacks
What I was thinking of, is saving a secret on the client’s side that is to be sent with each request to the backend, so that I can make sure the request is coming from my app. I think SSL pinning is meant for this.
Certificate pinning on the mobile app side serves to guarantee that the app is talking only with your API server and not anything else, like when a MitM attack occurs and the app has its requests intercepted, and potentially modified and/or replayed, or simply saved to later extract the secrets from it.
Pinning doesn't guarantee to your API server that the request is coming indeed from what it expects, a genuine and unmodified version of your mobile app, "unless" you implement mutual pinning, that isn't encouraged to do so, because you will need to ship the private key for the API server certificate in the mobile app. Even if you do so, all an attacker needs to do is to extract the private key and will be able to communicate with your API server like if it was your genuine mobile app.
I don't have an article to implement pinning on a react-native mobile app but you can take a look to the one I wrote for Android to understand better all the process. Read my article Securing HTTPS with Certificate Pinning on Android on how you can implement certificate pinning and by the end you will understand how it can prevent a MitM attack.
In this article you have learned that certificate pinning is the act of associating a domain name with their expected X.509 certificate, and that this is necessary to protect trust based assumptions in the certificate chain. Mistakenly issued or compromised certificates are a threat, and it is also necessary to protect the mobile app against their use in hostile environments like public wifis, or against DNS Hijacking attacks.
You also learned that certificate pinning should be used anytime you deal with Personal Identifiable Information or any other sensitive data, otherwise the communication channel between the mobile app and the API server can be inspected, modified or redirected by an attacker.
Finally you learned how to prevent MitM attacks with the implementation of certificate pinning in an Android app that makes use of a network security config file for modern Android devices, and later by using TrustKit package which supports certificate pinning for both modern and old devices.
Bypassing Certificate Pinning
I think SSL pinning is meant for this.
The good news is that you already learned how good pinning is to prevent MitM attacks, now the bad news is that it can be bypassed, and yes I also wrote an article on how to it on Android (sorry to not be specific on react-native). If you want to learn the mechanics of it then read my article How to Bypass Certificate Pinning with Frida on an Android App:
Today I will show how to use the Frida instrumentation framework to hook into the mobile app at runtime and instrument the code in order to perform a successful MitM attack even when the mobile app has implemented certificate pinning.
Bypassing certificate pinning is not too hard, just a little laborious, and allows an attacker to understand in detail how a mobile app communicates with its API, and then use that same knowledge to automate attacks or build other services around it.
Code Obfuscation and Modifying Code
I know that anyone can access my app source code if they extract the APK file. I want to make sure that no one can alter or steal my source code.
Sorry, but once you release it to the public is up for grabs for everyone, even if heavily obfuscated its still possible to modify it statically or during runtime.
I read that I can make my code unreadable by Obfuscating it ( I still need to figure out how I am going to do that on my EAS build ), is this enough?
No, you can use the best obfuscation tool, but then an attacker well versed in deobuscation techniques will be able to understand your code and modify it statically or at runtime. Several open-source tools exist to ake this easy, and if you read the article to bypass certificate pinning then you already saw an example of doing it at runtime with Frida:
Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.
RASP - Runtime Application Self-Protection
And I have to use JailMonkey to detect if the device is rooted.
Using Frida the check can be modified to always return that the device is not rooted. Also JailMonkey may not detect all ways used to hide that a device is rooted, and this a moving target, because hackers and developers are in a constant cat and mouse game.
Sensitive Info Security
I am using Expo secure store to save my sensitive info on the client side.
Even when a secret is securely stored it will need to be used at some point, and the attacker will hook Frida to this point and extract the secret or do it in a MitM attack.
Possible Solutions
Is this approach good enough, is there anything I am missing?
From all I wrote it looks no matter what you are doomed to failure in properly secure your sensitive info and to guarantee that your API server knows that what is making the request is the genuine mobile app it expects, but security its all about of applying as many layers of defences as possible, like done in medieval castles, prisons, etc., because this will increase the level of effort, time and expertise required to succeed in an attack.
You now need to find a solution that allows you to detect MitM attacks, tampered and modified apk binaries, Frida present at runtime and that can deliver a runtime secret to mobile apps that pass a mobile app attestation that guarantees with a very high degree of confidence that such threats are not present. Unfortunately I don't know any open-source project that can deliver all this features, but a commercial solution exists (I work there), and if you want to learn more about you can read the article:
Hands-on Mobile App and API Security - Runtime Secrets Protection
In a previous article we saw how to protect API keys by using Mobile App Attestation and delegating the API requests to a Proxy. This blog post will cover the situation where you can’t delegate the API requests to the Proxy, but where you want to remove the API keys (secrets) from being hard-coded in your mobile app to mitigate against the use of static binary analysis and/or runtime instrumentation techniques to extract those secrets.
We will show how to have your secrets dynamically delivered to genuine and unmodified versions of your mobile app, that are not under attack, by using Mobile App Attestation to secure the just-in-time runtime secret delivery. We will demonstrate how to achieve this with the same Astropiks mobile app from the previous article. The app uses NASA's picture of the day API to retrieve images and descriptions, which requires a registered API key that will be initially hard-coded into the app.
Do You Want To Go The Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
short answer you can't.
I want to know how to make my backend endpoints accept only requests
that are coming from my application, not from anything else like
Postman
the only thing you can do here is cors Cross-Site Request Forgery Prevention. Y to stop other servers from calling your api.
and you can't make only your application communicate with the server
you can hard code(parameters in the request) in the application to send to the server.but hackers can listen to request made from devices
I know that anyone can access my app source code if they extract the
APK file. I want to make sure that no one can alter or steal my source
code.
short answer you also can't
you can use ProGuard(native code) to obfuscate on native android and ios have compiled binary on release but those are not to js
so basically anyone can read your bundle js in plain text editor.
maybe in the future facebook can make something for hermes.

How to embed the certificate for the web socket in angular application

I am working on an application that is suppose to receive the data over web sockets. I haven't worked with socket data before.
I am trying to directly connect to web socket server over wss from my Angular application. This however throws an ERR_CERT_INVALID error.
I assume, I need to provide some detail to the server for authentication in form of certificate keys.
How can I pass these details directly from my Angular10 client while creating the connection. Is it even possible to pass these details while making a connection from browser or do I need to use an intermediate server ?
Please suggest.
Validating the certificates for a connection is done inside the browser. There is no way for an Angular application to setup own certificate validation or add its own trusted certificates. To make it easy a publicly issued certificate should be used which automatically is checked and trusted by the browser. In case of a private certificate it would need to be explicitly added by all users to their browsers, i.e. there is no way to do this automatically from the Angular application.

This solution is safe to access to user's private certificate on a web with a webSoket communication?

We are developing a web page that use https protocol (two way).
We need to access to the private certificates of the user, because we need sign documents by the user's certificate, so we developed a Java application that communicate with the web by a websoket.
This application will call with a protocol call since the web (same that when you open a pdf on Acrobat Reader from a browser).
So we have to be sure that our web is calling to the native application(only our web). We want develop a system to be sure of that. Our idea:
Send a public key, a signed token by the server's private certificate and a symmetric key (to encrypt websocket communications) to the native application.
Next, we will Check in the native application that the token it is OK with a web service to the server.
After, we will have to open the websocket between the native app and the web, and send the signed document by the native app by this way.
Then sent document to the server.
Is this implementation safe? We will be safe of a man in the middle?
Any suggestion about this solution will be wellcome, because I don't see any weakness but I am not an expert on security.
I know other solutions for this problem, like applets, JavaFX or native messages on Chrome, but I only want to know if these solution is safe.
Thanks to all in advance and sorry if my english isn't the best :P,
I see the following issues
Send a public key and a signed token by the server's private certificate to the native application.
You are calling a local app by protocol. For example mylocalapp://sign?securitytoken=.... You do not control which application is installed on local PC to respond to mylocalapp://. The browser shows an ugly warning because you are leaving the secure environment. An attacker could have replaced the default app, simulate the flow and get all signed documents.
2.Next, we will Check in the native application that the token it is OK with a web service to the server.
To verify identity of server and avoid a ManInTheMiddel attach you need also to set a trustore for your application with the server certificate
Your server needs also to verify identity of client. Are you planning to use TLS two ways also?
After, we will have to open the websocket between the native app and the web, and send the signed document by the native app by this way.
You do not need a websocket. Simply use a URL connection to download and upload the documents.
This solution was used by Spanish ministry of economy when chrome decided to cut the NPAPI support and signature applets began to fail. Now, they have rebuilt the system in this way
Install a local Java application on the user's PC. The application listens on a port as, for example 5678
In your page, javascript connects to the application in the form http://127.0.0.1:5678/sign and sends the data to sign.
The application is local and has no trouble using the operating system keystore, which includes drivers PKCS#11. Perform digital signature and sends the result to the server
The javascript of the page periodically query the result and retrieves it when ready
The security problem is basically the same, but install a server in localhost is harder than replace the local default app.
The solution is called #firma, I guess you probably know it. It is opensource, you can use it

What is the correct CORS entry for limiting an http:// connection to a remote, hosted web server from a grunt web server on a home network?

I've setup a remote, hosted javascript server (DreamFactory Server http://www.dreamfactory.com/) that responds via REST API's.
Locally, I'm running an Angularjs application through the grunt web server via $grunt serve
https://www.npmjs.com/package/grunt-serve
I have setup CORS on the remote server to allow '*' for multiple http:// connection types. THIS WORKS CORRECTLY.
My question is how I can limit the CORS configuration to only allow a connection from my home, grunt web server?
I've tried to create an entry for "localhost", "127.0.0.1", also my home Internet IP that is reported from whatismyip.com, the dns entry that my provider lists for my home IP when I ping it, a dyndns entry that I create for my home internet IP... None of them work, except for '*' (which allows any site to connect).
I think it is an educational issue for me to understand what that CORS entry should look like to allow ONLY a connection from my home web server.
Is this possible? If so, what and where should I be checking in order to find the correct entry to clear in the CORS configuration?
-Brian
To work and actually apply restrictions, the client requesting the connection must support and enforce CORS. In an odd sort of way (from a security point of view), restricting access using CORS requires a self-policing client (one that follows the prescribed access rules). This works for modern browsers as they all follow the rules so it generally works for applications that are served through a browser.
But, CORS access restrictions do not prevent other types of clients (such as any random script in any language) from accessing your API.
In other words, CORS is really about access rules from web pages that are enforced by the local browser. It doesn't sound like your grunt/angular code would necessarily be something that implements and enforces CORS.
If you really want to prevent other systems from accessing your DreamFactory Server, then you will need to implement some server-side access restrictions in the API server itself.
If you just have one client accessing it and that client is using "protected" code that is not public, then you could just implement a password or some sort of logon credentials and your one client would be the only client that would have the logon credentials.
If the access is always from one particular fixed IP address, you could refuse connections on your server from any IP address that was not in a config file you maintained.
You can't secure an API with CORS, for that you will need to implement an authentication scheme on your server. There's essentially 4 steps to do this.
Update the headers your server sends with a few additional Access-control statements.
Tell Angular to allow cross-domain requests.
Pass credentials in your API calls from Angular.
Implement an HTTP Authentication scheme on your web server or in your API code.
This post by Georgi Naumov is a good place to look for details of an implementation in Angular and PHP.
AngularJS $http, CORS and http authentication

Tomcat and Browser to Openfire Authentication scheme

We are developing a web application that uses strophe.js to communicate with an openfire server for XMPP chat. The web application is hosted on tomcat and both tomcat and openfire reside on the same server. Strophe.js is using BOSH (essentially http long-polling) as a communication mechanism between the client and the openfire.
Our tomcat instance authenticates (form-based) using a users table in our database. We've configured our openfire instance to read out of the same table. That way mobile apps can directly connect to our chat server using the user's credentials
We also have apache running as a reverse proxy. This might be TMI for the problem at hand, but more information can't hurt. The url schemes look like the following:
http://myserver/web Our web interface. Goes to http://myserver:8080/
http://myserver/chat Forwards to the openfire BOSH url (what strophe.js connects to). Goes to http://myserver:7070/http-bind (openfire bosh endpoint)
The problem I'm trying to figure out is how to log in to our openfire server from the browser. For example, if the user goes to the login.jsp site and enters their credentials, the server will forward that user to index.jsp. The strophe.js connection will try to connect to the chat server (/chat), but at that point, the username and password is no longer available to the javascript code.
I need to figure out how to securely authenticate the user in the web browser with the openfire server AFTER authentication has occurred. I've looked around for some examples, but there's not much information out there (or rather, I don't know what to look for).
Some Possible Solutions
1.) The first strategy I tried was creating an AuthProvider implementation in openfire that can take the browser's cookie as the password, make an HTTP request to tomcat with that cookie, and if succeeds deem that user as authenticated. This worked at first, but when deploying I found that I needed to configure tomcat to allow the document.cookie to be populated with the JSESSIONID. After reading a bit about this, it seems that using cookies is not recommended from a security standpoint. Jeff Atwood has an post Protecting Your Cookies: HttpOnly that discusses the security issues stemming from cookies accessible to javascript. Although I am not completely opposed to using cookies, is there a better way?
2.) A solution I have also thought of (haven't implemented yet) was providing a REST endpoint to create tokens that the user can fetch once they are logged in and use as passwords for the openfire server. Seems a little better, but I'll need to create a new table, manage their expiration, etc.
If anyone has tackled this problem, please let me know. It would be greatly appreciated.

Categories

Resources