Skip to content

Commit 494c1e0

Browse files
authored
Merge pull request #95 from ninoseki/add-whitelist
feat: add MISP-warninglist compatible whitelisting feature
2 parents dbe79c3 + c88abd7 commit 494c1e0

5 files changed

Lines changed: 76 additions & 1 deletion

File tree

tests/fixtures/whitelist.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "test",
3+
"version": 20200203,
4+
"description": "test",
5+
"matching_attributes": ["hostname", "domain"],
6+
"type": "hostname",
7+
"list": ["00-tv.com", "000webhost.com", "000webhostapp.com"]
8+
}

tests/test_whitelist.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import unittest
2+
from pathlib import Path
3+
4+
from threatingestor.whitelist import Whitelist
5+
6+
7+
class TestState(unittest.TestCase):
8+
def setUp(self):
9+
parent = Path(__file__).parent.absolute()
10+
path = parent / "fixtures/whitelist.json"
11+
self.whitelist = Whitelist(paths=[str(path)])
12+
13+
def test_contains(self):
14+
self.assertTrue(self.whitelist.contains("00-tv.com"))
15+
self.assertFalse(self.whitelist.contains("example.com"))

threatingestor/__init__.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import time
33
import collections
44

5-
65
from loguru import logger
76
import statsd
87
try:
@@ -16,6 +15,7 @@
1615
import threatingestor.config
1716
import threatingestor.state
1817
import threatingestor.exceptions
18+
import threatingestor.whitelist
1919

2020

2121
class Ingestor:
@@ -81,11 +81,21 @@ def __init__(self, config_file):
8181
self.operators = {name: operator(**kwargs)
8282
for name, operator, kwargs in self.config.operators()}
8383

84+
logger.debug("Initializing whitelists")
85+
self.whitelist = threatingestor.whitelist.Whitelist(self.config.whitelists())
86+
8487
except (TypeError, ConnectionError, threatingestor.exceptions.PluginError):
8588
logger.warning("Twitter config format has recently changed. See https://github.com/InQuest/ThreatIngestor/releases/tag/v1.0.0b5")
8689
logger.exception("Error initializing plugins")
8790
sys.exit(1)
8891

92+
def _is_whitelisted(self, artifact) -> bool:
93+
if self.whitelist.contains(str(artifact)):
94+
logger.debug(
95+
f"Reject {str(artifact)} from further processing because it is whitelisted."
96+
)
97+
return True
98+
return False
8999

90100
def run(self):
91101
"""Run once, or forever, depending on config."""
@@ -118,6 +128,13 @@ def run_once(self):
118128
# Save the source state.
119129
self.statedb.save_state(source, saved_state)
120130

131+
# Reject whitelisted artifacts
132+
artifacts = [
133+
artifact
134+
for artifact in artifacts
135+
if not self._is_whitelisted(artifact)
136+
]
137+
121138
# Process artifacts with each operator.
122139
for operator in self.operators:
123140
logger.debug(f"Processing {len(artifacts)} artifacts from source '{source}' with operator '{operator}'")

threatingestor/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,7 @@ def operators(self):
162162

163163
logger.debug(f"Found {len(operators)} total operators")
164164
return operators
165+
166+
def whitelists(self):
167+
"""Returns whitelist list."""
168+
return self.config.get("whitelists", [])

threatingestor/whitelist.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import json
2+
from pathlib import Path
3+
from typing import List, Set
4+
5+
from loguru import logger
6+
7+
class Whitelist:
8+
"""Base class for Whitelist plugin."""
9+
10+
def __init__(self, paths: List[str]):
11+
self.paths = paths
12+
self.values: Set[str] = set()
13+
self._load_paths()
14+
15+
def contains(self, value: str) -> bool:
16+
return value in self.values
17+
18+
def _load_path(self, path: str):
19+
if Path(path).is_file():
20+
try:
21+
with open(path) as f:
22+
data = json.load(f)
23+
list_ = data.get("list", [])
24+
self.values.update(list_)
25+
except json.decoder.JSONDecodeError:
26+
logger.exception(f"Couldn't load {path} as a JSON file")
27+
28+
29+
def _load_paths(self):
30+
for path in self.paths:
31+
self._load_path(path)

0 commit comments

Comments
 (0)