diff --git a/content/en/docs/howto/security/best-practices-security.md b/content/en/docs/howto/security/best-practices-security.md index 0bd601d39cb..353eb73e021 100644 --- a/content/en/docs/howto/security/best-practices-security.md +++ b/content/en/docs/howto/security/best-practices-security.md @@ -3,7 +3,7 @@ title: "Implement Best Practices for App Security" linktitle: "Best Practices for App Security" url: /howto/security/best-practices-security/ weight: 20 -description: "Describes the common aspects you should consider when delivering an application within Mendix Cloud." +description: "Describes common security best practices for Mendix applications, covering access control, authentication, data protection, and infrastructure configuration." aliases: - /howtogeneral/bestpractices/best-practices-security-and-improvements-for-mendix-applications.html - /howtogeneral/bestpractices/best-practices-security-and-improvements-for-mendix-applications @@ -12,100 +12,93 @@ aliases: ## Introduction -Security is one of the most important aspects of an application, because misconfiguration or failing security can have large stakeholder consequences. The Mendix Runtime protects your application and data according to your model, and Mendix Cloud handles security at the infrastructure level. +Security is one of the most important aspects of an application, because misconfiguration or failing security can have significant consequences for end-users, data, and your business. The Mendix Runtime protects your application and data according to your model, and Mendix Cloud handles security at the infrastructure level. -This document describes the common aspects you should consider when delivering an application within Mendix Cloud. +This document describes the common aspects to consider when deploying an application. ## Implementing Access Rules{#access-rules} -The Mendix architecture includes the Mendix Client, which can compose its own queries (generated by widgets) and send them to the Mendix Runtime. If the Mendix Runtime were to execute these queries without touching them, the Mendix Client would be able to request data that the user should not be allowed to see. +The Mendix architecture includes the Mendix Client, which can compose its own queries (generated by widgets) and send them to the Mendix Runtime. If the Mendix Runtime were to execute these queries without touching them, the Mendix Client would be able to request data that the user is not allowed to see. {{< figure src="/attachments/howto/security/best-practices-security/mendix-runtime-architecture.png" alt="Mendix Runtime Architecture" width="500" class="no-border" >}} -When designing an application, you can specify access rules on an entity (for more information, see [How to Create A Secure App](/howto/security/create-a-secure-app/)). These access rules are applied whenever a query (received from a client) should be executed, thus they constrain the data returned to the client. For example, users with the "Customer" role can only view orders that are associated to the customer of which this user is part. +When designing an application, you can specify access rules on an entity (for more information, see [How to Create A Secure App](/howto/security/create-a-secure-app/)). These access rules are applied whenever a query (received from a client) is executed, thus they constrain the data returned to the client. For example, end-users with the "Customer" role can only view orders that are associated with the customer of which this user is part. -While the data that should be viewable and editable in which role is application-specific, the following best practices are key: +While the data that is viewable and editable to each role is application-specific, the following best practices are key: -* Attributes determined by the system (like the status of an order) should never be writable -* If an anonymous user is allowed to create objects, constrain these objects to the owner (an anonymous user is actually a **System.User** object created on the fly) -* Do not set a default rule for read-and-write access – this forces you to think about each attribute that is added to an entity -* Security constraints should be formed as entity access rules -* Constraints on widgets in pages should not be used as a measure of security, but can filter out irrelevant data for the context of the page -* Keep your attributes editable within data views, because if an access rule prohibits write access, your client will display it as non-editable – this way you are aware of the (correct) working of an access rule +* Do not make attributes determined by the system (like the status of an order) writable +* If an anonymous user is allowed to create objects, constrain these objects to the owner (an anonymous user is a **System.User** object created on the fly)—you can do this using [Path to User](/refguide/access-rules/#path-to-user) in your entity *Access Rules* +* Set **Default rights for new members** to **None** so you have to think about who has access to each attribute that is added to an entity +* Implement security constraints as entity access rules +* Do not use constraints on widgets in pages as a security measure, but filter out irrelevant data for the context of the page +* Keep your attributes editable within data views, because if an access rule prohibits write access, your client will display it as non-editable—this way you are aware of the (correct) working of an access rule You can review and manage your entity access settings in the Security Overview in Mendix Studio Pro. This overview shows you your application's security configuration and allows you to verify which roles have access to specific entities and attributes (for more information, see [Security Overview](/refguide/security-overview/)). -## Avoiding Injection - -Injection occurs when (user) input can be misused to influence the behavior of a system. Common cases are parameters for queries (to influence the results of database queries) or HTML with JavaScript contents (to influence browser behavior). +## Separating Business Data from User Accounts -When using Mendix-native components, there are no concerns about the possibility of injection. Queries (like XPath) are parametrized and therefore always escaped, making SQL-injection impossible. For the other way around, retrieved data shown in the user interface is escaped to the HTML format. +If you have business information that is also related to end-users of your app, do not combine the business information with the end-user by using specializations of `System.User`. Keep business information and app security information separate. If you want to link business data to a user, use associations to link them. -When you are building an application, you may use [Mendix Marketplace](https://marketplace.mendix.com/) components and external interfaces. Remember that values which originate from user input or other systems should be escaped to avoid injection (and to ensure they are properly display). +For example, you may have an app where you want your customers to be end-users of the app. If you make an entity `MyModule.Customer` which is a specialization of `System.User` then all customers would be end-users of the app. This has security implications such as: -These are the common cases and best practices: +* Every customer becomes an end-user without any confirmation required +* If a customer stops being a customer, you cannot remove them from using the app without deleting other business information (which may, legally, need to be kept) +* You cannot fully control access to `MyModule.Customer`, because configuring [manageable roles](/refguide/user-roles/#user-management) generates additional implicit access rules that apply to all specializations of `System.User` +* You may want to add a customer who you do not want to become an end-user of the app -* HTML content, usually derived from an HTML editor and displayed using an HTML viewer, format string, or an email client – these are the ways to avoid this abuse: - * Use the XSSSanitize action from the [CommunityCommons Function Library](/appstore/modules/community-commons-function-library/) module to strip malicious code from the entered HTML - * Display the value of an attribute as HTML or using the HTMLEncode function from the [Community Commons Function Library](/appstore/modules/community-commons-function-library/) module -* Database connections (for example, using the [Database Connector](/appstore/modules/database-connector/)), where user input is being used within constraints – these are the ways to avoid this abuse: - * Use prepared statements, which will cause the database-specific connector to take care of escaping the value - * Sanity-check your user input (for example, use a regular expression to check if your user input only contains alphanumeric characters, spaces, and dashes) +In addition, apps are priced by the number of end-users and having unnecessary end-users might cost you more money. -## Applying Access Restrictions to Unnecessary Request Handlers{#request-handlers} +To link the customer information to an end-user, create a 1-1 association, `Customer_Account`, between `MyModule.Customer` and `Administration.Account`. -A Mendix app offers various endpoints that can be used to obtain information about offered services. The paths used by these endpoints end in `-doc`. By default, access to these endpoints is disabled when deploying to a cloud node. +## Configuring User Roles and Access {#access-control} -Access restrictions can be configured within the Mendix Portal. They can be found in the **Environment details** of your cloud node. This is an example of this overview showing the default settings after deploying to a new environment: +Which users and roles are defined within an application changes, depending on the function of the app. However, there are some key guidelines to keep in mind when validating the user security: -{{< figure src="/attachments/howto/security/best-practices-security/default-access-restrictions.png" alt="Mendix Cloud Access Restrictions Overview" class="no-border" >}} +* Disable [anonymous access](/refguide/anonymous-users/) if it has no function within the application + * Some applications have anonymous access enabled, solely to serve a custom login form—this can be replaced by modifying the default *login.html* within your theme (which will also help the user experience with an improved loading time) +* Make roles managing other user roles as strict as possible (configured via **User management** within the user role options) +* Only allow the user role of the app's administrator user (default **MxAdmin**) to create the actual administrative accounts (or configure Single Sign On (SSO))—the Administrator user role does not need access to the business data in the app—give this to a different user role if you need a role which can access all the business data. -Examples are the `ws-doc` or `rest-doc` endpoints that enumerate all the published web and REST services of the application. An attacker could use this information to discover possible areas to exploit. +## Enabling Strict Mode -You can take the following preventative measures: - -* Disable unused endpoints within the Mendix Portal completely by applying a **deny all access** preset on them -* Apply IP filtering or client certificate authentication to restrict access - -Keep the following in mind: +Enable [strict mode](/refguide/strict-mode/) in your application. Strict mode helps ensure that entities are accessible only in the ways defined within your model, through microflows, nanoflows, widgets, or pages, by restricting certain client APIs. -* If there are other app-specific request handlers that should have an access restriction applied, then click **New** to add them as additional paths -* The URLs of test and acceptance environments can easily be guessed; in order to take effective measures, the restrictions should be applied to these environments also +Configuring access rules is essential for the security of your app. However, accurately setting up these rules can be challenging. By enabling strict mode, you add a safety net in case access rules are misconfigured when your application is deployed, helping to reduce the risk of unintended data access. ## Applying Authentication on Services{#service-authentication} -When you expose APIs, you provide a way for users and external systems to access (create, read, update, and/or delete) data within your Mendix application. -As APIs are just a different interface to access your data, it is extremely important to restrict data access through authentication and authorization best practices. +When you expose APIs, you provide a way for end-users and external systems to access (create, read, update, and/or delete) data within your Mendix application. +As APIs are just a different interface to access your data, it is vital to restrict data access through authentication and authorization best practices. -### Turning On API Security +### Turning on API Security Firstly, you need to answer the question **Requires authentication** with *Yes* or *No*. -The platform guides you towards choosing *Yes* for the API endpoints you create. -Intuitively this seems correct, as when the *Yes* option is toggled on. Mendix Studio Pro will reveal a variety of authentication options. -These options will restrict which users or external systems have access to your API endpoint. +The platform guides you toward choosing *Yes* for the API endpoints you create. +This seems to be the most secure option. When enabled, Mendix Studio Pro reveals authentication options +that restrict which end-users or external systems have access to your API endpoint. From a security perspective this is exactly what is wanted. However, choosing between *Yes* and *No* is not this straightforward. Choosing *Yes* will force your API requests to be executed in the context of a user account and require an active session to be established. -Skipping the step where you retrieve the user account and establish a session can have a significant performance improvement for your API. +You can significantly improve the performance of your API if you can skip the step where you retrieve the user account and establish a session. This is why choosing *No* can still be a viable option for your API, and it might even be the recommended option in many situations. The best practices when selecting *No* as **Requires authentication** option are as follows. * Provide the HTTP Response object as a parameter to the microflow used as the API handler. * Configure the required headers for authentication as part of a published REST operation and add them explicitly to the API handling microflow as input parameters. This could, for example, be an "X-API-Key" header or "Authorization" header. By adding the header as an input parameter it will be included in the generated Swagger documentation hosted at `/rest-doc`. Here it can be manually set as a parameter and used as part of the "try it out" feature for that API operation. -* Perform your own validations on this header information at the very start of the API handling microflow. +* Perform your own validations on this header information at the beginning of the API handling microflow. * Abort execution of the rest of the API handling microflow when validations fail. -* Manipulate the status code and response directly in the HTTP response object that was provided as a parameter. It is recommended that you return a `401 Unauthorized` in cases where authentication fails and a `403 Forbidden` in cases where the authentication was successful, but the provided credentials to not grant access to the requested resource or allow the rest of that API operation's logic to be executed. +* Manipulate the status code and response directly in the HTTP response object that was provided as a parameter. It is recommended that you return a `401 Unauthorized` in cases where authentication fails and a `403 Forbidden` in cases where the authentication was successful, but the provided credentials do not grant access to the requested resource or allow the rest of that API operation's logic to be executed. By performing your authentication checks in this way, you will have the flexibility of the [Custom authentication option](#custom) described below, but it comes with the lowest performance hit. This is at the expense of losing the user context, which in most scenarios is acceptable for APIs. {{% alert color="warning" %}} -Choosing *No* without these restrictions will allow anyone on the internet to make requests to your API endpoint at any time and at any rate, which can seriously affect your app's response and even cause server failure. +Choosing *No* without these restrictions will allow anyone on the internet to make requests to your API endpoint at any time and at any rate, which can impact your app's response and even cause server failure. {{% /alert %}} -Choosing *Yes* comes with the benefits of having the time zone and language settings available for that API user account. It can also provide better traceability of changes made through API requests. Additionally, it gives the possibility of applying restrictions to requested entities based on the System.User object used for the API account. +Choosing *Yes* comes with the benefits of having the time zone and language settings available for that API user account. It can also provide better traceability of changes made through API requests. Additionally, it gives the possibility of applying restrictions to requested entities based on the `System.User` object used for the API account. ### Selecting Authentication Option @@ -115,7 +108,7 @@ All these authentication options will later be combined with the API's [Allowed Allowed roles can be any of the roles you have defined in [User Roles](/refguide/user-roles/), including the role assigned to Anonymous users. {{% alert color="warning" %}} -Assigning an Anonymous user role as one of the API's allowed roles is similar as choosing *No* at **Requires authentication**. +Assigning an Anonymous user role as one of the API's allowed roles is similar to choosing *No* at **Requires authentication**. This means that the same advice around certificate usage and IP restrictions applies, and you should perform the authentication inside the API handling microflow itself. {{% /alert %}} @@ -123,13 +116,13 @@ You can choose one or more of the authentication options described below. If you #### Authentication Option 1, Username and Password{#basic} -If you choose this option, the API will expect a `Basic auth` HTTP request header to be set on each incoming request. The `basic auth` header format is: `"Authorization": "Basic userid:password"`, where userid:password have been base64 encoded. +If you choose this option, the API will expect a `Basic auth` HTTP request header to be set on each incoming request. The `Basic auth` header format is: `"Authorization": "Basic userid:password"`, where userid:password have been base64 encoded. -This "Authorization" header will be combined with the allowed roles, and checked against the app users, recorded in the `System.User` entity. +This "Authorization" header will be combined with the allowed roles, and checked against the app end-users, recorded in the `System.User` entity. Credentials provided in the basic auth header will be checked as follows: * for REST and OData – endpoints will only look for accounts that have the attribute `WebServiceUser` set to "FALSE" -* for SOAP endpoints – `WebServiceUser` should be "TRUE" +* for SOAP endpoints – set `WebServiceUser` to "TRUE" {{% alert color="info" %}}This means that you cannot create an account in Mendix that can use Published Web Services, the application UI, and OData/REST APIs at the same time.{{% /alert %}} @@ -141,7 +134,7 @@ This authentication option is not available for Published Web Services and can o If you choose this option, the API will expect a "X-Csrf-Token" HTTP request header to be set on each incoming request. This authentication option is particularly interesting for custom JavaScript and widget implementations. -The session token can be acquired by calling a Mendix Client API method to get the current CSRF token. This method should be called before each API call in your widget or JavaScript action to prevent cross-site request forgery (CSRF/XSRF). +The session token can be acquired by calling a Mendix Client API method to get the current CSRF token. Call this method before each API call in your widget or JavaScript action to prevent cross-site request forgery (CSRF/XSRF). ```javascript import getCSRFToken from "mx-api/session"; @@ -161,35 +154,13 @@ To understand the full authentication flow, take a closer look at [Published RES ### Limiting API Access through IP Restrictions and Certificates -Additional API security measures can be implemented through the use of [IP restrictions and/or certificates](/developerportal/deploy/access-restrictions/), creating a secure bubble of trusted requesting users and systems. - -## Using the Encryption Module When Storing Sensitive Information - -Your application might require sensitive information that should be extra encrypted. These are some examples: - -* Connection information for consumed services (like credentials, service locations, or keys) -* Personal information (like bank account numbers or social security numbers) - -This data is defined within the domain model and stored within the database of your application. To minimize the impact of this information when it is leaked, Mendix recommends storing this data in a (symmetric) encrypted manner. The [Encryption](/appstore/modules/encryption/) module available from the Mendix Marketplace provides a way to encrypt this sensitive information in a database record based on an encryption key that is stored at the Mendix application server. - -## Using Credentials in Your App - -You may need to store sensitive information, such as credentials, in your app. To limit access to this sensitive information, Mendix recommends the following: - -* Credentials are recorded in [constants](/refguide/constants/) which can be set when your app is deployed—in the [Mendix Portal](/developerportal/deploy/environments-details/#constants), for example, if you are deploying to Mendix Cloud. -* The constants should be blank by default (not populated with the credentials) in the app. - - * Values for the constants can be provided during testing by creating a [configuration](/refguide/configurations-tab/#constants). - -* Only authorized people should be given access to set the constants when the app is deployed. This is done through the [app roles](/developerportal/general/app-roles/) and (for Mendix Cloud) the [node permissions](/developerportal/deploy/node-permissions/). - -Credentials should not be stored in your database as this means that they are also included in backups. Even if they are encrypted, your app will know the encryption key so that they can be decrypted. +Additional API security measures can be implemented through the use of [IP restrictions and/or certificates](/developerportal/deploy/access-restrictions/), creating a secure bubble of trusted requesting end-users and systems. ## Using a Third-Party Identity Provider -When developing an application, authentication is one of the basic considerations. Even though Mendix comes with a basic authentication mechanism, your application’s security is improved when authentication is delegated to an enterprise grade identity provider like ADFS. +When developing an application, authentication is one of the basic considerations. Even though Mendix comes with a basic authentication mechanism, your application’s security is improved when authentication is delegated to an enterprise-grade identity provider like ADFS. -Mendix offers the [SAML](/appstore/modules/saml/) module that enables your application to be connected with these services. +Mendix offers the [SAML](/appstore/modules/saml/) and [OIDC SSO](/appstore/modules/oidc/) modules that enable your application to be connected with these services. Your application can gain the following benefits from using an identity provider: @@ -205,41 +176,47 @@ By default, Mendix forces a strong password policy. The same password policy tha It is very tempting to simplify the password constraints for development purposes (for example, making it possible to use a single character to login). However, Mendix recommends avoiding this approach so that deployments will continue to force a strong password policy. -The password policy can be set by via the guidelines described in [Password Policy](/refguide/password-policy/). +The password policy can be set via the guidelines described in [Password Policy](/refguide/password-policy/). ## Renaming the Administrator User -Each application requires power users who should be able to administer technical functions (like configuring SSO). By default, the user who has these capabilities is called **MxAdmin** and has the **Administrator** role. +Each application requires power users who are end-users which can administer technical functions (like configuring SSO). By default, the user who has these capabilities is called **MxAdmin** and has the **Administrator** role. This information can be exploited by an attacker (for example, by trying to guess the password). Even though Mendix will block the user for about 5 minutes after three unsuccessful login attempts, renaming the default MxAdmin user is recommended. -The user name of the administrator can be changed in 's **App Security** settings on the **Administrator** tab. +The user name of the administrator can be changed in Studio Pro using the app's **App Security** settings on the **Administrator** tab. -When deployed to Mendix Cloud, the information about the administrator user name and role is taken into account when using the **Change admin password** button on the environment. After changing the settings in and redeploying the application, a successful admin password change will trigger the creation of a user in the app with the new name and role. +When deployed to Mendix Cloud, the information about the administrator user name and role is taken into account when using the **Change admin password** button on the environment. After changing the settings in Studio Pro and redeploying the application, a successful admin password change will trigger the creation of a user in the app with the new name and role. {{% alert color="info" %}} -At this point, the application does not automatically remove the user with the previous user name. Removing the old **MxAdmin** account has to be done manually. +As a new user is created, the previous administrator account (for example, `MxAdmin`) is not removed. You must remove the old administrator account manually. {{% /alert %}} -## Using SSL on Consumed Web Services Whenever Possible +## Applying Access Restrictions to Unnecessary Request Handlers{#request-handlers} + +A Mendix app offers various endpoints that can be used to obtain information about offered services. The paths used by these endpoints end in `-doc`. By default, access to these endpoints is disabled when deploying to a cloud node. -Most apps consume (web) services that could be located within an organization itself or at an external third party. When such a service is consumed by an application, your request crosses multiple networks and devices before it reaches its endpoint (the service). A potential attacker in between would be able to read and manipulate the conversation between the application and the service. +Access restrictions can be configured within the Mendix Portal. They can be found in the **Environment details** of your cloud node. This is an example of this overview showing the default settings after deploying to a new environment: -By using an SSL connection and adding the public key of the endpoint within your application, you will ensure the following: +{{< figure src="/attachments/howto/security/best-practices-security/default-access-restrictions.png" alt="Mendix Cloud Access Restrictions Overview" class="no-border" >}} -* The conversation between you and the service has not been tampered with -* The conversation is not readable if it was ever intercepted -* The identity of your endpoint is confirmed +Examples are the `ws-doc` or `rest-doc` endpoints that enumerate all the published web and REST services of the application. An attacker could use this information to discover possible areas to exploit. -There are several scenarios possible for protecting your outgoing connections using encryption. These depend on the infrastructure possibilities and protocols used. For more information, see [How to Secure Outgoing Connections from Your App](/developerportal/deploy/securing-outgoing-connections-from-your-application/). +You can take the following preventative measures: + +* Disable unused endpoints within the Mendix Portal completely by applying a **deny all access** preset on them +* Apply IP filtering or client certificate authentication to restrict access + +Keep the following in mind: -You can add individual certificates in your app's settings in . Test, acceptance, and production environments require their certificates to be uploaded to Mendix Cloud (for more information, see [Certificates](/developerportal/deploy/certificates/)). +* If there are other app-specific request handlers that should have an access restriction applied, then click **New** to add them as additional paths +* The URLs of test and acceptance environments can easily be guessed so to take effective measures, apply the restrictions to these environments as well ## Adding HTTP Headers {#adding-http-header} HTTP headers can add an additional layer of security and help you detect certain attacks. For information on how to add HTTP headers, see the [HTTP Headers](/developerportal/deploy/environments-details/#http-headers) section in *Environment Details*. -An example of an attack is when an application is embedded in an iframe. Applications that can be embedded within an iframe can be misused by attackers. By using an overlay, it could trick users into clicking buttons and make them perform actions within the application on their behalf without knowing it. This approach is called [clickjacking](https://www.owasp.org/index.php/Clickjacking). +An example of an attack is when an application is embedded in an iframe. Applications that can be embedded within an iframe can be misused by attackers. By using an overlay, it could trick end-users into clicking buttons and make them perform actions within the application on their behalf without knowing it. This approach is called [clickjacking](https://www.owasp.org/index.php/Clickjacking). By sending a header to the user’s browser, it can block the use of the Mendix application within an iframe and avoid this type of attack. The header is set by default to block embedding within an iframe. For Mendix Cloud, this can be configured using [HTTP Headers](/developerportal/deploy/environments-details/#http-headers) in your node’s environment details within the Mendix Portal. If you change this value, you will also need to ensure that *SameSite* cookies are set to the correct value. See [Iframes and Running Apps](/developerportal/deploy/running-in-iframe/) for more information. @@ -249,26 +226,36 @@ The Mendix Cloud Foundry Buildpack and Mendix Docker Buildpack also provide [an If you use a traditional deployment of your Mendix app, using Windows or Linux, you need to set up these headers on the web server in front of your Mendix application server, for example in Microsoft Internet Information Services (IIS). -## Maintaining a High Level of App Hygiene +## Using SSL on Consumed Web Services -As an application grows in functionality, it also increases the chance of containing logic that could be exploitable for an attacker. Also, over time, vulnerabilities within logic can be discovered. Keeping your app hygiene at a high level will reduce the chances of a vulnerable application. +Most apps consume (web) services that are located within an organization or at an external third party. When such a service is consumed by an application, your request crosses multiple networks and devices before it reaches its endpoint (the service). A man-in-the-middle attack can read and manipulate the conversation between the application and the service. -To keep your app hygiene at a good level, perform the following steps: +By using an SSL connection and adding the public key of the endpoint within your application, you will ensure the following: -* Remove unused modules, widgets, and Java libraries -* Remove microflows that are not being used (these appear as warnings in Studio Pro) -* Avoid using components with known vulnerabilities (like Java or JavaScript libraries) +* The conversation between you and the service has not been tampered with +* The conversation is not readable if it was ever intercepted +* The identity of your endpoint is confirmed -A good source of known vulnerabilities is the [Common Vulnerabilities and Exposures website](https://cve.mitre.org/). +There are several scenarios possible for protecting your outgoing connections using encryption. These depend on the infrastructure possibilities and protocols used. For more information, see [How to Secure Outgoing Connections from Your App](/developerportal/deploy/securing-outgoing-connections-from-your-application/). + +You can add individual certificates in your app's settings in Studio Pro. Test, acceptance, and production environments require their certificates to be uploaded to Mendix Cloud (for more information, see [Certificates](/developerportal/deploy/certificates/)). -## Configuring User Roles and Access +## Avoiding Injection -Which users and roles are defined within an application is different per app and app. However, there are some key guidelines to keep in mind when validating the user security: +Injection occurs when (user) input can be misused to influence the behavior of a system. Common cases are parameters for queries (to influence the results of database queries) or HTML with JavaScript contents (to influence browser behavior). -* Anonymous access should be disabled if it has no function within the application - * Some applications have anonymous access enabled, solely to serve a custom login form – this can be replaced by modifying the default *login.html* within your theme (which will also help the user experience with an improved loading time) -* Roles managing other user roles should be as strict as possible (configured via **User management** within the user role options) -* The role of the app's administrator user (default **MxAdmin**) should only be able to create the actual administrative accounts (or configure SSO) +When using Mendix-native components, there are no concerns about the possibility of injection. Queries (like XPath) are parametrized and therefore always escaped, making SQL-injection impossible. Conversely, retrieved data shown in the user interface is escaped to HTML format. + +When you are building an application, you may use [Mendix Marketplace](https://marketplace.mendix.com/) components and external interfaces. Remember to escape values that originate from user input or other systems to avoid injection (and to ensure they are properly displayed). + +These are the common cases and best practices: + +* HTML content, usually derived from an HTML editor and displayed using an HTML viewer, format string, or an email client—these are the ways to avoid this abuse: + * Use the XSSSanitize action from the [CommunityCommons Function Library](/appstore/modules/community-commons-function-library/) module to strip malicious code from the entered HTML + * Display the value of an attribute as HTML or using the HTMLEncode function from the [Community Commons Function Library](/appstore/modules/community-commons-function-library/) module +* Database connections (for example, using the [Database Connector](/appstore/modules/database-connector/)), where user input is being used within constraints—these are the ways to avoid this abuse: + * Use prepared statements, which will cause the database-specific connector to take care of escaping the value + * Sanity-check your user input (for example, use a regular expression to check if your user input only contains alphanumeric characters, spaces, and dashes) ## Scanning Uploaded Files for Malicious Content {#scanning-for-malicious-content} @@ -279,8 +266,36 @@ To scan uploaded files for malicious content, do one of the following: * Create a custom module and configure the functionality yourself, for example, by using a [before commit event](/refguide/setting-up-data-validation/#validation-before-commit-event). * Check available modules in the [Mendix Marketplace](https://marketplace.mendix.com/). For more information on how to use the Mendix Marketplace content, see [How to Use Marketplace Content](/appstore/use-content/). -## Enable Strict Mode +## Using the Encryption Module When Storing Sensitive Information -Enable [strict mode](/refguide/strict-mode/) in your application. Strict mode helps ensure that entities are accessible only in the ways defined within your model, through microflows, nanoflows, widgets, or pages, by restricting certain client APIs. +Your application might contain sensitive information that requires additional encryption. These are some examples: + +* Connection information for consumed services (like credentials, service locations, or keys) +* Personal information (like bank account numbers or social security numbers) + +This data is defined within the domain model and stored within the database of your application. To minimize the impact of this information when it is leaked, Mendix recommends storing this data in a (symmetric) encrypted manner. The [Encryption](/appstore/modules/encryption/) module available from the Mendix Marketplace provides a way to encrypt this sensitive information in a database record based on an encryption key that is stored at the Mendix application server. + +## Using Credentials in Your App + +You may need to store sensitive information, such as credentials, in your app. To limit access to this sensitive information, Mendix recommends the following: + +* Credentials are recorded in [constants](/refguide/constants/) which can be set when your app is deployed—in the [Mendix Portal](/developerportal/deploy/environments-details/#constants), for example, if you are deploying to Mendix Cloud. +* Make the constants blank by default (not populated with the credentials) in the app. + + * Values for the constants can be provided during testing by creating a [configuration](/refguide/configurations-tab/#constants). + +* Only give authorized people access to set the constants when the app is deployed. This is done through the [app roles](/developerportal/general/app-roles/) and (for Mendix Cloud) the [node permissions](/developerportal/deploy/node-permissions/). -Configuring access rules is essential for the security of your app. However, accurately setting up these rules can be challenging. By enabling strict mode, you add a safety net in case access rules are misconfigured when your application is deployed, helping to reduce the risk of unintended data access. +Do not store credentials in your database as this means that they are also included in backups. Even if they are encrypted, your app will know the encryption key so that they can be decrypted. + +## Maintaining a High Level of App Hygiene + +As an application grows in functionality, the chance of containing exploitable logic also increases. Also, over time, vulnerabilities within logic can be discovered. Keeping your app hygiene at a high level will reduce the chances of a vulnerable application. + +To keep your app hygiene at a good level, perform the following steps: + +* Remove unused modules, widgets, and Java libraries +* Remove microflows that are not being used (these appear as warnings in Studio Pro) +* Avoid using components with known vulnerabilities (like Java or JavaScript libraries) + +A good source of known vulnerabilities is the [Common Vulnerabilities and Exposures website](https://cve.mitre.org/). diff --git a/content/en/docs/quickstarts/native-mobile-app.md b/content/en/docs/quickstarts/native-mobile-app.md index dcd036734bd..e94efcefce0 100644 --- a/content/en/docs/quickstarts/native-mobile-app.md +++ b/content/en/docs/quickstarts/native-mobile-app.md @@ -58,7 +58,7 @@ In the pop-up window that appears, enter a **name** for your app. Leave all othe Just as in part one, we will need to create the entity to store employee data. In the **domain model** for the Native Mobile Module, add a **new entity**. 1. Name the entity Employee. -1. The entity should be a generalization of the Account entity. +1. The entity should be a specialization of the Account entity. 1. Add three attributes to the entity: * FirstName as String * LastName as String diff --git a/content/en/docs/refguide/modeling/domain-model/entities/access-rules.md b/content/en/docs/refguide/modeling/domain-model/entities/access-rules.md index 4c1c5dccb1e..082eb84e631 100644 --- a/content/en/docs/refguide/modeling/domain-model/entities/access-rules.md +++ b/content/en/docs/refguide/modeling/domain-model/entities/access-rules.md @@ -94,7 +94,11 @@ To edit the XPath constraint, click **Edit...** next to the XPath constraint fie XPath constraints can only be applied to persistable entities, as they are applied by the database. Defining XPath constraints for non-persistable entities results in consistency errors. {{% /alert %}} -There are two constraints that can be appended easily with a single button click: +{{% alert color="info" %}} +The **Owner** and **Path to user...** buttons described below are not available in the XPath **Builder**. You have to switch to entering an **XPath expression**. +{{% /alert %}} + +There are two constraints that can be appended with a single button click: ##### Owner @@ -106,22 +110,22 @@ The **Owner** button adds an XPath constraint so the access rule is only applied This constraint is only valid when the [Store 'owner'](/refguide/entities/#store-owner) checkbox in the **System members** section of the entity properties is checked. -##### Path to User +##### Path to User {#path-to-user} The **Path to user...** button adds an XPath constraint so the access rule is only applied when a `User` object which is associated (directly or indirectly) with the current object is the current end-user. When you click **Path to user...**, you can select a path to an associated entity that is either a `System.User` or a specialization of `System.User`. This is then converted into an XPath constraint for the access rule. -For example: +Take, for example a customer visiting a webshop: -1. Assume that the **Customer** entity is a specialization of the **User** entity. The **Order** entity is associated with the **Customer** entity via the **Order_Customer** association. -2. Assume that a logged-in customer is only allowed to view their orders, but is not allowed to view the orders of other customers. +1. Assume that the `Customer` entity contains information about an individual and is associated with the `Administration.Account` entity (which is a specialization of the `User` entity) via the `Customer_Account` association. The `Order` entity is associated with the `Customer` entity via the `Order_Customer` association. +2. The customer can sign in to the webshop app using the linked Administration.Account, but is only allowed to view their own orders. They cannot view the orders of other customers. -The XPath constraint can be constructed easily using the **Path to user...** button by selecting the **Customer** entity in the **Order** entity access rule. The created rule will look like this: +The required XPath constraint can be constructed using the **Path to user...** button on the `Order` entity by navigating to the `Administration.Account` entity via the `Order_Customer` and `Customer_Account` associations in the entity navigation tree. The created rule will look like this: ```xpath -[Module.Order_Customer = '[%CurrentUser%]'] +[Module.Order_Customer/Module.Customer/Module.Customer_Account='[%CurrentUser%]'] ``` -Because of this XPath constraint, access defined in the access rule is only applied to orders for which the customer is the current end-user. +This XPath constraint means the current end-user can only see orders for the customer associated with the current end-user. #### Entity Rights diff --git a/content/en/docs/refguide/modeling/security/app-security/administrator.md b/content/en/docs/refguide/modeling/security/app-security/administrator.md index 0bcd5353d96..16c1f359835 100644 --- a/content/en/docs/refguide/modeling/security/app-security/administrator.md +++ b/content/en/docs/refguide/modeling/security/app-security/administrator.md @@ -72,15 +72,15 @@ The user role assigned to the Administrator. For more information, see [User Rol Default: *Administrator* {{% alert color="info" %}} -The administrator is always created and has the System.Administrator role by default. The System.Administrator role allows users of your application to be managed. +The Administrator user role is always created and has the System.Administrator module role by default. The Administrator user role can also manage users of your application as it has all [manageable roles](/refguide/user-roles/#user-management). -For Free Apps, the user that created the application automatically has this role by default as well so you can use it to manage your users in that environment. +For Free Apps, the user that created the application automatically also defaults to having the Administrator role so they can use it to manage the users in that environment. -This role may be helpful in case you have exceeded your user license restriction in which case you can use any user that has this System.Administrator role to sign in to manage your users. +This role may be helpful if you exceed your user license restriction, as you can sign in as any end-user that has this Administrator user role to manage your end-users. {{% /alert %}} {{% alert color="warning" %}} -When your app is not deployed locally, for example to Mendix Cloud, changes to the user role of the administrator account will not be applied until the administrator password is changed. See the [actions](/developerportal/deploy/environments-details/#actions) section of *Environment Detail* for instructions on changing the admin password. +When your app is not deployed locally, for example, if it is deployed to Mendix Cloud, changes to the user role of the Administrator account will not be applied until the Administrator password is changed. See the [actions](/developerportal/deploy/environments-details/#actions) section of *Environment Detail* for instructions on changing the admin password. {{% /alert %}} ## Read More diff --git a/content/en/docs/refguide/modeling/security/app-security/anonymous-users.md b/content/en/docs/refguide/modeling/security/app-security/anonymous-users.md index d5c98b29bf9..2ed333b19fd 100644 --- a/content/en/docs/refguide/modeling/security/app-security/anonymous-users.md +++ b/content/en/docs/refguide/modeling/security/app-security/anonymous-users.md @@ -21,8 +21,12 @@ The properties of anonymous users are described in the table below: | Allow anonymous users | When **Yes** is selected, anonymous users are allowed. End-users do not have to sign in to access the application.
When **No** is selected, anonymous users are not allowed. End-users have to sign in to access the application. | | Anonymous user role | The user role that end-users of your application have when they are not signed in. This tells the application which role should be automatically applied to anonymous users who access the app. The **Allow anonymous users** property should be set to **Yes** to select an anonymous user role. | +{{% alert color="info" %}} +Mendix advises always naming a user role which allows anonymous users in an app or module as `Anonymous`. This ensures that it is clear to all users what it is being used for. +{{% /alert %}} + {{% alert color="warning" %}} -Enabling anonymous users allows anyone to use your app without signing in. To prevent unintended data exposure, ensure that the anonymous user role has limited access across your app by configuring appropriate entity and microflow access rules. +Enabling anonymous users allows anyone to use your app without signing in. To prevent unintended data exposure, ensure that the anonymous user role has limited access across your app by configuring appropriate entity and microflow access rules. See [Configuring User Roles and Access](/howto/security/best-practices-security/#access-control) in *Implement Best Practices for App Security* for more advice on configuring user roles. {{% /alert %}} ## Read More diff --git a/content/en/docs/refguide/modeling/security/app-security/user-roles.md b/content/en/docs/refguide/modeling/security/app-security/user-roles.md index 510940d2a7a..9711b1a6628 100644 --- a/content/en/docs/refguide/modeling/security/app-security/user-roles.md +++ b/content/en/docs/refguide/modeling/security/app-security/user-roles.md @@ -83,7 +83,7 @@ If the **Select / deselect all** box is checked (that is, all roles are manageab {{% /alert %}} {{% alert color="info" %}} -Internally, user management properties are translated into implicit entity access rules for **System.User**. This means that they are not applied in microflows that do not check entity access. +Internally, user management properties are translated into implicit entity access rules for **System.User**. These implicit rules are not applied when a microflow runs with [Apply entity access](/refguide/microflow/#security) enabled as only explicitly configured entity access rules are checked. {{% /alert %}} ### What Can User Roles Manage?