Skip to content

Commit 6107546

Browse files
committed
add new features for v4.0.0
1 parent 615701f commit 6107546

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+4051
-2871
lines changed

Docker/Dockerfile-volatility

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM python:3.13
2+
LABEL maintainer="SYNETIS <[email protected]>"
3+
VOLUME ["/data"]
4+
RUN pip install git+https://github.com/volatilityfoundation/volatility3.git
5+
ENTRYPOINT ["vol"]
6+
#RUN pip install volatility3

Docker/docker-compose.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ services:
44
build:
55
context: ..
66
dockerfile: Docker/Dockerfile
7-
image: pytriage:3.0.0
8-
container_name: pytriage
7+
no_cache: true
8+
image: pytriage:4.0.0
9+
container_name: pytriage-preprod
910
volumes:
1011
- /data/hayabusa:/hayabusa
1112
- /data:/data
@@ -24,7 +25,7 @@ services:
2425
ports:
2526
- 443:8080
2627
worker:
27-
image: pytriage:3.0.0
28+
image: pytriage:4.0.0
2829
command: celery --app triage.celery worker --loglevel=info
2930
environment:
3031
- CELERY_BROKER_URL=redis://redis:6379/0
@@ -47,5 +48,19 @@ services:
4748
- /winlogbeat:/winlogbeat
4849
- /var/run/docker.sock:/var/run/docker.sock
4950
redis:
50-
image: redis:7.2.5
51+
image: redis:8.2.2
52+
plaso:
53+
image: log2timeline/plaso:20240317 # must be the same in triage.yaml
54+
command: ["exit 0"]
5155

56+
filebeat:
57+
image: elastic/filebeat:8.9.1 #must be the same in triage.yaml
58+
command: ["exit 0"]
59+
60+
volatility:
61+
build:
62+
context: ..
63+
dockerfile: Docker/Dockerfile-volatility
64+
no_cache: true
65+
image: volatility3:2.26.2 #must be the same in triage.yaml
66+
command: ["exit 0"]

README.md

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22
<img src="docs/images/pytriage_blanc.png"/>
33
</p>
44

5+
<div align="center">
6+
7+
![Status](https://img.shields.io/badge/status-active-success?style=for-the-badge)
8+
![Powered By: CERT SYNETIS](https://img.shields.io/badge/Powered_By-CERT_SYNETIS-f80808.svg?style=for-the-badge)
9+
10+
</div>
11+
12+
<div align="center">
13+
514
[Introduction](#introduction) | [Fonctionnement](#fonctionnement) | [Ajout de plugin](#ajout-de-plugin) | [Déploiement](#déploiement)
615

16+
</div>
17+
718
## Introduction
819

920
Le serveur de triage a pour but d'automatiser le traitement des collectes effectuées sur les systèmes à investiguer. Il effectue le *processing* de certaines tâches (*timelining* et détection SIGMA notamment) ainsi que le *forwarding* vers les outils d'analyses (pile ELK et Timesketch si configuré dans config/triage.yaml).
@@ -47,21 +58,19 @@ Chaque collecte concerne :
4758
</p>
4859

4960
### Plugins
61+
![parsers.png](/docs/images/parsers.png)
5062

5163
#### KAPE
5264

53-
> Ce plugin s'exécute sur une collecte réalisée par kape. Le fichier d'entrée est la seconde archive ZIP contenant le fichier VHDX généré par l'outil de collecte du CERT.
54-
65+
> Ce plugin s'exécute sur une collecte réalisée par kape. Le fichier d'entrée est l'archive ZIP contenant le fichier VHDX généré par l'outil de collecte.
5566
5667
Ce plugin dézippe l'archive, monte le vhdx fournis dans un dossier créé et propre à chaque collecte.
5768

58-
![plugin_kape.png](/docs/images/plugin_kape.png)
59-
6069
Plusieurs artefacts sont traités si sélectionnés dans l'interface :
6170

62-
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour indexation
63-
OU
71+
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour parsing et indexation
6472
- Les EVTX sont parsés (par la lib python) puis envoyés à ELK
73+
- Exécution Hayabusa sur les EVTX
6574
- Les logs IIS seront extraits du vhdx, copiés dans un dossier, parsés puis envoyés à ELK
6675
- Les timelines Plaso seront créées puis envoyées à Timesketch
6776
- Parsing MFT
@@ -73,6 +82,10 @@ OU
7382
- Parsing $Recycle.Bin
7483
- Récupération des fichiers d'historique Powershell des utilisateurs
7584
- RDP Bitmap Cache parser
85+
- Parsing LNK
86+
- Parsing JumpList
87+
- Parsing Tasks
88+
- Parsing Webcache
7689

7790
#### GENERAPTOR Windows
7891

@@ -81,9 +94,9 @@ OU
8194

8295
Plusieurs artefacts sont traités si sélectionnés dans l'interface :
8396

84-
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour indexation
85-
OU
97+
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour parsing et indexation
8698
- Les EVTX sont parsés (par la lib python) puis envoyés à ELK
99+
- Exécution Hayabusa sur les EVTX
87100
- Les logs IIS seront extraits du ZIP, copiés dans un dossier, parsés puis envoyés à ELK
88101
- Une timeline Plaso est créée puis envoyée à Timesketch
89102
- Parsing MFT
@@ -95,6 +108,10 @@ OU
95108
- Parsing $Recycle.Bin
96109
- Récupération des fichiers d'historique Powershell des utilisateurs
97110
- RDP Bitmap Cache parser
111+
- Parsing LNK
112+
- Parsing JumpList
113+
- Parsing Tasks
114+
- Parsing Webcache
98115

99116
#### DFIR-ORC
100117

@@ -103,14 +120,23 @@ OU
103120

104121
Plusieurs artefacts sont traités si sélectionnés dans l'interface :
105122

106-
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour indexation
107-
OU
123+
- Les EVTX sont copiés dans un dossier puis envoyés à la VM Winlogbeat pour parsing et indexation
108124
- Les EVTX sont parsés (par la lib python) puis envoyés à ELK
125+
- Exécution Hayabusa sur les EVTX
109126
- Une timeline Plaso est créée puis envoyée à Timesketch
110127
- Parsing MFT
111128
- Parsing USNJrnl
112129
- Parsing Registres (amcache, system, security, ntuser...)
113130
- Parsing prefetch
131+
- Parsing MPLog
132+
- Parsing Windows10 Timeline (ActivitiesCache)
133+
- Parsing $Recycle.Bin
134+
- Récupération des fichiers d'historique Powershell des utilisateurs
135+
- RDP Bitmap Cache parser
136+
- Parsing LNK
137+
- Parsing JumpList
138+
- Parsing Tasks
139+
- Parsing Webcache
114140

115141
#### GENERAPTOR Linux
116142

@@ -120,6 +146,7 @@ OU
120146
Plusieurs artefacts sont traités si sélectionnés dans l'interface :
121147

122148
- Une timeline Plaso est créée puis envoyées à Timesketch
149+
- PSORT est exécuté sur le plaso précédement généré
123150
- Filebeat indexera dans ELK les logs capturés lors de la collecte
124151

125152
#### Hayabusa
@@ -137,6 +164,7 @@ Deux artefacts sont traités dans ce plugin :
137164

138165
- Filebeat indexera dans ELK les logs capturés lors de la collecte
139166
- Une timelines Plaso est créée puis envoyée à Timesketch
167+
- PSORT est exécuté sur le plaso précédement généré
140168

141169
#### ADTimeline
142170

@@ -183,7 +211,7 @@ L'archive envoyée est dézippée et les fichiers JSON présents sont parsés pu
183211

184212
![6cyimage.png](/docs/images/standalone1.png)
185213

186-
Cette partie permet de facilité l'exécution d'un plugin sur des artefacts spécifiques.
214+
Cette partie permet de faciliter l'exécution d'un plugin sur des artefacts spécifiques.
187215

188216
![gvpimage.png](/docs/images/standalone2.png)
189217

@@ -206,7 +234,11 @@ Une page d'administration est accesssible pour le moment à tout le monde car au
206234

207235

208236
Elle permet:
209-
- D'avoir une vue sur l'ensemble des collectes, de pouvoir les supprimer et récupérer le fichier de log associé.
237+
- D'avoir une vue sur l'ensemble des collectes
238+
- De supprimer des collectes
239+
- De relancer des collectes
240+
- D'arrêter des triages en cours
241+
- De récupérer les fichier de log des collectes
210242
- De supprimer des sketch TIMESKETCH
211243
- De supprimer des index ELASTIC
212244
- De mettre à jour HAYABUSA
@@ -300,10 +332,8 @@ KEYCLOAK_USERS_GROUP=CERT
300332

301333
Créer les dossiers **data**, **winlogbeat**, **log** et **hayabusa** si non présents (chemin à renseigner dans les fichiers docker-compose-build/prod.yml et dans config/triage.yaml *volumes => data* qui est le volume hôte à monter donc ici ./data)
302334
```bash
303-
mkdir ./data
304-
mkdir ./winlogbeat
305-
mkdir ./log
306-
mkdir ./hayabusa
335+
mkdir /winlogbeat
336+
mkdir -p /data/hayabusa
307337
```
308338
- Monter le partage winlogbeat dans le dossier précédement créé
309339
- Placer le binaire hayabusa et ses dépendances dans le dossier précédement créé
@@ -322,7 +352,7 @@ sudo apt install cifs-utils
322352
Start docker images
323353

324354
```bash
325-
docker compose -f Docker/docker-compose.yml up -d --build
355+
docker compose -f Docker/docker-compose.yml up -d
326356
```
327357

328358
Le service web est disponible sur https://localhost

config/triage.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pipelines:
1717
selfassessment: 5050
1818
mail: 5061
1919
google: 5051
20+
psort: 5051
2021

2122
administration:
2223
Timesketch:
@@ -30,6 +31,15 @@ administration:
3031
port: 9200
3132
username: xxx
3233
password: xxx
34+
index_patterns:
35+
- "ir-lin-*"
36+
- "ir-orc-*"
37+
- "ir-m365-*"
38+
- "ir-ad-*"
39+
- "secop-ad-*"
40+
- "ir-log-*"
41+
- "dlq-*"
42+
- "ir-evtx-*"
3343
Logstash:
3444
active: false
3545
url: "https://xxx"
@@ -51,7 +61,7 @@ docker_images:
5161
tag: "8.9.1"
5262
volatility3:
5363
image: volatility3
54-
tag: "2.5.0"
64+
tag: "2.26.2"
5565

5666
artifacts:
5767
apache:
@@ -81,3 +91,4 @@ plaso_parsers:
8191
- "!mft"
8292
- "!usnjrnl"
8393
- "!filestat"
94+

docs/images/parsers.png

44.7 KB
Loading

docs/images/user_view.png

26 KB
Loading

requirements.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ beautifulsoup4==4.13.4
1111
billiard==4.2.1
1212
black==25.1.0
1313
blinker==1.9.0
14-
Brotli==1.1.0
14+
Brotli==1.2.0
1515
bs4==0.0.2
1616
build==1.2.2.post1
1717
cachetools==5.5.2
@@ -33,6 +33,7 @@ entrypoints==0.4
3333
enum-compat==0.0.3
3434
Flask==3.1.1
3535
Flask-Login==0.6.3
36+
Flask-WTF==1.2.2
3637
flower==2.0.1
3738
frozenlist==1.7.0
3839
google-auth==2.40.3
@@ -53,10 +54,12 @@ jsonschema==4.25.0
5354
jsonschema-specifications==2025.4.1
5455
jwcrypto==1.5.6
5556
kombu==5.5.4
57+
libesedb-python==20240420
5658
libfwps-python==20240417
5759
libfwsi-python==20240423
5860
libpff-python==20231205
5961
libscca-python==20250915
62+
LnkParse3==1.5.2
6063
lxml==6.0.0
6164
mailbox==0.4
6265
markdown-it-py==3.0.0
@@ -71,6 +74,7 @@ networkx==3.5
7174
nose==1.3.7
7275
numpy==2.3.2
7376
oauthlib==3.3.1
77+
olefile==0.47
7478
packaging==25.0
7579
pandas==2.3.1
7680
pathspec==0.12.1
@@ -89,6 +93,7 @@ pycryptodome==3.23.0
8993
pycryptodomex==3.23.0
9094
Pygments==2.19.2
9195
PyJWT==2.10.1
96+
pylnk3==0.4.3
9297
pyppmd==1.2.0
9398
pyproject_hooks==1.2.0
9499
pyrsistent==0.20.0

src/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self, config=None):
2525
self.config = config
2626

2727
internal_config = triageutils.INTERNAL_CONFIG
28-
28+
self.uuid = config["uuid"]
2929
self.timesketch_url = internal_config["administration"]["Timesketch"]["url"]
3030
self.is_timesketch_active = internal_config["administration"]["Timesketch"][
3131
"active"
@@ -53,8 +53,9 @@ def __init__(self, config=None):
5353
self.adaudit_port = internal_config["pipelines"]["adaudit"]
5454
self.filebeat_port = internal_config["pipelines"]["filebeat"]
5555
self.selfassessment_port = internal_config["pipelines"]["selfassessment"]
56-
5756
self.orc_port = internal_config["pipelines"]["orc"]
57+
self.psort_port = internal_config["pipelines"]["psort"]
58+
5859
self.hayabusa_bin_path = internal_config["general"]["hayabusa_bin_path"]
5960

6061
self.winlogbeat = internal_config["administration"]["Winlogbeat"]["folder"]
@@ -86,7 +87,7 @@ def _ParseMapFile(self):
8687

8788
def run(self, logger: Logger):
8889
"""Main entry point of the plugin"""
89-
raise NotImplementedError("[BasePlugin] run() needs to be overriden")
90+
raise NotImplementedError("[BasePlugin] run() needs to be overridden")
9091

9192
def warning(self, msg):
9293
"""Logs a message at WARNING level"""

src/plugins/adaudit.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def __init__(self, conf: dict):
1616
self.adaudit_dir = os.path.join(self.upload_dir, self.audit_date, "adaudit")
1717
triageutils.create_directory_path(path=self.adaudit_dir, logger=self.logger)
1818
self.adaudit_archive = os.path.join(self.upload_dir, conf["archive"]["name"])
19+
self.config["general"]["extracted_zip"] = f"{self.adaudit_dir}"
20+
self.update_config_file(data=self.config)
1921

2022
@triageutils.LOG
2123
def adaudit_extract_zip(
@@ -210,3 +212,5 @@ def run(self, logger=None):
210212
self.error(f"[adaudit] run {str(ex)}")
211213
self.update_workflow_status(plugin="adaudit", status=Status.ERROR)
212214
raise ex
215+
finally:
216+
self.info("[adaudit] End processing")

src/plugins/adtimeline.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def __init__(self, conf: dict):
1818
self.adtimeline_dir, f"ADTimeline_{self.clientname}.json"
1919
)
2020
triageutils.create_directory_path(path=self.adtimeline_dir, logger=self.logger)
21+
self.config["general"]["extracted_zip"] = f"{self.adtimeline_dir}"
22+
self.update_config_file(data=self.config)
2123

2224
@triageutils.LOG
2325
def send_to_elk(self, json_data: list = [], logger=None):
@@ -70,3 +72,5 @@ def run(self, logger=None):
7072
self.error(f"[ADTimeline] run {str(ex)}")
7173
self.update_workflow_status(plugin="adtimeline", status=Status.ERROR)
7274
raise ex
75+
finally:
76+
self.info("[ADTimeline] End processing")

0 commit comments

Comments
 (0)