Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support to create timeline from FireEye HX .mans triage #937

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Timesketch is an open source tool for collaborative forensic timeline analysis.
#### Adding timelines
* [Create timeline from JSON/JSONL/CSV file](docs/CreateTimelineFromJSONorCSV.md)
* [Create timeline from Plaso file](docs/CreateTimelineFromPlaso.md)
* [Enable Plaso upload via HTTP](docs/EnablePlasoUpload.md)
* [Create timeline from MANS file](docs/CreateTimelineFromMANS.md)
* [Enable Plaso and MANS upload via HTTP](docs/EnablePlasoUpload.md)

#### Using Timesketch

Expand Down
27 changes: 27 additions & 0 deletions docs/CreateTimelineFromMANS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Create timeline from MANS file

You need to run version mans-to-es >= 1.0 on your Timesketch server. See the [mans_to_es documentation](https://github.com/LDO-CERT/mans_to_es) for installing mans_to_es and it's dependencies. If you haven't installed Timesketch yet, take a look at the [installation instructions](Installation.md).

When you have working installations of Timesketch and mans_to_es you can, from the command line, do:

```
$ mans_to_es.py --help
usage: MANS to ES [-h] [--filename FILENAME] [--name NAME] [--index INDEX]
[--es_host ES_HOST] [--es_port ES_PORT]
[--cpu_count CPU_COUNT] [--bulk_size BULK_SIZE] [--version]

Push .mans information in Elasticsearch index

optional arguments:
-h, --help show this help message and exit
--filename FILENAME Path of the .mans file
--name NAME Timeline name
--index INDEX ES index name
--es_host ES_HOST ES host
--es_port ES_PORT ES port
--cpu_count CPU_COUNT
cpu count
--bulk_size BULK_SIZE
Bulk size for multiprocessing parsing and upload
--version show program's version number and exit
```
6 changes: 5 additions & 1 deletion docs/EnablePlasoUpload.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Enable Plaso upload via HTTP
# Enable Plaso and MANS upload via HTTP

To enable uploading and processing of Plaso storage files, there are a couple of things to do.

Expand All @@ -18,6 +18,10 @@ https://github.com/log2timeline/plaso/wiki/Ubuntu-Packaged-Release

$ sudo apt-get install redis-server

**Install mans_to_es**

$ pip install mans-to-es

**Configure Timesketch** (/etc/timesketch.conf)

UPLOAD_ENABLED = True
Expand Down
9 changes: 6 additions & 3 deletions timesketch/lib/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,12 @@ class UploadFileForm(BaseForm):
'file',
validators=[
FileRequired(),
FileAllowed(['plaso', 'csv', 'jsonl'],
'Allowed file extensions: .plaso, .csv, or .jsonl')
])
FileAllowed(
['plaso', 'mans', 'csv', 'jsonl'],
'Allowed file extensions: .plaso, .mans, .csv, or .jsonl'
)
]
)
name = StringField('Timeline name', validators=[Optional()])
sketch_id = IntegerField('Sketch ID', validators=[Optional()])

Expand Down
51 changes: 51 additions & 0 deletions timesketch/lib/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ def _get_index_task_class(file_extension):
"""
if file_extension == 'plaso':
index_class = run_plaso
elif file_extension == 'mans':
index_class = run_mans
elif file_extension in ['csv', 'jsonl']:
index_class = run_csv_jsonl
else:
Expand Down Expand Up @@ -484,3 +486,52 @@ def run_csv_jsonl(source_file_path, timeline_name, index_name, source_type):
_set_timeline_status(index_name, status='ready')

return index_name


@celery.task(track_started=True, base=SqlAlchemyTask)
def run_mans(source_file_path, timeline_name, index_name, source_type):
"""Create a Celery task for processing mans file.

Args:
source_file_path: Path to mans file.
timeline_name: Name of the Timesketch timeline.
index_name: Name of the datastore index.
source_type: Type of file, csv or jsonl.

Returns:
Name (str) of the index.
"""
# Log information to Celery
garanews marked this conversation as resolved.
Show resolved Hide resolved
message = 'Index timeline [{0:s}] to index [{1:s}] (source: {2:s})'
logging.info(message.format(timeline_name, index_name, source_type))

try:
mans_to_es_path = current_app.config['MANS_TO_ES_PATH']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this is being done...

mans_to_es seems to be a python project, why on earth are you requiring someone to install the toola dn then use supbrocess to run it, rather than just import it as a module (have it in the requirements and then import iit)

looks to me all that the command line tool does is to parse the command line arguments and then run

            mte = MansToEs(args)
            mte.extract_mans()
            mte.parse_manifest()
            mte.parse_hits()
            mte.process()
            mte.to_elastic()
            mte.delete_temp_folder()

so you might as well just import the library and do the same here, and avoid this whole subprocess

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to follow the same behavior of plaso, when called psort.py
If you think is better to use library, we can change the approach.
We tought in this way it was easier to add features or fixes at our side without opening pr on timesketch repo.

except KeyError:
mans_to_es_path = 'mans_to_es.py'
garanews marked this conversation as resolved.
Show resolved Hide resolved

elastic_path = current_app.config['ELASTIC_HOST']
elastic_port = current_app.config['ELASTIC_PORT']

cmd = [
mans_to_es_path, '--filename', source_file_path,
'--name', timeline_name, '--index', index_name,
'--es_host', str(elastic_path), '--es_port', str(elastic_port)
]

# Run mans_to_es.py
garanews marked this conversation as resolved.
Show resolved Hide resolved
try:
if six.PY3:
subprocess.check_output(
cmd, stderr=subprocess.STDOUT, encoding='utf-8')
else:
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
# Mark the searchindex and timelines as failed and exit the task
_set_timeline_status(index_name, status='fail', error_msg=e.output)
return e.output

# Mark the searchindex and timelines as ready
_set_timeline_status(index_name, status='ready')

return index_name
2 changes: 1 addition & 1 deletion timesketch/templates/sketch/timelines.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{% if sketch.has_permission(current_user, 'write') and upload_enabled %}
<div class="card">
<h4>Import timeline</h4>
<p>You can upload either a Plaso storage file, JSONL, or a CSV file.<br>
<p>You can upload either a Plaso storage file, MANS, JSONL, or a CSV file.<br>
<i>Supported Plaso version: {{ plaso_version }}</i>
</p>
<ts-core-upload sketch-id="{{ sketch.id }}" visible="true" btn-text="'Select file'"></ts-core-upload>
Expand Down