Skip to content

Commit 53d7c40

Browse files
authored
v1.2 Release (#133)
1 parent ea5c31e commit 53d7c40

22 files changed

+260
-221
lines changed

cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""BinaryAlert release version"""
2-
__version__ = '1.1.0'
2+
__version__ = '1.2.0'

docs/images/architecture.png

-275 KB
Loading

docs/source/adding-yara-rules.rst

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ In summary, BinaryAlert will copy a file from a remote repository if and only if
7979

8080
Write Your Own Rules
8181
--------------------
82-
You can add your own ``.yar`` or ``.yara`` files anywhere in the ``rules/`` directory tree. Refer to the `writing YARA rules <http://yara.readthedocs.io/en/latest/writingrules.html>`_ documentation for guidance and examples. Note that when BinaryAlert finds a file which matches a YARA rule, the rule name, `metadata <http://yara.readthedocs.io/en/latest/writingrules.html#metadata>`_, `tags <http://yara.readthedocs.io/en/latest/writingrules.html#rule-tags>`_, and matched `string <http://yara.readthedocs.io/en/latest/writingrules.html#strings>`_ names will be included in the alert for your convenience.
82+
You can add your own ``.yar`` or ``.yara`` files anywhere in the ``rules/`` directory tree. Refer to the `writing YARA rules <http://yara.readthedocs.io/en/latest/writingrules.html>`_ documentation for guidance and examples. Note that when BinaryAlert finds a file which matches a YARA rule, the rule name, `metadata <http://yara.readthedocs.io/en/latest/writingrules.html#metadata>`_, `tags <http://yara.readthedocs.io/en/latest/writingrules.html#rule-tags>`_, and matched `string <http://yara.readthedocs.io/en/latest/writingrules.html#strings>`_ names and string data will be included in the alert for your convenience.
8383

8484
.. note:: Because the folders for each remote source will be overwritten during rule cloning, we recommend keeping your own YARA rules in ``rules/private`` or similar.
8585

8686
.. _external-variables:
8787

8888
External Variables
8989
------------------
90-
In order to support the rule repositories listed above, BinaryAlert provides the following `external variables <http://yara.readthedocs.io/en/latest/writingrules.html#external-variables>`_:
90+
In order to support the rule repositories listed above, BinaryAlert provides the following `external variables <http://yara.readthedocs.io/en/latest/writingrules.html#external-variables>`_ to YARA:
9191

9292
* ``extension`` - File extension (".docx", ".exe", ".pdf", etc)
9393
* ``filename`` - File basename ("file.exe")
@@ -120,7 +120,7 @@ Disabling Rules
120120
---------------
121121
There may be times you want to disable certain YARA rules, but not delete them (e.g. rules with high false-positive rates). Since only ``.yar`` and ``.yara`` files in the ``rules/`` directory tree are bundled in a BinaryAlert deploy, you can simply rename ``rules.yar`` to any other extension, e.g. ``rules.yar.DISABLED``, to skip it during rules compilation.
122122

123-
If you want to disable an individual rule (not the entire file), you can either comment it out or prefix the rule with the ``private`` modifier to elide it from reported YARA match results. Unfortunately, there is no easy way to automatically *remove* individual rules from a file.
123+
If you want to disable an individual rule (not the entire file), you can either comment it out or prefix the rule with the ``private`` modifier to elide it from reported YARA match results.
124124

125125

126126
.. _testing_yara_rules:
@@ -141,13 +141,8 @@ To test *all* of your YARA rules, you first need to compile them into a single b
141141
142142
$ ./manage.py compile_rules # Saves "compiled_yara_rules.bin"
143143
144-
This compiled rules file is what gets bundled with the BinaryAlert analyzers. Now, from a Python interpreter:
144+
This compiled rules file is what gets bundled with the BinaryAlert analyzers, and you can use it with YARA just like any other rules file:
145145

146-
.. code-block:: python
147-
148-
import yara
149-
rules = yara.load('compiled_yara_rules.bin')
150-
matches = rules.match('file_to_text.exe')
151-
print(matches)
146+
.. code-block:: bash
152147
153-
See the `yara-python <http://yara.readthedocs.io/en/latest/yarapython.html>`_ docs for more information about using YARA from Python.
148+
$ yara compiled_yara_rules.bin file_to_test

docs/source/analyzing-files.rst

Lines changed: 127 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,144 @@
11
Analyzing Files
22
===============
33
Files uploaded to the BinaryAlert S3 bucket will be automatically queued for analysis. You can also
4-
use the analyzer to scan files from other buckets directly or in response to event notifications.
4+
invoke the analyzer directly, scan files in other buckets, or download files from CarbonBlack.
55

66
Uploading Files
77
---------------
88

9-
To upload files for analysis, you need only upload them to the BinaryAlert S3 bucket. The S3 bucket name is of the form
9+
All files uploaded to the BinaryAlert S3 bucket will be immediately queued for analysis. The S3 bucket name is of the form
1010

1111
.. code-block:: none
1212
1313
YOUR.NAME.PREFIX.binaryalert-binaries.REGION
1414
1515
When uploading to S3, any object metadata you set will be included in all match alerts. In addition, if there is a ``filepath`` metadata key, BinaryAlert will make the filepath :ref:`external variables <external-variables>` available to the YARA rules.
1616

17-
Uploaded files are persisted indefinitely so that BinaryAlert can retroactively analyze all files with every rule update. The S3 bucket has both `access logging <http://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html>`_ and `object versioning <http://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectVersioning.html>`_ enabled.
17+
Uploaded files are persisted indefinitely so that BinaryAlert can retroactively analyze all files.
18+
The S3 bucket has `access logging <http://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html>`_, `object versioning <http://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectVersioning.html>`_, `inventory <https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html>`_, and `server-side encryption <https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html>`_ enabled.
19+
20+
21+
Analyzing Existing Buckets
22+
--------------------------
23+
To scan files in other S3 buckets, you first need to grant BinaryAlert permission to access them. Modify the S3 section of your `terraform.tfvars <https://github.com/airbnb/binaryalert/blob/master/terraform/terraform.tfvars>`_ file and `deploy <deploying.html>`_ the changes:
24+
25+
.. code-block:: terraform
26+
27+
# ##### S3 #####
28+
29+
# If using BinaryAlert to scan existing S3 buckets, add the S3 and KMS resource ARNs here
30+
# (KMS if the objects are server-side encrypted)
31+
external_s3_bucket_resources = ["arn:aws:s3:::bucket-name/*"]
32+
external_kms_key_resources = ["arn:aws:kms:REGION:ACCOUNT:key/KEY-UUID"]
33+
34+
35+
Direct Invocation
36+
.................
37+
You can directly invoke the BinaryAlert analyzer to scan any S3 object it has access to. The match
38+
results will always be saved to Dynamo, but you can configure whether each request should also trigger
39+
the normal SNS alerts:
40+
41+
.. code-block:: python
42+
43+
import boto3, json
44+
45+
response = boto3.client('lambda').invoke(
46+
FunctionName='your_prefix_binaryalert_analyzer',
47+
InvocationType='RequestResponse',
48+
Payload=json.dumps({
49+
'BucketName': 'your-bucket-name', # S3 bucket name
50+
'EnableSNSAlerts': False, # Toggle SNS alerts
51+
'ObjectKeys': ['key1', 'key2'] # List of S3 object keys
52+
}),
53+
Qualifier='Production'
54+
)
55+
56+
results = json.loads(response['Payload'].read().decode('utf-8'))
57+
print(json.dumps(results, sort_keys=True, indent=4))
58+
59+
{
60+
'S3:BUCKET-NAME:KEY1': {
61+
'FileInfo': {
62+
'MD5': '...',
63+
'S3LastModified': '...',
64+
'S3Metadata': {},
65+
'SHA256': '...'
66+
},
67+
'MatchedRules': {
68+
'Rule1':
69+
'MatchedData': ['abc'],
70+
'MatchedStrings': ['$a'],
71+
'Meta': {
72+
'description': 'Test YARA rule'
73+
},
74+
'RuleFile': 'rules.yara',
75+
'RuleName': 'test_dummy_true'
76+
},
77+
'NumMatchedRules': 1
78+
}
79+
'S3:BUCKET-NAME:KEY2': {
80+
'FileInfo': {
81+
'MD5': '...',
82+
'S3LastModified': '...',
83+
'S3Metadata': {},
84+
'SHA256': '...'
85+
},
86+
'MatchedRules': {},
87+
'NumMatchedRules': 0
88+
}
89+
}
90+
91+
Configuring Event Notifications
92+
...............................
93+
You can configure other buckets to send S3 event notifications to the BinaryAlert SQS queue.
94+
To do so, create an `event notification <http://docs.aws.amazon.com/AmazonS3/latest/user-guide/enable-event-notifications.html>`_ on your existing bucket
95+
and then modify the `BinaryAlert SQS permissions <https://github.com/airbnb/binaryalert/blob/ea5c31ee55a483e5216296e3e0598e3318b7eb24/terraform/sqs.tf#L28-L33>`_ accordingly.
96+
Once configured, BinaryAlert will be automatically analyzing new objects in your existing buckets in addition to its own.
97+
98+
99+
.. _retro_scan:
100+
101+
Retroactive Analysis
102+
--------------------
103+
When adding new YARA rules to your collection, you can easily re-scan all of your files in the BinaryAlert bucket to see if any of them match the new rules:
104+
105+
.. code-block:: bash
106+
107+
$ ./manage.py retro_fast
108+
109+
This will enumerate the most recent `S3 inventory manifest <https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html>`_, adding all object keys to the analysis SQS queue.
110+
However, if your bucket is less than 48 hours old, it may not yet have an inventory manifest. In that case, you can list the objects yourself:
111+
112+
.. code-block:: bash
113+
114+
$ ./manage.py retro_slow
115+
116+
As its name suggests, enumerating the bucket directly will generally be much slower than reading the inventory, particularly for buckets with thousands of objects or more.
117+
118+
.. note:: Because the inventory may be up to 24 hours old, a ``retro_fast`` scan may miss the newest objects in the bucket. If you need to scan *all* files immediately, use ``retro_slow``.
119+
120+
In either case, once all of the objects are in the analyzer SQS queue, it will take some time for BinaryAlert to finish scanning all of them (depending on how many objects you have).
121+
`YARA matches <yara-matches.html>`_ found during a retroactive scan are treated like any other - the matches are saved to Dynamo and reported via SNS.
122+
123+
Stopping a Retro Scan
124+
.....................
125+
Sometimes, a new YARA rule you thought would be great turns out to be super noisy, flooding you with false positive alerts.
126+
Unfortunately, if you have millions of objects in your BinaryAlert bucket, a retro scan can take hours to finish.
127+
To stop a retro scan dead in its tracks, you can drop all messages from the analysis queue:
128+
129+
.. code-block:: bash
130+
131+
$ ./manage.py purge_queue
132+
133+
.. warning:: This will also drop any event notifications from newly added objects that arrived after the retro scan started. These objects won't be scanned again until either (a) the next ``retro_slow`` scan or (b) the next ``retro_fast`` after 24 hours when the new object is in the inventory.
18134

19135

20136
.. _cb_downloader:
21137

22138
CarbonBlack Downloader
23139
----------------------
24-
If you use CarbonBlack Enterprise Response, you can enable BinaryAlert's optional downloader Lambda function. The downloader copies files (and some metadata) from CarbonBlack into BinaryAlert's S3 bucket. To enable it:
140+
If you use CarbonBlack Enterprise Response, you can enable BinaryAlert's optional downloader SQS queue and Lambda function.
141+
The downloader copies files (and some metadata) from CarbonBlack into BinaryAlert's S3 bucket. To enable it:
25142

26143
.. code-block:: none
27144
@@ -32,6 +149,8 @@ If you use CarbonBlack Enterprise Response, you can enable BinaryAlert's optiona
32149
CarbonBlack URL: https://your.carbonblack.url
33150
CarbonBlack API token (only needs binary read access):
34151
152+
$ ./manage.py deploy
153+
35154
.. warning:: The API token only needs access to read binaries. Do not use a token with admin privileges, do not allow other users to share the same token, and be sure to regularly rotate the token.
36155

37156
.. note:: The API token will not be shown on screen and BinaryAlert will create a new KMS key to encrypt the credentials before saving them to the ``terraform.tfvars`` configuration file. The downloader (and no other component) is authorized to decrypt the credentials with the generated key.
@@ -51,8 +170,6 @@ Binaries downloaded from CarbonBlack are saved to the BinaryAlert S3 bucket with
51170
'filepath' # from the "observed_filenames" CarbonBlack metadata
52171
]
53172
54-
Once the downloader is enabled, you can either copy everything from CarbonBlack in one go, or you can `deploy <deploying.html>`_ the downloader components and setup real-time invocations for every new binary.
55-
56173
57174
Copy All Files
58175
..............
@@ -62,113 +179,20 @@ If you want to run a one-time job to copy every file from CarbonBlack into Binar
62179
63180
$ ./manage.py cb_copy_all
64181
65-
This runs *locally*, using multiple threads to enumerate the files in CarbonBlack and copy them over to BinaryAlert. The downloader *code* is used, but there are no Lambda invocations. This means you can copy all of the files from CarbonBlack without actually deploying the downloader components.
182+
This runs locally, using multiple threads to enumerate the files in CarbonBlack into the BinaryAlert downloader SQS queue.
66183

67184

68185
Real-Time Invocations
69186
.....................
70-
To ensure real-time file analysis, we recommend invoking the downloader every time CarbonBlack logs a ``binarystore.file.added`` event. If you use `StreamAlert <https://streamalert.io/>`_ to process CarbonBlack logs, the following `rule <https://streamalert.io/rules.html>`_ will invoke the BinaryAlert downloader for every new binary (assuming BinaryAlert is a properly configured Lambda `output <https://streamalert.io/outputs.html>`_):
187+
For real-time file analysis, we recommend publishing to the downloader SQS queue every time CarbonBlack logs a ``binarystore.file.added`` event. If you use `StreamAlert <https://streamalert.io/>`_ to process CarbonBlack logs, the following `rule <https://streamalert.io/rules.html>`_ will publish a message for every new binary (assuming the SQS queue is a properly configured StreamAlert `output <https://streamalert.io/outputs.html>`_):
71188

72189
.. code-block:: python
73190
74-
@rule(logs=['carbonblack:binarystore.file.added'],
75-
matchers=[],
76-
outputs=['aws-lambda:binaryalert'])
191+
@rule(logs=['carbonblack:binarystore.file.added'], outputs=['aws-sqs:binaryalert'])
77192
def cb_binarystore_file_added(rec):
78193
"""
79194
description: CarbonBlack found a new binary: forward to BinaryAlert for YARA analysis.
80195
"""
81196
return True
82197
83-
If you don't use StreamAlert, you can invoke the downloader yourself:
84-
85-
.. code-block:: python
86-
87-
import boto3, json
88-
boto3.client('lambda').invoke(
89-
FunctionName='your_prefix_binaryalert_downloader',
90-
InvocationType='Event', # Asynchronous invocation
91-
Qualifier='Production', # Invoke production alias
92-
Payload=json.dumps({'md5': 'FILE_MD5'}).encode('utf-8')
93-
)
94-
95-
96-
Analyzing Existing Buckets
97-
--------------------------
98-
As of v1.1, the BinaryAlert YARA analyzer is no longer restricted to just its own S3 bucket - it can
99-
read other existing buckets as well. To grant access to other buckets, modify the analyzer's
100-
IAM policy in `lambda_iam.tf <https://github.com/airbnb/binaryalert/blob/master/terraform/lambda_iam.tf>`_.
101-
102-
Direct Invocation
103-
.................
104-
You can directly invoke the BinaryAlert analyzer to scan any S3 object it has access to:
105-
106-
.. code-block:: python
107-
108-
import boto3, json
109-
110-
response = boto3.client('lambda').invoke(
111-
FunctionName='your_prefix_binaryalert_analyzer',
112-
InvocationType='RequestResponse',
113-
Qualifier='Production',
114-
Payload=json.dumps({
115-
'Records': [
116-
{
117-
's3': {
118-
'bucket': {'name': 'BUCKET-NAME'},
119-
'object': {'key': 'KEY1'}
120-
}
121-
},
122-
{
123-
's3': {
124-
'bucket': {'name': 'BUCKET-NAME'},
125-
'object': {'key': 'KEY2'}
126-
}
127-
}
128-
]
129-
})
130-
)
131-
132-
decoded = json.loads(response['Payload'].read().decode('utf-8'))
133-
print(decoded)
134-
135-
{
136-
'S3:BUCKET-NAME:KEY1': {
137-
'FileInfo': {
138-
'MD5': '...',
139-
'S3LastModified': '...',
140-
'S3Metadata': {},
141-
'SHA256': '...'
142-
},
143-
'MatchedRules': {
144-
'Rule1':
145-
'MatchedStrings': ['$a'],
146-
'Meta': {
147-
'description': 'Test YARA rule'
148-
},
149-
'RuleFile': 'rules.yara',
150-
'RuleName': 'test_dummy_true'
151-
},
152-
'NumMatchedRules': 1
153-
}
154-
'S3:BUCKET-NAME:KEY2': {
155-
'FileInfo': {
156-
'MD5': '...',
157-
'S3LastModified': '...',
158-
'S3Metadata': {},
159-
'SHA256': '...'
160-
},
161-
'MatchedRules': {},
162-
'NumMatchedRules': 0
163-
}
164-
}
165-
166-
.. note:: The analyzer will always save YARA matches to Dynamo and send alerts to the SNS topic, even when invoked directly or when analyzing other buckets.
167-
168-
Configuring Event Notifications
169-
...............................
170-
You can configure other buckets to send S3 event notifications to the BinaryAlert SQS queue
171-
(recommended) or to the analyzer directly. In either case, once configured, BinaryAlert will be
172-
automatically analyzing your existing buckets in addition to its own.
173-
See `AWS: Enable Event Notifications <http://docs.aws.amazon.com/AmazonS3/latest/user-guide/enable-event-notifications.html>`_
174-
and a `terraform example <https://www.terraform.io/docs/providers/aws/r/s3_bucket_notification.html#add-notification-configuration-to-sqs-queue>`_ to get started.
198+
You can also directly publish messages to the downloader SQS queue. Messages are expected to be in the very simple format ``{'md5': 'ABCDE....'}``

docs/source/architecture.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ BinaryAlert utilizes a `serverless <https://aws.amazon.com/serverless/>`_ archit
44

55
.. image:: ../images/architecture.png
66
:align: center
7-
:scale: 30%
7+
:scale: 80%
88
:alt: BinaryAlert Architecture
99

1010

@@ -16,5 +16,5 @@ Analysis Lifecycle
1616
3. The SQS queue automatically batches files and invokes many analyzers in parallel.
1717
4. Each analyzer scans its files using a list of pre-compiled `YARA rules <adding-yara-rules.html>`_.
1818
5. `YARA matches <yara-matches.html>`_ are saved to DynamoDB and an alert is sent to an SNS topic. You can subscribe to these alerts via `StreamAlert <https://streamalert.io>`_, email, or any other supported `SNS subscription <http://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html>`_.
19-
6. For retroactive analysis, a batching Lambda function enqueues the entire S3 bucket to be re-analyzed.
19+
6. For :ref:`retroactive analysis <retro_scan>`, the CLI will enqueue the entire S3 bucket to be re-analyzed.
2020
7. Configurable :ref:`CloudWatch alarms <metric_alarms>` will trigger if any BinaryAlert component is behaving abnormally. This will notify a different SNS topic than the one used for YARA match alerts.

docs/source/conf.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# sys.path.insert(0, os.path.abspath('.'))
2323

2424
import os
25+
import re
2526
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
2627

2728
if not on_rtd: # only import and set the theme if we're building docs locally
@@ -55,17 +56,17 @@
5556

5657
# General information about the project.
5758
project = 'BinaryAlert'
58-
copyright = '2017, Airbnb'
59-
author = 'Austin Byers'
59+
copyright = '2018, Airbnb'
60+
author = 'Airbnb'
6061

6162
# The version info for the project you're documenting, acts as replacement for
6263
# |version| and |release|, also used in various other places throughout the
6364
# built documents.
6465
#
65-
# The short X.Y version.
66-
version = '1.1'
67-
# The full version, including alpha/beta/rc tags.
68-
release = '1.1.0'
66+
with open('../../cli/__init__.py', 'r') as version_file:
67+
release = re.search(
68+
r"^__version__ = ['\"]([^'\"]+)['\"]", version_file.read(), re.MULTILINE).group(1)
69+
version = release
6970

7071
# The language for content autogenerated by Sphinx. Refer to documentation
7172
# for a list of supported languages.

0 commit comments

Comments
 (0)