Parse Security: Securing Your Open Source App Stack
What Is Parse?
Parse is the most commonly used open source framework for developing application backends. It was introduced in 2016 and is backed by a large community of developers. It is a proven platform that can accelerate web application developments at any scale.
Parse is a Node.js application that is deployed on hosts in a cloud platform like AWS. It provides APIs for user authentication and stores data in a MongoDB document store. By combining a mobile SDK with a backend service, Parse provides features including several user authentication methods, social login, creation and querying of arbitrary data models, push notifications, and the ability to upload files to a server for client-to-client access.
Open source security is a major concern for most organizations. While open source platforms like Parse can be highly beneficial, they often present vulnerabilities that must be identified and resolved. Here are some of the main security concerns with the Parse platform.
Parse tries to accommodate less technical developers, making it easier to produce the entire backend for mobile applications without programming. Developers can handle all or most of the server setup, including creating and inserting classes, via the Parse dashboard. However, some important security features are not enabled by default, so users must configure the right settings to secure their application stack.
All stored data in Parse resides in class objects, with the users class storing all user data by default. These class objects should not be automatically searchable, especially if they contain sensitive data. Parse lets developers restrict access to object classes using object-level access control and class-level permissions.
These security features offer more granular control over stored data in Parse instances and prevent unknown users from accessing any instance in a protected class. However, the user has to turn them on—otherwise, all class objects in Parse remain searchable, and anonymous, potentially malicious users could access sensitive data in objects like the users class.
Automated file upload is a requirement for many web applications. Another major vulnerability in the design of the Parse server is the file upload functionality. The file adapter submodule allows the Parse server to upload all files by default. Users can block uploads of specific file types using hooks in Parse Cloud. It is still impossible to prevent a potential attacker from uploading file types via the Parse dashboard, a popular GUI for developers to work with the Parse server.
Once a file is uploaded, it is accessible without authentication headers, so an attacker could easily share it. The only way to mitigate this risk is to obfuscate the name of uploaded files. This method can make finding the files uploaded to a bucket harder, but it doesn’t stop attackers from uploading malicious HTML files to the server or sharing malicious URLs with the victim.
Applications typically serve the uploaded Parse files from the primary domain, creating serious vulnerabilities for all users. If an application serves uploaded files from the same domain as a web portal with cookies, it may place all users at risk.
Here are best practices you can use to secure your Parse deployment, both at the class and object levels.
Because client keys are distributed to users, they should be considered accessible by the general public, including threat actors.
A master key, on the other hand, must be strongly protected. Master keys can be used to bypass all security mechanisms in your application, such as class-level permissions and ACLs. Obtaining the master key is equivalent to gaining root access to the application server. Protecting your master key is a central goal of a Parse security strategy—just like protecting the root password on a production machine.
The general idea is to limit the capabilities of the client (using the client secret) and perform any sensitive operations in Cloud Code, requiring the master secret. Learn more about Cloud Code in the Parse documentation.
Another area to secure is the schema and data level. You should limit when and how client applications can create or access data in Parse. When you first start developing Parse applications, insecure defaults are set to maximize initial productivity—as you transition to production, you must configure Parse to protect sensitive data.
Configure permissions to assign to specific users and roles in your application on a least privilege basis, rather than granting universal access. A role can group users or other roles together to provide the same access permissions. Roles are assigned to objects to limit their use. Permissions granted to a user role or other role are also extended to its children, creating an access hierarchy for your app.
Consider how users can access data. Object-level access control allows you to separate one user’s data from another user’s data. Different users may need to access different objects within a class—for example, a user’s personal data must only be accessible to that user.
Parse also supports the concept of anonymous users in applications that store and secure user-specific data without explicit login.
When a user logs into your application, a Parse session is started. During the entire session, users can only add or modify their personal data, but not other data.
The simplest way to control who has access to what data is via access control lists called ACLs. ACLs work by providing each object with a list of roles and users and a list of permissions for each role or user. Users must have read access or be assigned to a role that has read access to retrieve data in an object. Users also need write access (or be assigned to a role with write access) to modify or delete data. Set user permissions carefully to ensure each category of users has exactly the permissions they need and no more.
As mentioned, Parse suffers from an infinite file upload vulnerability, which you will need to mitigate. This can be done at the bucket level, as recommended in the Parse documentation.
For example, to restrict file upload types in AWS, add the following statements to your bucket policy:
- The s3:PutObject operation should only be allowed on objects that require a file type extension.
- The s3:PutObject operation should be explicitly denied on objects that do not have the required file type extension.
In this article, I reviewed the main security concerns in the Parse platform and provided several best practices to help you overcome them:
- Client vs. master secrets—ensure that external entities with a client secret cannot perform sensitive operations and restrict master secret operations using Cloud Code.
- Class-level permissions—configure permissions to secure the schema and datastore.
- Object-level access control—define ACLs and roles to ensure that each user can access the data and operations they need, and no more.
- Securing file upload—prevent unlimited file upload by adding limitations to your cloud storage buckets.
I hope this will be useful as you improve the security posture of your Parse applications.