From 20d8a2561a21c4e3ea79ba66d617887a7b0f34f0 Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:47:05 -0500 Subject: [PATCH 01/19] Fix Docker errors --- app/__init__.py | 20 +++++++++++++++----- requirements.txt | 2 +- setup.py | 14 +------------- testing_config.py | 13 +++++-------- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 512ebc36..ae5ff146 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,3 +1,8 @@ +import os +import sys +import logging +import datetime +import distutils import functools from flask import Flask, abort, jsonify, request @@ -10,14 +15,19 @@ from functools import wraps, update_wrapper from flask_caching import Cache from flask_selfdoc import Autodoc -import datetime -import logging -import os -import distutils app = Flask(__name__, static_url_path='') -app.config.from_object("config") + +if os.path.exists("testing_config.py") and not os.path.exists("config.py"): + app.config.from_object("testing_config") + +if os.path.exists("config.py"): + app.config.from_object("config") + +if not os.path.exists("config.py") and not os.path.exists("testing_config.py"): + print("Missing configuration settings") + sys.exit(1) if app.config.get('REDIS_CACHE_URL', None): cache = Cache(app, config={'CACHE_TYPE': 'redis', 'CACHE_REDIS_URL': app.config.get('REDIS_CACHE_URL')}) diff --git a/requirements.txt b/requirements.txt index 64cc23f2..fd49d12d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -93,7 +93,7 @@ sqlparse==0.4.2 Tempita==0.5.2 termcolor==1.1.0 tabulate==0.8.9 -threatkb==0.1.1 +threatkb==1.0.0a2 typing_extensions==4.4.0 urllib3==1.26.9 uWSGI==2.0.20 diff --git a/setup.py b/setup.py index 242615ce..8c8312b6 100644 --- a/setup.py +++ b/setup.py @@ -4,28 +4,19 @@ name='threatkb', version='0.1.1', description='Knowledge base workflow management for Yara rules and C2 artifacts (IP, DNS, SSL)', - url='https://github.com/InQuest/ThreatKB', - author='Daniel Tijerina, Rohan Kotian, David Cuellar, Ryan Shipp, Pedram Amini', author_email='ryan.ship@inquest.net, pedram@inquest.net', - classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: InfoSec', - 'Licence :: ', - 'Programming Language :: Python :: 2.7', ], - keywords='infosec yara c2 management', - py_modules=['config'], packages=find_packages(exclude=['migrations', 'venv', 'contrib', 'docs', 'tests', 'build', 'dist', 'flask']), - - license='...', - + license='GPL-2.0', install_requires=[ 'alembic==1.7.7', 'amqp==5.1.1', @@ -90,18 +81,15 @@ 'WTForms==3.0.1', 'yara-python==4.2.0' ], - extra_require={ 'dev': [], 'test': [], }, - include_package_data=True, package_data={ 'statics': ['app/static/*'], 'config': ['config.py'] }, - entry_points={ 'console_scripts': [ 'hunt = hunting.macro_hunter.cli:main', diff --git a/testing_config.py b/testing_config.py index 2da64678..5cbc3ac9 100644 --- a/testing_config.py +++ b/testing_config.py @@ -1,8 +1,7 @@ -import os -import sys +import os, sys, logging -from flask_bcrypt import Bcrypt from flask import Flask +from flask_bcrypt import Bcrypt SQL_PROTOCOL = os.getenv('SQL_PROTOCOL', 'mysql') SQL_HOST = os.getenv('SQL_HOST', '127.0.0.1') @@ -19,16 +18,14 @@ database = SQL_DATABASE ) +LOGGING_LEVEL = getattr(logging, os.getenv('LOGGING_LEVEL', 'DEBUG')) + SQLALCHEMY_TRACK_MODIFICATIONS = False # Dummy user for tests. TEST_USER = 'admin' TEST_PASSWORD = 'password' - -app = Flask(__name__, static_url_path="") -b = Bcrypt(app) -TEST_PASSWORD_HASHED = b.generate_password_hash(TEST_PASSWORD) - +TEST_PASSWORD_HASHED = Bcrypt(Flask(__name__, static_url_path="")).generate_password_hash(TEST_PASSWORD) try: SQLALCHEMY_DATABASE_URI From d21352490c6fcee5168f5e4f4603a61ce8ed40bb Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:51:25 -0500 Subject: [PATCH 02/19] Remove wiki --- {wiki/res => .github/wiki}/inquest_logo.svg | 0 .../wiki}/threatkb-db-struct.svg | 0 README.md | 18 +++----- wiki/README.md | 13 ------ wiki/db-struct.md | 5 -- wiki/docker.md | 18 -------- wiki/documentation.md | 15 ------ wiki/faq.md | 7 --- wiki/getting-started.md | 34 -------------- wiki/licensing.md | 3 -- wiki/setup.md | 46 ------------------- 11 files changed, 6 insertions(+), 153 deletions(-) rename {wiki/res => .github/wiki}/inquest_logo.svg (100%) rename {wiki/res => .github/wiki}/threatkb-db-struct.svg (100%) delete mode 100644 wiki/README.md delete mode 100644 wiki/db-struct.md delete mode 100644 wiki/docker.md delete mode 100644 wiki/documentation.md delete mode 100644 wiki/faq.md delete mode 100644 wiki/getting-started.md delete mode 100644 wiki/licensing.md delete mode 100644 wiki/setup.md diff --git a/wiki/res/inquest_logo.svg b/.github/wiki/inquest_logo.svg similarity index 100% rename from wiki/res/inquest_logo.svg rename to .github/wiki/inquest_logo.svg diff --git a/wiki/res/threatkb-db-struct.svg b/.github/wiki/threatkb-db-struct.svg similarity index 100% rename from wiki/res/threatkb-db-struct.svg rename to .github/wiki/threatkb-db-struct.svg diff --git a/README.md b/README.md index dce147c3..068f2231 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ -

- +

### NOTE: THIS REPO IS IN AN ALPHA STATE -ThreatKB is a knowledge base workflow management dashboard for Yara rules and C2 artifacts. Rules are categorized and used to denote intent, severity, and confidence on accumulated artifacts. +ThreatKB is a knowledge base workflow management dashboard for YARA rules and C2 artifacts. Rules are categorized and used to denote intent, severity, and confidence in accumulated artifacts. -To start using ThreatKB, follow our [guide](wiki/setup.md). +To start using ThreatKB, check out our [wiki](https://github.com/InQuest/ThreatKB/wiki). - --- +--- Installing by Docker is the currently recommended way of setting up ThreatKB, directions are included as the first link in the wiki. Installation by source is included in the wiki as well. - ## Table of Contents * [Docker Installation](wiki/docker.md) @@ -29,13 +27,9 @@ Installing by Docker is the currently recommended way of setting up ThreatKB, di * [Documentation](wiki/documentation.md) * [FAQ](wiki/faq.md) - - ## Thank You -ThreatKB utilizes Plyara to parse yara rules into python dictionaries. A huge thank you to the Plyara team! Links to the project are below: +ThreatKB utilizes Plyara to parse YARA rules into Python dictionaries. A huge thank you to the Plyara team! Links to the project are below: -https://github.com/8u1a/plyara -https://github.com/8u1a/plyara/blob/master/LICENSE +- [Plyara](https://github.com/8u1a/plyara) ([LICENSE](https://github.com/8u1a/plyara/blob/master/LICENSE)) When a release is created, the system first pulls all signatures that are in the release state. Then, it gathers all signatures that are in the staging state and checks their revision history for the most recently released revision that is in the release state. If it finds it, it will include it in the release. If it does not find any previously released revisions, it will skip the signature. - diff --git a/wiki/README.md b/wiki/README.md deleted file mode 100644 index 8ca2866c..00000000 --- a/wiki/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Table of Contents - -* [Setup ThreatKB](setup.md) - + [Pre-requisites](setup.md#pre-requisites) - + [System Prep](setup.md#system-prep) -* [Getting Started](getting-started.md) - + [Application Install](getting-started.md#application-install) - + [Running ThreatKB](getting-started.md#running-threatkb) - + [Admin User Creation](getting-started.md#admin-user-creation) -* [Docker Installation](docker.md) -* [Databases](db-struct.md) -* [Documentation](documentation.md) -* [FAQ](faq.md) diff --git a/wiki/db-struct.md b/wiki/db-struct.md deleted file mode 100644 index 6d455e5e..00000000 --- a/wiki/db-struct.md +++ /dev/null @@ -1,5 +0,0 @@ -# Database Structure - -

- -

diff --git a/wiki/docker.md b/wiki/docker.md deleted file mode 100644 index 7e3a0e89..00000000 --- a/wiki/docker.md +++ /dev/null @@ -1,18 +0,0 @@ -## Docker Installation -1. Edit docker-compose.yml if you change to change defaults such as ports or credentials -2. Build the Docker image: `docker build -t threatkb .` -3. Execute docker-compuse: `docker-compose up` -4. Open your browser to http://127.0.0.1:5000/#!/login - -**Example output:** -``` -$ docker-compose up --Starting inquestkb_db_1 ... --Starting inquestkb_db_1 ... done --Recreating inquestkb_threatkb_1 ... --Recreating inquestkb_threatkb_1 ... done --Attaching to inquestkb_db_1, inquestkb_threatkb_1 --....snip... --threatkb_1 | * Debugger is active! --threatkb_1 | * Debugger PIN: 212-674-856 -``` diff --git a/wiki/documentation.md b/wiki/documentation.md deleted file mode 100644 index ef273714..00000000 --- a/wiki/documentation.md +++ /dev/null @@ -1,15 +0,0 @@ -# Documentation - - - -### Release Logic - -Releases are controlled by artifact states. States are configurable in the States admin section. There are 4 kinds of states: -1. **Release state** - This is the state artifacts go into when you want to release them. -2. **Staging state** - This is the state artifacts go into when they are being prepped for release. Any signature that is in the release state and is modified automatically get put into the staging state by the system. Only relevant for signatures. -3. **Retired state** - This excludes a previously released artifact from future releases. Only relevant for signatures. -4. **Any other state** - Any other state has no significance on releases. These will not be included in releases. - -The Release, Staging, and Retired states must be configured in the admin section *before* you can generate a release. If they are not, the system will error out. - -When a release is created, the system first pulls all signatures that are in the release state. Then, it gathers all signatures that are in the staging state and checks their revision history for the most recently released revision that is in the release state. If it finds it, it will include it in the release. If it does not find any previously released revisions, it will skip the signature. diff --git a/wiki/faq.md b/wiki/faq.md deleted file mode 100644 index d3a1e62a..00000000 --- a/wiki/faq.md +++ /dev/null @@ -1,7 +0,0 @@ -# Frequently Asked Questions - - - -#### What is ThreatKB? - -ThreatKB is a knowledge base workflow management system for Yara rules and C2 artifacts (IP, DNS, SSL) diff --git a/wiki/getting-started.md b/wiki/getting-started.md deleted file mode 100644 index 581947ea..00000000 --- a/wiki/getting-started.md +++ /dev/null @@ -1,34 +0,0 @@ -# Getting Started - -### Running ThreatKB - -It's best to run the application and it's Python virtualenv within a screen session to ensure ThreatKB continues to run. - -**Note:** Within screen, Ctrl+a+d will dettach your session and return you to your normal shell. To return to the screen session, run `screen -r threatkb` - -1. Start a screen session for the application to run within: - - `cd /opt/ThreatKB && screen -dmS threatkb InQuest_ThreatKB` -2. Inside of screen, start the virtualenv: - - `source env/bin/activate` -3. Start the celery workers: - - `celery -A app.celeryapp.celery work -E` - - This is required in order for testing against your clean corpus of files -4. Build the database tables and columns: - - `env/bin/python3 manage.py db upgrade` -4. Run the application: - - `env/bin/python3 run.py` - - Follow the instructions below on creating your first Admin user before continuing to next step -5. Open your browser to http://127.0.0.1:5000/#!/login and get started using ThreatKB! - - -### Admin User Creation -1. Hash your password for MySQL kb_users table: - - `env/bin/python3 hash_pass.py yourSecretPassword` -2. Connect to MySQL instance and insert your admin user (replace values below as needed): - - `INSERT INTO kb_users (email, password, admin, active) VALUES ('user@domain.com', '', 1, 1);` - - ----- -#### Installation Complete - -ThreatKB is now running. To learn more about this project, explore the [wiki](README.md). diff --git a/wiki/licensing.md b/wiki/licensing.md deleted file mode 100644 index e87bef8b..00000000 --- a/wiki/licensing.md +++ /dev/null @@ -1,3 +0,0 @@ -# Licensing - -**TODO** diff --git a/wiki/setup.md b/wiki/setup.md deleted file mode 100644 index df7bbe9e..00000000 --- a/wiki/setup.md +++ /dev/null @@ -1,46 +0,0 @@ -### Pre-requisites - -Tested on Ubuntu Linux 14.04 -> 18.10 - -1. Install system dependencies and libraries: - - `sudo apt-get install git screen libffi-dev libssl-dev libsqlite3-dev libmysqlclient-dev` -2. Install Python and associated packages: - - `sudo apt-get install python2.7 python-pip python-dev libpython-dev` -3. Install Python virtualenv library: - - `pip install virtualenv` -3. Install databases: - - `sudo apt-get install mysql-server redis-server` -4. Install front-end packages: - - `sudo apt-get install nodejs npm && npm install -g bower` - - On some systems, nodejs is installed as either `/usr/bin/node` or `/usr/bin/nodejs`, if it is installed as `/usr/bin/nodejs` simply run the command `sudo cp /usr/bin/nodejs /usr/bin/node` for the npm install command to work properly - -**Note:** If you are running on CentOS, install these dependencies: -`yum install MySQL-python libffi-devel mysql mysql-devel mysql-lib` - -### System Prep -1. Create system user: `sudo useradd -d /opt/ThreatKB -s /bin/bash -m -U threatkb` -2. Clone repo: `sudo git clone -b master https://github.com/InQuest/ThreatKB.git /opt/ThreatKB/install` -3. Fix permissions of /opt/ThreatKB if needed: `sudo chown -R threatkb:threatkb /opt/ThreatKB` -4. In MySQL shell as root user: - - Create MySQL database: `CREATE DATABASE threatkb;` - - Create MySQL user: `CREATE USER 'threatkb'@'localhost' IDENTIFIED BY 'password';` - - Allow permissions: `GRANT ALL PRIVILEGES ON threatkb . * TO 'threatkb'@'localhost';` - - Flush privileges: `FLUSH PRIVILEGES;` -5. Update SQL config in /opt/ThreatKB/config.py parameters: - - SQL_HOST - - SQL_USERNAME - - SQL_PASSWORD - -### Application Install -**Note:** These steps and the execution of ThreatKB should be ran under the `threatkb` local user you created earlier - -1. Run `./install.sh` - - Setups a Python virtual environment in the directory `/opt/ThreatKB/flask` - - Installs required node libraries for front-end - -By default Flask will listen on 127.0.0.1:5000, if you want to change this modify the `app.run()` command inside `/opt/ThreatKB/run.py` - ----- -#### Setup Complete - -Now that you are finished with setup, head to [Getting Started](getting-started.md). From 2a568efbb90b3fd1e6e1a8e2b5835a92308c0653 Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:09:05 -0500 Subject: [PATCH 03/19] Update README.md --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 068f2231..81d06a2d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@

- +

- ### NOTE: THIS REPO IS IN AN ALPHA STATE ThreatKB is a knowledge base workflow management dashboard for YARA rules and C2 artifacts. Rules are categorized and used to denote intent, severity, and confidence in accumulated artifacts. @@ -15,21 +14,22 @@ Installing by Docker is the currently recommended way of setting up ThreatKB, di ## Table of Contents -* [Docker Installation](wiki/docker.md) -* [Setup ThreatKB](wiki/setup.md) - + [Pre-requisites](wiki/setup.md#pre-requisites) - + [System Prep](wiki/setup.md#system-prep) -* [Getting Started](wiki/getting-started.md) - + [Application Install](wiki/getting-started.md#application-install) - + [Running ThreatKB](wiki/getting-started.md#running-threatkb) - + [Admin User Creation](wiki/getting-started.md#admin-user-creation) -* [Databases](wiki/db-struct.md) -* [Documentation](wiki/documentation.md) -* [FAQ](wiki/faq.md) +* [Home](https://github.com/InQuest/ThreatKB/wiki) +* [Setup ThreatKB](https://github.com/InQuest/ThreatKB/wiki/Setup#pre-requisites) + + [Pre-requisites](https://github.com/InQuest/ThreatKB/wiki/Setup#pre-requisites) + + [System Prep](https://github.com/InQuest/ThreatKB/wiki/Setup#system-prep) + + [Application Install](https://github.com/InQuest/ThreatKB/wiki/Setup#application-install) +* [Getting Started](https://github.com/InQuest/ThreatKB/wiki/Getting-Started) + + [Running ThreatKB](https://github.com/InQuest/ThreatKB/wiki/Getting-Started#running-threatkb) + + [Admin User Creation](https://github.com/InQuest/ThreatKB/wiki/Getting-Started#running-threatkb) +* [Docker Installation](https://github.com/InQuest/ThreatKB/wiki/Docker) +* [Database Structure](https://github.com/InQuest/ThreatKB/wiki/Database-Structure) +* [Documentation](https://github.com/InQuest/ThreatKB/wiki/Documentation) +* [FAQ](https://github.com/InQuest/ThreatKB/wiki/Frequently-Asked-Questions) ## Thank You ThreatKB utilizes Plyara to parse YARA rules into Python dictionaries. A huge thank you to the Plyara team! Links to the project are below: -- [Plyara](https://github.com/8u1a/plyara) ([LICENSE](https://github.com/8u1a/plyara/blob/master/LICENSE)) +- [Plyara](https://github.com/plyara/plyara) ([LICENSE](https://github.com/plyara/plyara/blob/master/LICENSE)) When a release is created, the system first pulls all signatures that are in the release state. Then, it gathers all signatures that are in the staging state and checks their revision history for the most recently released revision that is in the release state. If it finds it, it will include it in the release. If it does not find any previously released revisions, it will skip the signature. From 035c8b9b6db47ddf64656581c1d463c01a9cea35 Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:12:01 -0500 Subject: [PATCH 04/19] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 81d06a2d..b6503226 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ Installing by Docker is the currently recommended way of setting up ThreatKB, di ## Table of Contents * [Home](https://github.com/InQuest/ThreatKB/wiki) -* [Setup ThreatKB](https://github.com/InQuest/ThreatKB/wiki/Setup#pre-requisites) +* [Setup ThreatKB](https://github.com/InQuest/ThreatKB/wiki/Setup) + [Pre-requisites](https://github.com/InQuest/ThreatKB/wiki/Setup#pre-requisites) + [System Prep](https://github.com/InQuest/ThreatKB/wiki/Setup#system-prep) + [Application Install](https://github.com/InQuest/ThreatKB/wiki/Setup#application-install) * [Getting Started](https://github.com/InQuest/ThreatKB/wiki/Getting-Started) + [Running ThreatKB](https://github.com/InQuest/ThreatKB/wiki/Getting-Started#running-threatkb) - + [Admin User Creation](https://github.com/InQuest/ThreatKB/wiki/Getting-Started#running-threatkb) + + [Admin User Creation](https://github.com/InQuest/ThreatKB/wiki/Getting-Started#admin-user-creation) * [Docker Installation](https://github.com/InQuest/ThreatKB/wiki/Docker) * [Database Structure](https://github.com/InQuest/ThreatKB/wiki/Database-Structure) * [Documentation](https://github.com/InQuest/ThreatKB/wiki/Documentation) From 102163deaf05dcec6d3ff922a1858f36f9bad3e4 Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:21:24 -0500 Subject: [PATCH 05/19] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6503226..9fedcb21 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

### NOTE: THIS REPO IS IN AN ALPHA STATE From 6eae967f391fc375c327fb0f66e09455db1e2131 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 03:19:35 +0000 Subject: [PATCH 06/19] Bump cryptography from 37.0.1 to 39.0.1 Bumps [cryptography](https://github.com/pyca/cryptography) from 37.0.1 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/37.0.1...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fd49d12d..4836a430 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ click==8.1.2 click-didyoumean==0.3.0 click-plugins==1.1.1 click-repl==0.2.0 -cryptography==37.0.1 +cryptography==39.0.1 decorator==5.1.1 deepdiff==5.8.0 defusedxml==0.7.1 From 1854b027a8b1ec5d9efaa10ab1d95dfa8b2da71e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:13:02 +0000 Subject: [PATCH 07/19] Bump redis from 2.10.6 to 4.4.4 Bumps [redis](https://github.com/redis/redis-py) from 2.10.6 to 4.4.4. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/2.10.6...v4.4.4) --- updated-dependencies: - dependency-name: redis dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4836a430..8dd2f39d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -80,7 +80,7 @@ python-openid==2.2.5 python3-openid==3.2.0 pytz==2022.1 pyzipcode==3.0.1 -redis==4.2.2 +redis==4.4.4 requests==2.27.1 semantic-version==2.10.0 setuptools-rust==1.5.2 diff --git a/setup.py b/setup.py index 8c8312b6..375aaa9a 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ 'python-openid==2.2.5', 'pytz==2022.1', 'pyzipcode==3.0.1', - 'redis==4.2.2', + 'redis==4.4.4', 'requests==2.27.1', 'six==1.16.0', 'speaklater==1.3', From 2358ccfdee5c0bb33207ddb04ea5a71251d1eee0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:15:08 +0000 Subject: [PATCH 08/19] Bump werkzeug from 0.15.5 to 2.2.3 Bumps [werkzeug](https://github.com/pallets/werkzeug) from 0.15.5 to 2.2.3. - [Release notes](https://github.com/pallets/werkzeug/releases) - [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/werkzeug/compare/0.15.5...2.2.3) --- updated-dependencies: - dependency-name: werkzeug dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8dd2f39d..e4e40748 100644 --- a/requirements.txt +++ b/requirements.txt @@ -99,7 +99,7 @@ urllib3==1.26.9 uWSGI==2.0.20 vine==5.0.0 wcwidth==0.2.5 -Werkzeug==0.15.5 +Werkzeug==2.2.3 Whoosh==2.7.4 wrapt==1.14.0 WTForms==3.0.1 diff --git a/setup.py b/setup.py index 375aaa9a..69293e16 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ 'Tempita==0.5.2', 'urllib3==1.26.9', 'vine==5.0.0', - 'Werkzeug==0.15.5', + 'Werkzeug==2.2.3', 'Whoosh==2.7.4', 'WTForms==3.0.1', 'yara-python==4.2.0' From 24f5ab371acefae1172dbec90b1696f118fd9a52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 22:04:42 +0000 Subject: [PATCH 09/19] Bump sqlparse from 0.4.2 to 0.4.4 Bumps [sqlparse](https://github.com/andialbrecht/sqlparse) from 0.4.2 to 0.4.4. - [Release notes](https://github.com/andialbrecht/sqlparse/releases) - [Changelog](https://github.com/andialbrecht/sqlparse/blob/master/CHANGELOG) - [Commits](https://github.com/andialbrecht/sqlparse/compare/0.4.2...0.4.4) --- updated-dependencies: - dependency-name: sqlparse dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e4e40748..8748b9b6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -89,7 +89,7 @@ six==1.16.0 speaklater==1.3 SQLAlchemy==1.4.36 sqlalchemy-migrate==0.13.0 -sqlparse==0.4.2 +sqlparse==0.4.4 Tempita==0.5.2 termcolor==1.1.0 tabulate==0.8.9 From c52c736ac2c55986b20c9763eb51aad7b3bd98fb Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Wed, 31 May 2023 19:49:52 -0500 Subject: [PATCH 10/19] Fixing file issue. --- app/routes/files.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/routes/files.py b/app/routes/files.py index 510ce449..a826ce7c 100644 --- a/app/routes/files.py +++ b/app/routes/files.py @@ -254,9 +254,7 @@ def get_file_for_entity(entity_type, entity_id, file_id): if not file_entity: abort(404) - full_path = os.path.join(cfg_settings.Cfg_settings.get_setting("FILE_STORE_PATH"), - str(ENTITY_MAPPING[entity_type]) if entity_type != "0" else "", - str(entity_id) if entity_id != 0 else "", + full_path = os.path.join(file_entity.full_path, secure_filename(file_entity.filename)) if not os.path.exists(full_path): abort(404) From bd456b7dff6f8e1389aa47aa00359fb971c1227e Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Sun, 16 Apr 2023 19:35:58 -0500 Subject: [PATCH 11/19] #457 : small fix to ensure empty version file doesn't blow up Dashboard. --- .gitignore | 2 ++ app/routes/version.py | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4235ade9..065c4a0c 100755 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,5 @@ dump.rdb # STS (Spring Tool Suite) .springBeans .vagrant + +version diff --git a/app/routes/version.py b/app/routes/version.py index b13126f4..dd4130d6 100644 --- a/app/routes/version.py +++ b/app/routes/version.py @@ -11,7 +11,10 @@ def get_version(): Return: version number""" try: version = [v.strip() for v in open("version", "r").readlines()] + return Response( + json.dumps({"version": version[0], "version_email": version[1], "version_date": version[2][:-6]}), + mimetype='application/json') except: - version = ["unavailable", "unavailable", "unavailable"] - return Response(json.dumps({"version": version[0], "version_email": version[1], "version_date": version[2][:-6]}), - mimetype='application/json') + return Response( + json.dumps({"version": "unavailable", "version_email": "unavailable", "version_date": "unavailable"}), + mimetype='application/json') From 6f8510aeefb08ec1c4b2503eecf291e0d02d7f23 Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Sun, 16 Apr 2023 21:06:43 -0500 Subject: [PATCH 12/19] #368 : Setting yara_rule_string after hotkey save. --- app/routes/yara_rules.py | 2 +- app/static/js/yara_rule/yara_rule-controller.js | 1 + app/static/views/c2dns/c2dns.html | 8 ++++---- app/static/views/c2ip/c2ips.html | 8 ++++---- app/static/views/yara_rule/yara_rules.html | 8 ++++---- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/routes/yara_rules.py b/app/routes/yara_rules.py index b9c749f8..d202a7eb 100755 --- a/app/routes/yara_rules.py +++ b/app/routes/yara_rules.py @@ -599,7 +599,7 @@ def update_yara_rule(id): if tags_to_create: create_tags_mapping(entity.__tablename__, entity.id, tags_to_create) - return jsonify(entity.to_dict()), 200 + return jsonify(entity.to_dict(include_yara_rule_string=True)), 200 @app.route('/ThreatKB/yara_rules/batch/edit', methods=['PUT']) diff --git a/app/static/js/yara_rule/yara_rule-controller.js b/app/static/js/yara_rule/yara_rule-controller.js index 4ba8a475..231c52fe 100755 --- a/app/static/js/yara_rule/yara_rule-controller.js +++ b/app/static/js/yara_rule/yara_rule-controller.js @@ -784,6 +784,7 @@ angular.module('ThreatKB') growl.error(error.data, {ttl: -1}); } else { $scope.yara_rule.state = data.state; + $scope.yara_rule.yara_rule_string = data.yara_rule_string; growl.info("Successfully saved signature '" + $scope.yara_rule.name + "'.", {ttl: 2000}); } }, diff --git a/app/static/views/c2dns/c2dns.html b/app/static/views/c2dns/c2dns.html index 61240a94..b91ebe2b 100755 --- a/app/static/views/c2dns/c2dns.html +++ b/app/static/views/c2dns/c2dns.html @@ -80,13 +80,13 @@
- + Toggle full screen diff --git a/app/static/views/c2ip/c2ips.html b/app/static/views/c2ip/c2ips.html index 6fa0d6da..bcf7edac 100755 --- a/app/static/views/c2ip/c2ips.html +++ b/app/static/views/c2ip/c2ips.html @@ -97,13 +97,13 @@
- + Toggle full screen diff --git a/app/static/views/yara_rule/yara_rules.html b/app/static/views/yara_rule/yara_rules.html index 5d942ae9..c8839062 100755 --- a/app/static/views/yara_rule/yara_rules.html +++ b/app/static/views/yara_rule/yara_rules.html @@ -79,13 +79,13 @@
+
+ +
-
From 1151b6c7da9037c880a0027197612764aec55e65 Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Wed, 31 May 2023 22:20:51 -0500 Subject: [PATCH 14/19] Category prefixes and rule name validation. --- .../js/yara_rule/yara_rule-controller.js | 40 +++++++++++++--- .../65e3f200abd3_category_prefix_mapping.py | 47 +++++++++++++++++++ 2 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 migrations/versions/65e3f200abd3_category_prefix_mapping.py diff --git a/app/static/js/yara_rule/yara_rule-controller.js b/app/static/js/yara_rule/yara_rule-controller.js index 767725df..f76c0564 100755 --- a/app/static/js/yara_rule/yara_rule-controller.js +++ b/app/static/js/yara_rule/yara_rule-controller.js @@ -713,7 +713,16 @@ angular.module('ThreatKB') } ); } - + let category_prefixes = Cfg_settings.get({key: "CATEGORY_PREFIX_MAPPING"}); + if (category_prefixes.$promise !== null && category_prefixes.$promise !== undefined) { + category_prefixes.$promise.then( + function (category_prefixes) { + if (category_prefixes !== null && category_prefixes.value !== null) { + $scope.category_prefixes = JSON.parse(category_prefixes.value); + } + } + ); + } var mitre_techniques = Cfg_settings.get({key: "MITRE_TECHNIQUES"}); if (mitre_techniques.$promise !== null && mitre_techniques.$promise !== undefined) { @@ -994,13 +1003,30 @@ angular.module('ThreatKB') }; $scope.ok = function () { - // Check if outstanding comment - if ($scope.yara_rule.new_comment && $scope.yara_rule.new_comment.trim() && confirm('There is a unsaved comment, do you wish to save it as well?')) { - $scope.add_comment($scope.yara_rule.id); + // Ensure that Rule name starts with Category Prefix + let category; + let validationPassed = true; + if ($scope.yara_rule.category && (typeof $scope.yara_rule.category === 'object')) { + category = $scope.yara_rule.category.category; + } else { + category = $scope.yara_rule.category; + } + if ($scope.category_prefixes.hasOwnProperty(category)) { + let expectedPrefix = $scope.category_prefixes[category] + "_"; + if (!$scope.yara_rule.name.startsWith(expectedPrefix)) { + alert("Rule Name " + $scope.yara_rule.name + " must start with " + expectedPrefix + " based on selected Category."); + validationPassed = false; + } + } + if (validationPassed) { + // Check if outstanding comment + if ($scope.yara_rule.new_comment && $scope.yara_rule.new_comment.trim() && confirm('There is a unsaved comment, do you wish to save it as well?')) { + $scope.add_comment($scope.yara_rule.id); + } + // Close modal + $window.document.title = "ThreatKB"; + $uibModalInstance.close($scope.yara_rule); } - // Close modal - $window.document.title = "ThreatKB"; - $uibModalInstance.close($scope.yara_rule); }; $scope.cancel = function () { diff --git a/migrations/versions/65e3f200abd3_category_prefix_mapping.py b/migrations/versions/65e3f200abd3_category_prefix_mapping.py new file mode 100644 index 00000000..79c1a5d9 --- /dev/null +++ b/migrations/versions/65e3f200abd3_category_prefix_mapping.py @@ -0,0 +1,47 @@ +"""Category Prefix Mapping + +Revision ID: 65e3f200abd3 +Revises: fc0cab9d77dc +Create Date: 2023-05-31 21:05:32.214274 + +""" +import datetime + +from alembic import op +from app.models import cfg_settings + +# revision identifiers, used by Alembic. +revision = '65e3f200abd3' +down_revision = 'fc0cab9d77dc' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + date_created = datetime.datetime.now().isoformat() + date_modified = datetime.datetime.now().isoformat() + + op.bulk_insert( + cfg_settings.Cfg_settings.__table__, + [ + { + "key": "CATEGORY_PREFIX_MAPPING", + "value": "{ \"Hunt Pivots\": \"HP\", \"Evasion Characteristics\": \"EC\", \"File Characteristics\": \"FC\", \"FileID\": \"FID\", \"Suspicious Characteristics\": \"SC\", \"Malicious Characteristics\": \"MC\", \"Header Analytics\": \"HA\", \"Light House\" : \"LH\", \"Data Loss\": \"DL\", \"Template\": \"UD\", \"Retention\": \"RET\" }", + "public": True, + "date_created": date_created, + "date_modified": date_modified, + "description": "The mapping between categories and their rule prefixes." + } + ] + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + keys = ["CATEGORY_PREFIX_MAPPING"] + for key in keys: + op.execute("""DELETE from cfg_settings where `key`='%s';""" % (key)) + + # ### end Alembic commands ### From b0fb99a45f2f9a4b2a446e06c20d92000e584750 Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Mon, 21 Aug 2023 12:08:46 -0500 Subject: [PATCH 15/19] Updating dependencies --- app/__init__.py | 9 +++++++-- app/models/users.py | 2 +- requirements.txt | 34 +++++++++++++++++----------------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index ae5ff146..dfd9e8db 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -213,7 +213,6 @@ def teardown_request(exception): db.session.remove() -@app.before_first_request def setup_logging(): app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(app.config["LOGGING_LEVEL"]) @@ -314,7 +313,6 @@ def teardown_request(exception): db.session.rollback() db.session.remove() - @app.before_first_request def setup_logging(): app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(app.config["LOGGING_LEVEL"]) @@ -343,6 +341,9 @@ def load_user_from_request(request): return None + with app.app_context(): + setup_logging() + def run(debug=False, port=0, host=''): import os @@ -352,3 +353,7 @@ def run(debug=False, port=0, host=''): generate_app() app.run(debug=debug, port=port, host=host) + + +with app.app_context(): + setup_logging() diff --git a/app/models/users.py b/app/models/users.py index 8b3e6f4e..ddfee348 100755 --- a/app/models/users.py +++ b/app/models/users.py @@ -1,4 +1,4 @@ -from itsdangerous import (JSONWebSignatureSerializer +from itsdangerous import (URLSafeTimedSerializer as Serializer, BadSignature) from app import db diff --git a/requirements.txt b/requirements.txt index 8748b9b6..938a3b85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ aiohttp==3.8.1 aiosignal==1.2.0 -alembic==1.7.7 +alembic==1.9.0 amqp==5.1.1 app==0.0.1 async-timeout==4.0.2 attrs==21.4.0 -Babel==2.10.1 +Babel==2.12 bcrypt==3.2.0 billiard==3.6.4.0 -blinker==1.4 +blinker==1.6.2 celery==5.2.6 certifi==2022.12.7 cffi==1.15.0 chardet==4.0.0 charset-normalizer==2.0.12 -click==8.1.2 +click==8.1.3 click-didyoumean==0.3.0 click-plugins==1.1.1 click-repl==0.2.0 @@ -27,19 +27,19 @@ Deprecated==1.2.13 dnspython==2.0.0 docopt==0.6.2 envoy==0.0.3 -Flask==1.1.2 -Flask-Babel==2.0.0 +Flask==2.3.2 +Flask-Babel==3.1.0 Flask-Bcrypt==1.0.1 -Flask-Caching==1.10.1 -Flask-Login==0.5.0 +Flask-Caching==2.0.2 +Flask-Login==0.6.2 Flask-Mail==0.9.1 -Flask-Migrate==2.6.0 +Flask-Migrate==4.0.4 Flask-OpenID==1.3.0 Flask-Script==2.0.6 -flask-selfdoc==1.3.0 -Flask-SQLAlchemy==2.5.1 +flask-selfdoc==1.4.0 +Flask-SQLAlchemy==3.0.5 Flask-WhooshAlchemy==0.56 -Flask-WTF==1.0.1 +Flask-WTF==1.1.1 flup==1.0.3 frozenlist==1.3.0 geoip2==4.5.0 @@ -50,12 +50,12 @@ importlib-resources==5.7.1 ipaddr==2.2.0 ipaddress==1.0.23 ipwhois==1.2.0 -itsdangerous==1.1.0 -Jinja2==2.11.3 +itsdangerous==2.1.2 +Jinja2==3.1.2 jsonpickle==2.1.0 kombu==5.2.4 Mako==1.2.2 -MarkupSafe==1.1.0 +MarkupSafe==2.1.1 maxminddb==2.2.0 migrate==0.3.8 more-itertools==8.12.0 @@ -78,7 +78,7 @@ python-editor==1.0.4 python-magic==0.4.26 python-openid==2.2.5 python3-openid==3.2.0 -pytz==2022.1 +pytz==2022.7 pyzipcode==3.0.1 redis==4.4.4 requests==2.27.1 @@ -99,7 +99,7 @@ urllib3==1.26.9 uWSGI==2.0.20 vine==5.0.0 wcwidth==0.2.5 -Werkzeug==2.2.3 +Werkzeug==2.3.3 Whoosh==2.7.4 wrapt==1.14.0 WTForms==3.0.1 From 2decd66cac967c74841f0b3483e77acd61e658ad Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Sun, 30 Jul 2023 23:13:40 -0500 Subject: [PATCH 16/19] ZH #8 : Fixing Access Token issue. --- app/routes/access_keys.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/routes/access_keys.py b/app/routes/access_keys.py index bffba142..d6a3ee8d 100644 --- a/app/routes/access_keys.py +++ b/app/routes/access_keys.py @@ -1,3 +1,4 @@ +import codecs import time import datetime import os @@ -76,7 +77,7 @@ def create_access_key(): active_inactive_count = json.loads(get_active_inactive_key_count().data) if active_inactive_count and active_inactive_count['activeInactiveCount'] < 2: - s_key = os.urandom(24).encode('hex') + s_key = codecs.encode(os.urandom(24), 'hex').decode() token = user.generate_auth_token(s_key) key = AccessKeys( From 1823379a0ddfa345f01a7b5155785501fdf275cb Mon Sep 17 00:00:00 2001 From: David Cuellar Date: Sun, 30 Jul 2023 23:00:40 -0500 Subject: [PATCH 17/19] #472 : adding match type to c2dns batch edit --- app/routes/batch.py | 2 ++ app/routes/c2dns.py | 1 + app/static/js/c2dns/c2dns-controller.js | 4 ++++ app/static/views/c2dns/c2dns.html | 11 +++++++++++ 4 files changed, 18 insertions(+) diff --git a/app/routes/batch.py b/app/routes/batch.py index f74b1944..6418af2b 100644 --- a/app/routes/batch.py +++ b/app/routes/batch.py @@ -37,6 +37,8 @@ def batch_update(batch, artifact, session, include_tags=True): fields_to_update = dict() if 'description' in batch and batch['description']: fields_to_update['description'] = batch['description'] + if 'match_type' in batch and batch['match_type']: + fields_to_update['match_type'] = batch['match_type'] if 'expiration_timestamp' in batch and batch['expiration_timestamp'] and hasattr(artifact, 'expiration_timestamp'): fields_to_update['expiration_timestamp'] = batch['expiration_timestamp'] if 'category' in batch and batch['category'] and hasattr(artifact, 'category'): diff --git a/app/routes/c2dns.py b/app/routes/c2dns.py index 20e4081c..e3059cd2 100755 --- a/app/routes/c2dns.py +++ b/app/routes/c2dns.py @@ -234,6 +234,7 @@ def batch_update_c2dns(): """Batch update c2dns artifacts From Data: batch { state (str), + match_type (str), owner_user (str), tags (array), ids (array) diff --git a/app/static/js/c2dns/c2dns-controller.js b/app/static/js/c2dns/c2dns-controller.js index f157c65b..b10be37a 100755 --- a/app/static/js/c2dns/c2dns-controller.js +++ b/app/static/js/c2dns/c2dns-controller.js @@ -420,6 +420,7 @@ angular.module('ThreatKB') var c2dnsToUpdate = { owner_user: $scope.batch.owner, state: $scope.batch.state, + match_type: $scope.batch.match_type, description: $scope.batch.description, expiration_timestamp: $scope.batch.expiration_timestamp, tags: $scope.batch.tags, @@ -505,6 +506,7 @@ angular.module('ThreatKB') $scope.batch = { owner: null, state: null, + match_type: null, description: null, expiration_timestamp: null, tags: null @@ -829,6 +831,8 @@ angular.module('ThreatKB') $scope.cfg_states = Cfg_states.query(); + $scope.match_types = ['exact', 'wildcard']; + $scope.ok = function () { $uibModalInstance.close($scope.batch); }; diff --git a/app/static/views/c2dns/c2dns.html b/app/static/views/c2dns/c2dns.html index b91ebe2b..9b91fe97 100755 --- a/app/static/views/c2dns/c2dns.html +++ b/app/static/views/c2dns/c2dns.html @@ -37,6 +37,17 @@
+
+ + + + + + + {{ match_type }} + + +
From 82e174571e84a3ab4b741c521fe8edbefb51f682 Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:12:49 -0500 Subject: [PATCH 19/19] Moving everything over from deps branch Most of the updates were introduced in other branches, so this is all that's left to be merged from the deps upgrading branch --- app/models/users.py | 3 +- setup.py | 68 +++------------------------------------------ 2 files changed, 5 insertions(+), 66 deletions(-) diff --git a/app/models/users.py b/app/models/users.py index ddfee348..98a1b113 100755 --- a/app/models/users.py +++ b/app/models/users.py @@ -1,5 +1,4 @@ -from itsdangerous import (URLSafeTimedSerializer - as Serializer, BadSignature) +from itsdangerous import (URLSafeTimedSerializer as Serializer, BadSignature) from app import db from app.models import metadata, scripts diff --git a/setup.py b/setup.py index 69293e16..e1d90fd5 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,8 @@ +import os from setuptools import setup, find_packages +requirements = open(os.path.join(os.path.dirname(__file__), "requirements.txt")).read().strip().split('\n') + setup( name='threatkb', version='0.1.1', @@ -17,70 +20,7 @@ py_modules=['config'], packages=find_packages(exclude=['migrations', 'venv', 'contrib', 'docs', 'tests', 'build', 'dist', 'flask']), license='GPL-2.0', - install_requires=[ - 'alembic==1.7.7', - 'amqp==5.1.1', - 'app==0.0.1', - 'Babel==2.10.1', - 'bcrypt==3.2.0', - 'billiard==3.6.4.0', - 'blinker==1.4', - 'celery==5.2.6', - 'certifi==2022.12.7', - 'cffi==1.15.0', - 'chardet==4.0.0', - 'click==8.1.2', - 'decorator==5.1.1', - 'deepdiff==5.8.0', - 'dnspython==2.0.0', - 'Flask==1.1.2', - 'Flask-Autodoc==0.1.2', - 'Flask-Babel==2.0.0', - 'Flask-Bcrypt==1.0.1', - 'Flask-Login==0.5.0', - 'Flask-Mail==0.9.1', - 'Flask-Migrate==2.6.0', - 'Flask-OpenID==1.3.0', - 'Flask-Script==2.0.6', - 'Flask-SQLAlchemy==2.5.1', - 'Flask-WhooshAlchemy==0.56', - 'Flask-WTF==1.0.1', - 'flup==1.0.3', - 'geoip2==4.5.0', - 'idna==3.3', - 'ipaddr==2.2.0', - 'ipaddress==1.0.23', - 'ipwhois==1.2.0', - 'itsdangerous==1.1.0', - 'Jinja2==2.11.3', - 'jsonpickle==2.1.0', - 'kombu==5.2.4', - 'Mako==1.2.2', - 'MarkupSafe==1.1.0', - 'maxminddb==2.2.0', - 'migrate==0.3.8', - 'more-itertools==8.12.0', - 'ply==3.11', - 'pycparser==2.21', - 'python-dateutil==2.8.2', - 'python-editor==1.0.4', - 'python-openid==2.2.5', - 'pytz==2022.1', - 'pyzipcode==3.0.1', - 'redis==4.4.4', - 'requests==2.27.1', - 'six==1.16.0', - 'speaklater==1.3', - 'SQLAlchemy==1.4.36', - 'sqlalchemy-migrate==0.13.0', - 'Tempita==0.5.2', - 'urllib3==1.26.9', - 'vine==5.0.0', - 'Werkzeug==2.2.3', - 'Whoosh==2.7.4', - 'WTForms==3.0.1', - 'yara-python==4.2.0' - ], + install_requires=requirements, extra_require={ 'dev': [], 'test': [],