The following are some best practices for using LimaCharlie. These will help you get started on the right foot and make your life easier.
If you're not familiar with the LimaCharlie Command Line Interface, a short introduction is available here.
Setting up the environment
The first thing you need to do is install the LimaCharlie CLI:
pip install limacharlie
Now create an API key with the following privileges:
dr.del, dr.list, dr.set, ikey.del, ikey.list, ikey.set, org.get, output.del, output.list, output.set, sensor.get, sensor.list, sensor.tag
These privileges allow you to manage your organization but not interact with sensors or query historical data (those privileges are not needed for this example).
From your terminal, login to LimaCharlie:
python -m limacharlie login # When prompted enter your Organization ID and API Key.
Everything should be ready. You can test it by fetching your configurations:
python -m limacharlie.Sync fetch
This will write a
LCConf file in your current directory. If your organization is already configured, this file will contain all your Outputs and D&R rules.
LCConf file we got from setting our environment is important. It will allow you to keep all configurations as config files. This is called Infrastructure as Code. These files are best kept under revision control. The advantage of managing your LimaCharlie deployment using these files is that it removes a lot of the human factor (who hasn't forgotten to check a specific checkbox somewhere). It will save you time and headaches, and enable you to build a robust infrastructure.
Now, our initial
fetch produced a single file, but it's unlikely you will want to keep it that way. It's much easier to maintain your configurations as multiple files where each file takes care of a specific concern.
For example, you might keep a copy of all auditing messages LimaCharlie produces somewhere for compliance. If you do, and you have multiple LimaCharlie organizations you manage, it will be easier to keep this auditing Output in its own file and to re-use it for all organizations.
This is where the
include: some-config-file.yaml statement comes in. It allows you to have a top level config file, let's call it "customer-A.yaml" which includes the more generic components like the "auditing-output.yaml" mentioned above:
For simplicity, we will assume you're using one configuration file and will leave it to you to split them according to your needs.
You can generate a set of configuration files that is a good general boilerplate setup for your organization. They will already contain some of the recommended setup described below:
# Create a directory for your configurations. mkdir myorg # Generate the default configs. python -m limacharlie init ./myorg
The fun part
Now for the fun part, let's setup some functionality.
Tags are simple. yet powerful. They will give you a uniform mechanism to apply and remove behavior, with the added advantage of always having the tags displayed in the LimaCharlie data (so you always know the context around a host from its events).
Host isolation is extremely powerful, but it can be difficult to keep track of which hosts are isolated and why. What we can do here is setup a tag, named "isolated", to apply to a sensor in order to isolate it. When the tag is removed so is isolation.
This approach makes it easy to see which hosts are isolated.
To do this, we will setup two Detection & Response rules (our swiss army knife).
# Detection # ========================= op: and rules: - op: is tagged tag: isolated event: CONNECTED - op: is path: event/IS_SEGREGATED value: 0 # Response # ========================= - action: task command: segregate_network
This rule says: if a CONNECTED event comes in from a sensor that is tagged with the "isolated" tag, and the "event/IS_SEGREGATED" value is false (0), it means someone wants the sensor to be isolated (the tag), but the sensor is not currently isolated (the value in the CONNECTED event). So the action to take is to sent the "segregate_network" command.
Now we will want another rule to do the inverse:
# Detection # ========================= op: and rules: - op: is tagged tag: isolated not: true event: CONNECTED - op: is path: event/IS_SEGREGATED value: 1 # Response # ========================= - action: task command: rejoin_network
This says: if a sensor comes in indicating it is isolated, but it is NOT tagged with "isolated", make it rejoin the network.
From this point on, this will allow you to control host isolation entirely through the use of the "isolated" tag. These rules only fire when a sensor connects, so you might also want to fire a "segregate_network" and "rejoin_network" command at the same time as tagging and untagging if you want the changes to occur imemdiately.
File integrity management
FIM tends to be platform specific. The monitored files/registries on Windows are not the same as MacOS. So we'll use two rules to setup the various monitored files and directories. You can expand the method described here to be more granular. An example of higher granularity would be monitoring specific files on Windows Domain Controllers by using tags associated with these hosts.
# Detection # ========================= op: and rules: - op: is windows event: CONNECTED # Response # ========================= - action: task command: - fim_add - --pattern - "C:\\\\*\\\\Programs\\\\Startup\\\\*" - --pattern - "\\\\REGISTRY\\\\*\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run*"
# Detection # ========================= op: and rules: - op: is mac event: CONNECTED # Response # ========================= - action: task command: - fim_add - --pattern - /Users/*/.ssh/authorized_keys - --pattern - /Users/*/Library/Services/* - --pattern - /System/Library/Services/* - --pattern - /System/Library/Extensions/*
LimaCharlie is generally extremely performant but there are some edge cases where performance suffers. For these rare situation, encoutered when deployed on high-io database servers, there is the high performance mode.
To simplify the management of applying this mode to the right sensors, we will use a "high-perf" tag:
# Detection # ========================= op: and rules: - op: is tagged tag: high-perf event: CONNECTED # Response # ========================= - action: task command: set_performance_mode --is-enabled
There is obviously a lot more that can go into your base configurations. I'd like to leave you on some possible ways you could expand your tagging rules that would result in better situational awareness of your network.
Tagging by department
You can create a rule that tags sensors based on seeing a USER_OBSERVED event and doing a lookup against a list of users exported from an Active Directory you upload to LimaCharlie as a resource. For example, this could allow you to know at a glance that a specific asset belongs to the Finance department.
Tagging by role
Most assets in the company can be assigned one or multiple roles easily by using processes observed. For example, a host running "devenv.exe" (Microsoft Visual Studio) is likely a developer, white one running "nginx" is likely a web server.
Creating tagging rules based on seeing these processes can be a quick and easy way to further enhance your awareness of your network.
Tagging for geo-location
It can be useful for a security analyst to see that a specific host has recently traveled overseas. Using the GeoLocation API, you can create a rule that, for example adds a "EU" or "USA" tag when the asset connects from these locations.