This document is targeted at Administrators of Geocortex Essentials and Geocortex Analytics who want to prevent unwanted access to Geocortex Core. It assumes that you are already familiar with the Geocortex Essentials or Analytics suite of products, including Geocortex Core.
1.0 Background
Geocortex Essentials and Analytics are built on top of Core, and use it for persistent storage of data. This can include sensitive information like security configuration, access tokens, and secured map service credentials. Given access, an unskilled attacker could compromise security by deleting or damaging data. A skilled attacker, intimately familiar with Geocortex, could use this data to impersonate another user. Thus, Core has built-in security mechanisms to prevent its data from falling into the wrong hands. This article will outline actions that can be taken to reinforce Core’s existing security.
1.1 Document Store Watcher
Core provides persistent storage through the DocumentStore Role (DSR), which is included in all Core deployments except that of Analytics agents. The DSR, along with the many other services it provides, is a wrapper around Elasticsearch - a no-SQL database that is designed for full text search. Elasticsearch exposes the typical database CRUD operations through a REST API. This is the mechanism that allows nodes in a Core cluster to access data from other nodes.
Exposing a REST API presents a challenge: How can we allow a trusted party, such as a Core node, to access the API, while preventing an untrusted party from doing so? This is done in two steps:
- Make the Elasticsearch REST API accessible only on the loopback interface – a network interface that is used by a machine to route requests to itself. This ensures that the REST API is not available outside the machine where Core is deployed.
- Place a proxy – called the DocumentStoreWatcher - in front of the Elasticsearch REST API and allow it to decide whether requests will be forwarded to Elasticsearch.
Figure 1 demonstrates what happens when a request is sent to the DocumentStoreWatcher. The request is forwarded if the sender is trusted, otherwise it is ignored.
The DocumentStoreWatcher will inspect the IP address of the sender and compare it to a whitelist of IP addresses that are trusted. If the sender’s IP is not trusted, the request is ignored, and a 403 response is sent back. The whitelist used by the DocumentStoreWatcher is stored in an Elasticsearch document so that it can be shared across all nodes in the cluster. This means that a sender with a whitelisted IP address can access the DocumentStoreWatcher on any node in the cluster.
1.1.1Automatic Whitelist Registration
For two or more clustered Core nodes to share data, their host machines must be mutually whitelisted. To ensure this, the DSR will automatically register the IP address of its host machine on the shared whitelist. Since the whitelist is stored in Elasticsearch, this must be done by the DSR. Figure 2 shows an example of a two-node cluster where both host machine IPs are registered on the whitelist. Since node A and B are both on the whitelist, they are free to access data on any node in the cluster, including nodes that are added later.
Figure 2: Two node cluster with a shared whitelist.
1.1.2 Whitelist Registration with Shared Secret
Since registration can only be done through the DSR, deployments of Core that don’t have a DSR, but still need to access cluster data – Analytics agents for example - must register themselves in a different way. The DSR exposes a web endpoint that can be used to register with the whitelist if you know the cluster’s shared secret. When the DSR receives a registration request, it will check that the correct shared secret was provided, and will then add the IP address of the sender to the whitelist. This can be seen in figure 3.
Figure3: Node C registers on the whitelist by sending Node A the shared secret.
The registration process is automatic and an example of when it would be performed would be adding an Agent for Geocortex Analytics, the IP address would be whitelisted by the DSR. No action is required by an admin, this information is provided as example of a background process the DSR performs.
1.2 Elasticsearch Head Plugin
The Elasticsearch head plugin provides a web interface for managing Elasticsearch data. It is hosted on the same web interface as Elasticsearch and uses the REST API. Just like the REST API, any whitelisted party can access the head plugin through the DocumentStoreWatcher. The head plugin’s human-friendly interface makes it easier to access potentially sensitive data.
Solution:
2.0 Preventing Unwanted Access
This section will cover several actions that can be taken to prevent unwanted access to data in a Core cluster.
2.1 Follow Best Practices
Always follow best practices when deploying any Geocortex software. Make sure to do things like:
- Ensure a network firewall is configured to refuse unnecessary connections.
- Use a reverse proxy when making resources available outside the network.
- Use Windows security to limit access to the network where Geocortex is deployed.
2.2 DocumentStoreWatcher Whitelist Configuration
Another excellent way to prevent unwanted access to a Core cluster is to ensure that the DocumentStoreWatcher’s whitelist is configured properly. This gives the Core administrator precise control over which machines can access data in the cluster. The whitelist is configurable through the startup settings in the DSR’s role.config file. The settings that control the whitelist are: WatcherHost, EnableWhiteList, and WhiteList.
WatcherHost
Here is how this setting will affect the whitelist:
_local_ | The whitelist is ignored. All requests from anywhere other than the local machine are ignored. (Note: Requests from the local machine are always allowed.). Core 3.1.7 and later only. |
* | Delegate to the whitelist. Only requests from IPs that are on the whitelist are allowed. |
_site_ | Always allow requests from machines that are on the same network (see Appendix A). In addition, allow requests from IPs that are on the whitelist. |
Any other value | Same as “*”. |
EnableWhiteList
This setting is a Boolean value that indicates if the whitelist should be enforced. Requests will always be forwarded if this is set to false.
WhiteList
A comma or semi-colon delimited list of IP addresses that are whitelisted. Example: “10.0.32.72;10.0.45.123”. Since the whitelist is cluster-wide, whitelisting an IP address in any DSR role.config will whitelist that IP on every node in the cluster.
Example
Here is an example of what the configuration looks like in the DSR’s role.config file.
<StartupSetting Key="WatcherHost" Value="*" />
<StartupSetting Key="EnableWhiteList" Value="True" />
<StartupSetting Key="WhiteList" Value="192.168.0.3;192.168.0.4" />
2.2.1 The Default Configuration
Core comes with pre-configured whitelist settings.
Core 3.1.6 and Earlier
WatcherHost | _site_ | Accept requests from any machine on the local network and any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | empty |
With this configuration, the DocumentStoreWatcher will allow requests from machines on the same network and from machines with whitelisted IPs. If Core is installed with the default configuration on a network where there are untrusted users, they could potentially acquire or modify sensitive information through the Elasticsearch REST API or head plugin. The best practice is to always install Core on a network that is only accessible to trusted users.
Core 3.1.7 and Later
WatcherHost | * | Accept any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | empty |
With this configuration, the DocumentStoreWatcher will only allow requests from machines with whitelisted IPs. This is considered more secure than the configuration that ships with versions 3.1.6 and earlier.
2.2.2 Recommended Configurations
This section will cover the recommended configuration for some common deployment scenarios.
Single Instance of Geocortex Essentials 4.9 and earlier
With a single instance of Essentials 4.9 (Core 3.1.6), the most secure configuration is:
WatcherHost | * | Accept any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | empty |
Single Instance of Geocortex Essentials 4.10 and later
With a single instance of Essentials 4.10 (Core 3.1.7), there is no need for the DocumentStoreWatcher to allow requests that come from any other machine. In this case, the most secure configuration is:
WatcherHost | _local_ | Allow requests from the local machine only. Do not check if they are allowed by the whitelist. |
EnableWhiteList | True | Irrelevant, in this case. |
WhiteList | empty |
“_local_” is only a valid setting for WatcherHost in Core versions 3.1.7 and later. It should be noted that this is the only deployment scenario where WatcherHost can be set to “_local_”. This will not work for any Analytics deployment or for any multi-node Essentials deployment.
Multiple Instances of Geocortex Essentials and Core
With multiple instances of Core and Essentials, nodes will need to communicate with each other. However, it is desirable to prevent any other machines from accessing data in the cluster. In this case, the most secure configuration is (default in versions 3.1.7 and later):
WatcherHost | * | Accept any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | empty |
Note: There is no need to configure the WhiteList setting in this case, because nodes will automatically add themselves to the whitelist.
Geocortex Analytics 1.4.1 and Earlier
With a typical Analytics deployment, agents will need to communicate with the hub node. However, it is desirable to prevent any other machines from accessing data on the hub node. In this case, the most secure configuration is:
WatcherHost | * | Accept any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | {agent1-IP};{agent2-IP};{agent3-IP} |
Accept requests from senders with these IPs. |
Note: The WhiteList setting must be manually configured with the IP addresses of all the Analytics agents. This is because agents are not capable of automatically registering themselves on the whitelist.
Geocortex Analytics 1.4.2 and Later
In Analytics 1.4.2, agents became capable of registering themselves on the whitelist. This was done so that the DocumentStoreWatcher, by default, can refuse access to machines on the same network if they are not whitelisted. The most secure configuration for versions 1.4.2 and above is:
WatcherHost | * | Accept any requests that are allowed by the whitelist. |
EnableWhiteList | True | Deny requests from senders that are not on the whitelist. |
WhiteList | empty |
2.3 Choose a Secure Cluster Shared Secret
When installing Core, make sure to choose a secure shared secret for the cluster. The DSR provides a web endpoint that allows any party who knows the cluster’s shared secret to register themselves on the whitelist. The registered party would then have full access to the cluster’s data. It is extremely unlikely there would be unwanted access in this manner, because it requires possession of the cluster’s shared secret and intimate knowledge of the DocumentStoreWatcher.
2.4 Remove the Head Plugin (Core 3.1.6 and Earlier)
Since the Elasticsearch head plugin provides a human friendly interface to the cluster data, removing it can close off another avenue of unwanted access. It should be noted that removing the head plugin does not make the data less accessible, it simply means there is no longer a nice interface for accessing it.
Core 3.1.7 will not include the head plugin. Use the following steps to manually remove the head plugin from versions 3.1.6 and earlier:
- Stop the Core Service
- Navigate to {Install Dir}\Geocortex Core\NSRoot\Geocortex\Core\Roles\DocumentStore\3.1.x\elasticsearch-2.4.2\plugins
- Remove the “head” folder
- Start the Core Service
- Test that the web interface is not available at http://localhost:19200/_plugin/head/ or use the server name instead of localhost
Appendix A: The Local Network
The DocumentStoreWatcher can be configured to allow requests that originate from the local network by setting WatcherHost to “_site_” in the DocumentStore Role’s role.config file. A request that originates from the local network is defined as the following:
- Request that has an IPv4 source address in one of the following subnets:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- Request that has an IPv6 source address in one of the following subnets:
- FEC0::/10
- FE80::/10
Comments
0 comments
Article is closed for comments.