├── pytests
├── __init__.py
└── test_flask.py
├── log
└── README
├── bulkdownload
└── README
├── static
├── favicon.ico
├── fonts
│ ├── .DS_Store
│ ├── ._webfonts
│ ├── ._.DS_Store
│ ├── Bold
│ │ ├── OpenSans-Bold.woff
│ │ ├── OpenSans-Bold.woff2
│ │ └── SourceCodePro-Bold.ttf
│ ├── Light
│ │ ├── OpenSans-Light.woff
│ │ ├── OpenSans-Light.woff2
│ │ └── SourceCodePro-Light.ttf
│ ├── webfonts
│ │ ├── fa-solid-900.eot
│ │ ├── fa-solid-900.ttf
│ │ ├── ._fa-solid-900.eot
│ │ ├── ._fa-solid-900.svg
│ │ ├── ._fa-solid-900.ttf
│ │ ├── fa-brands-400.eot
│ │ ├── fa-brands-400.ttf
│ │ ├── fa-brands-400.woff
│ │ ├── fa-regular-400.eot
│ │ ├── fa-regular-400.ttf
│ │ ├── fa-solid-900.woff
│ │ ├── fa-solid-900.woff2
│ │ ├── ._fa-brands-400.eot
│ │ ├── ._fa-brands-400.svg
│ │ ├── ._fa-brands-400.ttf
│ │ ├── ._fa-brands-400.woff
│ │ ├── ._fa-brands-400.woff2
│ │ ├── ._fa-regular-400.eot
│ │ ├── ._fa-regular-400.svg
│ │ ├── ._fa-regular-400.ttf
│ │ ├── ._fa-regular-400.woff
│ │ ├── ._fa-solid-900.woff
│ │ ├── ._fa-solid-900.woff2
│ │ ├── fa-brands-400.woff2
│ │ ├── fa-regular-400.woff
│ │ ├── fa-regular-400.woff2
│ │ └── ._fa-regular-400.woff2
│ ├── Italic
│ │ ├── OpenSans-Italic.woff
│ │ └── OpenSans-Italic.woff2
│ ├── Regular
│ │ ├── OpenSans-Regular.woff
│ │ ├── OpenSans-Regular.woff2
│ │ └── SourceCodePro-Regular.ttf
│ ├── Semibold
│ │ ├── OpenSans-Semibold.woff
│ │ ├── OpenSans-Semibold.woff2
│ │ └── SourceCodePro-Semibold.ttf
│ ├── BoldItalic
│ │ ├── OpenSans-BoldItalic.woff
│ │ └── OpenSans-BoldItalic.woff2
│ ├── ExtraBold
│ │ ├── OpenSans-ExtraBold.woff
│ │ └── OpenSans-ExtraBold.woff2
│ ├── LightItalic
│ │ ├── OpenSans-LightItalic.woff
│ │ └── OpenSans-LightItalic.woff2
│ ├── ExtraBoldItalic
│ │ ├── OpenSans-ExtraBoldItalic.woff
│ │ └── OpenSans-ExtraBoldItalic.woff2
│ ├── SemiboldItalic
│ │ ├── OpenSans-SemiboldItalic.woff
│ │ └── OpenSans-SemiboldItalic.woff2
│ └── bootstrap
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
├── vlines
│ ├── node.png
│ ├── vline.png
│ └── lastnode.png
├── fireeye-2-color.png
├── img
│ └── datatables
│ │ ├── sort_asc.png
│ │ ├── sort_both.png
│ │ ├── sort_desc.png
│ │ ├── details_open.png
│ │ ├── details_close.png
│ │ ├── sort_asc_disabled.png
│ │ └── sort_desc_disabled.png
├── fontawesome-free-5.7.2-web
│ ├── ._css
│ ├── .DS_Store
│ ├── ._.DS_Store
│ ├── ._webfonts
│ ├── ._LICENSE.txt
│ ├── css
│ │ ├── ._all.css
│ │ ├── ._brands.css
│ │ ├── ._solid.css
│ │ ├── ._all.min.css
│ │ ├── ._regular.css
│ │ ├── ._solid.min.css
│ │ ├── ._v4-shims.css
│ │ ├── ._brands.min.css
│ │ ├── ._fontawesome.css
│ │ ├── ._regular.min.css
│ │ ├── ._svg-with-js.css
│ │ ├── ._v4-shims.min.css
│ │ ├── ._fontawesome.min.css
│ │ ├── ._svg-with-js.min.css
│ │ ├── brands.min.css
│ │ ├── solid.min.css
│ │ ├── regular.min.css
│ │ ├── brands.css
│ │ ├── solid.css
│ │ ├── regular.css
│ │ └── svg-with-js.min.css
│ ├── webfonts
│ │ ├── fa-brands-400.eot
│ │ ├── fa-brands-400.ttf
│ │ ├── fa-solid-900.eot
│ │ ├── fa-solid-900.ttf
│ │ ├── fa-solid-900.woff
│ │ ├── ._fa-brands-400.eot
│ │ ├── ._fa-brands-400.svg
│ │ ├── ._fa-brands-400.ttf
│ │ ├── ._fa-brands-400.woff
│ │ ├── ._fa-regular-400.eot
│ │ ├── ._fa-regular-400.svg
│ │ ├── ._fa-regular-400.ttf
│ │ ├── ._fa-solid-900.eot
│ │ ├── ._fa-solid-900.svg
│ │ ├── ._fa-solid-900.ttf
│ │ ├── ._fa-solid-900.woff
│ │ ├── ._fa-solid-900.woff2
│ │ ├── fa-brands-400.woff
│ │ ├── fa-brands-400.woff2
│ │ ├── fa-regular-400.eot
│ │ ├── fa-regular-400.ttf
│ │ ├── fa-regular-400.woff
│ │ ├── fa-regular-400.woff2
│ │ ├── fa-solid-900.woff2
│ │ ├── ._fa-brands-400.woff2
│ │ ├── ._fa-regular-400.woff
│ │ └── ._fa-regular-400.woff2
│ └── LICENSE.txt
├── css
│ ├── colReorder.dataTables.min.css
│ ├── scroller.dataTables.min.css
│ └── buttons.jqueryui.min.css
├── hxtool-css
│ ├── hxtool-chartjs.css
│ ├── hxtool-login.css
│ ├── hxtool-typography.css
│ ├── hxtool-top-nav.css
│ ├── hxtool-panel.css
│ ├── hxtool-rtioc.css
│ ├── hxtool-datatables.css
│ ├── hxtool-scriptbuilder.css
│ ├── hxtool-grid.css
│ ├── hxtool-host.css
│ └── hxtool-table.css
├── progress.js
├── ico
│ ├── windows.svg
│ └── apple.svg
├── js
│ ├── buttons.jqueryui.min.js
│ └── buttons.print.min.js
├── ChartJS
│ └── LICENSE.md
├── alert_types.json
├── hxtool-js
│ ├── hxtool-widgets.js
│ ├── hxtool-generic.js
│ └── hxtool-doc-ready.js
├── multi-select.css
├── spinner.svg
└── fireeye.svg
├── requirements.txt
├── scripts
├── ports.json
├── processes-api.json
├── w32drivers-modulelist.xml
├── files_listing_template.json
├── services-md5.xml
├── w32mbr.xml
├── w32tasks.xml
├── w32drivers-signature.xml
└── w32processes-memory.xml
├── .dockerignore
├── hxtool_db.py
├── hxtool_vars.py
├── docker-entrypoint.sh
├── README.DOCKER
├── hxtool_global.py
├── templates
├── ht_noaccess.html
├── widget-radio.html
├── widget-input.html
├── widget-textarea.html
├── widget-panel-noheader.html
├── widget-panel.html
├── ht_settings.html
├── widget-modal.html
├── widget-dropdown.html
├── ht_sysinfo.html
├── voltron_data.html
├── ht_hostsearch.html
├── widget-schedule.html
├── ht_search_dd.html
├── ht_auditmanager.html
├── ht_stacking_analyze.html
├── ht_scheduler.html
└── ht_categories.html
├── Dockerfile
├── gunicorn_container.py
├── hxtool_task_modules
├── __init__.py
├── task_api_session_module.py
├── file_listing_task_module.py
├── mongodb_ingest_task_module.py
├── task_module.py
├── file_acquisition_task_module.py
├── enterprise_search_task_module.py
├── stacking_task_module.py
├── file_write_task_module.py
├── streaming_task_module.py
├── helix_task_module.py
└── x15_postgres_task_module.py
├── hxtool_logging.py
├── data
├── conf.json
├── hxtool.crt
└── hxtool.key
├── hxtool_x15_db.py
├── tests
└── test_scheduler.py
├── tools
└── xagentinput_parser.py
├── LICENSE
├── README.md
├── hxtool_config.py
├── hxtool_session.py
└── README.CONFIG
/pytests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/log/README:
--------------------------------------------------------------------------------
1 | THIS IS WHERE HXTool logs end up
2 |
--------------------------------------------------------------------------------
/bulkdownload/README:
--------------------------------------------------------------------------------
1 | This directory holds your downloaded bulk acquisitions
2 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/favicon.ico
--------------------------------------------------------------------------------
/static/fonts/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/.DS_Store
--------------------------------------------------------------------------------
/static/fonts/._webfonts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/._webfonts
--------------------------------------------------------------------------------
/static/vlines/node.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/vlines/node.png
--------------------------------------------------------------------------------
/static/vlines/vline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/vlines/vline.png
--------------------------------------------------------------------------------
/static/fonts/._.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/._.DS_Store
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | flask>=2.0.0
2 | requests
3 | pycryptodomex
4 | tinydb>=3.15.2
5 | pandas
6 | keyring
7 |
--------------------------------------------------------------------------------
/static/fireeye-2-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fireeye-2-color.png
--------------------------------------------------------------------------------
/static/vlines/lastnode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/vlines/lastnode.png
--------------------------------------------------------------------------------
/scripts/ports.json:
--------------------------------------------------------------------------------
1 | {
2 | "commands": [
3 | {
4 | "name": "ports"
5 | }
6 | ]
7 | }
--------------------------------------------------------------------------------
/static/img/datatables/sort_asc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/sort_asc.png
--------------------------------------------------------------------------------
/static/img/datatables/sort_both.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/sort_both.png
--------------------------------------------------------------------------------
/static/img/datatables/sort_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/sort_desc.png
--------------------------------------------------------------------------------
/static/fonts/Bold/OpenSans-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Bold/OpenSans-Bold.woff
--------------------------------------------------------------------------------
/static/fonts/Bold/OpenSans-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Bold/OpenSans-Bold.woff2
--------------------------------------------------------------------------------
/static/fonts/Light/OpenSans-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Light/OpenSans-Light.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/static/img/datatables/details_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/details_open.png
--------------------------------------------------------------------------------
/scripts/processes-api.json:
--------------------------------------------------------------------------------
1 | {
2 | "commands": [
3 | {
4 | "name": "processes-api"
5 | }
6 | ]
7 | }
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/._css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/._css
--------------------------------------------------------------------------------
/static/fonts/Bold/SourceCodePro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Bold/SourceCodePro-Bold.ttf
--------------------------------------------------------------------------------
/static/fonts/Italic/OpenSans-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Italic/OpenSans-Italic.woff
--------------------------------------------------------------------------------
/static/fonts/Light/OpenSans-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Light/OpenSans-Light.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-solid-900.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-solid-900.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-solid-900.svg
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-solid-900.ttf
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/static/img/datatables/details_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/details_close.png
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.git
2 | **/__pycache__
3 | **/*.pyc
4 | *.db
5 | log/*
6 | !log/README
7 | bulkdownload/*
8 | !bulkdownload/README
9 |
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/.DS_Store
--------------------------------------------------------------------------------
/static/fonts/Italic/OpenSans-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Italic/OpenSans-Italic.woff2
--------------------------------------------------------------------------------
/static/fonts/Light/SourceCodePro-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Light/SourceCodePro-Light.ttf
--------------------------------------------------------------------------------
/static/fonts/Regular/OpenSans-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Regular/OpenSans-Regular.woff
--------------------------------------------------------------------------------
/static/fonts/Regular/OpenSans-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Regular/OpenSans-Regular.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-brands-400.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-brands-400.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-brands-400.svg
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-brands-400.ttf
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-brands-400.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-brands-400.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-regular-400.eot
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-regular-400.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-regular-400.svg
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-regular-400.ttf
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-regular-400.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-solid-900.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-solid-900.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/static/fonts/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/static/img/datatables/sort_asc_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/sort_asc_disabled.png
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/._.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/._.DS_Store
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/._webfonts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/._webfonts
--------------------------------------------------------------------------------
/static/fonts/Semibold/OpenSans-Semibold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Semibold/OpenSans-Semibold.woff
--------------------------------------------------------------------------------
/static/fonts/Semibold/OpenSans-Semibold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Semibold/OpenSans-Semibold.woff2
--------------------------------------------------------------------------------
/static/fonts/webfonts/._fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/webfonts/._fa-regular-400.woff2
--------------------------------------------------------------------------------
/static/img/datatables/sort_desc_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/img/datatables/sort_desc_disabled.png
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/._LICENSE.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/._LICENSE.txt
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._all.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._all.css
--------------------------------------------------------------------------------
/static/fonts/BoldItalic/OpenSans-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/BoldItalic/OpenSans-BoldItalic.woff
--------------------------------------------------------------------------------
/static/fonts/ExtraBold/OpenSans-ExtraBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/ExtraBold/OpenSans-ExtraBold.woff
--------------------------------------------------------------------------------
/static/fonts/ExtraBold/OpenSans-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/ExtraBold/OpenSans-ExtraBold.woff2
--------------------------------------------------------------------------------
/static/fonts/Regular/SourceCodePro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Regular/SourceCodePro-Regular.ttf
--------------------------------------------------------------------------------
/static/fonts/Semibold/SourceCodePro-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/Semibold/SourceCodePro-Semibold.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._brands.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._brands.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._solid.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._solid.css
--------------------------------------------------------------------------------
/static/fonts/BoldItalic/OpenSans-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/BoldItalic/OpenSans-BoldItalic.woff2
--------------------------------------------------------------------------------
/static/fonts/LightItalic/OpenSans-LightItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/LightItalic/OpenSans-LightItalic.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._all.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._all.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._regular.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._regular.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._solid.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._solid.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._v4-shims.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._v4-shims.css
--------------------------------------------------------------------------------
/static/fonts/LightItalic/OpenSans-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/LightItalic/OpenSans-LightItalic.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._brands.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._brands.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._fontawesome.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._fontawesome.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._regular.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._regular.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._svg-with-js.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._svg-with-js.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._v4-shims.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._v4-shims.min.css
--------------------------------------------------------------------------------
/static/fonts/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff
--------------------------------------------------------------------------------
/static/fonts/SemiboldItalic/OpenSans-SemiboldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/SemiboldItalic/OpenSans-SemiboldItalic.woff
--------------------------------------------------------------------------------
/static/fonts/SemiboldItalic/OpenSans-SemiboldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/SemiboldItalic/OpenSans-SemiboldItalic.woff2
--------------------------------------------------------------------------------
/static/fonts/bootstrap/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/bootstrap/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/static/fonts/bootstrap/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/bootstrap/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._fontawesome.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._fontawesome.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/._svg-with-js.min.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/css/._svg-with-js.min.css
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/static/fonts/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fonts/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.svg
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.svg
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.svg
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-solid-900.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-brands-400.woff2
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.woff
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireeye/HXTool/master/static/fontawesome-free-5.7.2-web/webfonts/._fa-regular-400.woff2
--------------------------------------------------------------------------------
/static/css/colReorder.dataTables.min.css:
--------------------------------------------------------------------------------
1 | table.DTCR_clonedTable.dataTable{position:absolute !important;background-color:rgba(255,255,255,0.7);z-index:202}div.DTCR_pointer{width:1px;background-color:#0259C4;z-index:201}
2 |
--------------------------------------------------------------------------------
/hxtool_db.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | class hxtool_db:
5 | def __init__(self):
6 | pass
7 |
8 | @property
9 | def database_engine(self):
10 | raise NotImplementedError("You must override this in your database class.")
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-chartjs.css:
--------------------------------------------------------------------------------
1 | .hxtool_chartjs_canvas {
2 | padding: 24px;
3 | padding-bottom: 6px;
4 | padding-top: 6px;
5 | }
6 |
7 | .hxtool_chartjs_host_canvas {
8 | padding: 12px;
9 | padding-bottom: 6px;
10 | padding-top: 6px;
11 | height: 90px;
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/hxtool_vars.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Global variables
5 |
6 | default_encoding = 'utf-8'
7 | HXTOOL_API_VERSION = 1
8 | __version__ = "4.8-pre"
9 | hxtool_schema_version = 40
10 | data_path = "data"
11 | log_path = "log"
12 |
13 | global app_instance_path
14 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-login.css:
--------------------------------------------------------------------------------
1 | .hxtool_login_main {
2 | position: absolute;
3 | left: 50%;
4 | top: 20%;
5 | margin-left: -250px;
6 | }
7 |
8 | .hxtool_login_profile {
9 | list-style-type: none;
10 | }
11 |
12 | .hxtool_login_profile li {
13 | font-size: 14px;
14 | margin-bottom: 12px;
15 | }
--------------------------------------------------------------------------------
/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | PASSWORD_FILE=/opt/hxtool/data/.keyring_password
3 | if [ ! -f "$PASSWORD_FILE" ]; then
4 | dd if=/dev/urandom of=$PASSWORD_FILE bs=1 count=32
5 | fi
6 | /usr/bin/dbus-run-session -- bash -r << EOF
7 | cat $PASSWORD_FILE | gnome-keyring-daemon --unlock
8 | python3 hxtool.py
9 | EOF
10 |
--------------------------------------------------------------------------------
/README.DOCKER:
--------------------------------------------------------------------------------
1 | To build a Docker image from the HXTool source, execute the following:
2 | docker build --pull -t hxtool:latest .
3 |
4 | To run HXTool once the image build process is complete, execute the following:
5 | docker run -p 8080:8080/tcp -d --cap-add=IPC_LOCK --name hxtool hxtool:latest
6 |
7 | IPC_LOCK is needed for the GNOME keyring daemon
--------------------------------------------------------------------------------
/hxtool_global.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # The sole purpose of this module is to store global variables and functions
5 |
6 | def initialize():
7 | global apicache
8 | apicache = {}
9 |
10 | global hxtool_db
11 | global hxtool_config
12 | global hxtool_scheduler
13 | global hxtool_x15_object
14 | global hx_alert_types
15 |
--------------------------------------------------------------------------------
/static/css/scroller.dataTables.min.css:
--------------------------------------------------------------------------------
1 | div.DTS{display:block !important}div.DTS tbody th,div.DTS tbody td{white-space:nowrap}div.DTS div.DTS_Loading{z-index:1}div.DTS div.dataTables_scrollBody{background:repeating-linear-gradient(45deg, #edeeff, #edeeff 10px, #fff 10px, #fff 20px)}div.DTS div.dataTables_scrollBody table{z-index:2}div.DTS div.dataTables_paginate,div.DTS div.dataTables_length{display:none}
2 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-typography.css:
--------------------------------------------------------------------------------
1 | .hxtool_typography_h3 {
2 | margin-bottom: 8px;
3 | margin-top: 8px;
4 | }
5 |
6 | .hxtool_typography_h4 {
7 | margin-bottom: 8px;
8 | margin-top: 8px;
9 | }
10 |
11 | .hxtool_typography_h5 {
12 | margin-bottom: 8px;
13 | margin-top: 8px;
14 | }
15 |
16 | .hxtool_typography_underline {
17 | border-bottom: 0.5px solid rgba(15, 184, 220, 0.3);
18 | padding-bottom: 2px;
19 | }
--------------------------------------------------------------------------------
/templates/ht_noaccess.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Access denied{% endblock %}
3 | {% block navlocation %}Access denied{% endblock %}
4 | {% block content %}
5 |
6 | {{ htPanel.widgetHeader("HXTool message", panelIcon="fa-ban") }}
7 | Access to this feature is denied. Check your account role in the FireEye HX appliance some features requires "API Administrator" access.
8 | {{ htPanel.widgetFooter() }}
9 |
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/brands.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/solid.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900}
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/regular.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400}
--------------------------------------------------------------------------------
/static/progress.js:
--------------------------------------------------------------------------------
1 | (function ( $ ) {
2 | $.fn.progress = function() {
3 | var percent = this.data("percent");
4 | this.html("
"+percent+"%
");
5 | this.find("div").animate({ width: percent+"%" });
6 | };
7 | }( jQuery ));
8 |
9 | (function ( $ ) {
10 | $.fn.progressNoAnimate = function() {
11 | var percent = this.data("percent");
12 | this.html(""+percent+"%
");
13 | };
14 | }( jQuery ));
15 |
--------------------------------------------------------------------------------
/templates/widget-radio.html:
--------------------------------------------------------------------------------
1 | {% macro widgetHeader(elementTitle, elementValue, elementId, elementName, elementChecked="false") -%}
2 |
3 |
4 |
5 |
6 | {{elementTitle}}
7 |
8 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/widget-input.html:
--------------------------------------------------------------------------------
1 | {% macro widget(elementPlaceholder, elementTitle="", elementHint="", elementId="", elementWidth="") -%}
2 | {% if elementTitle != "" %}
3 |
4 | {% endif %}
5 |
6 | {% if elementHint != "" %}
7 | {{elementHint}}
8 | {% endif %}
9 | {% endmacro %}
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6-slim
2 | LABEL maintainer="Elazar Broad "
3 | WORKDIR /opt/hxtool
4 | # TODO: should be converted to a script
5 | COPY requirements.txt ./
6 | RUN apt-get update && apt-get install -y dbus gnome-keyring \
7 | && pip install --no-cache-dir pymongo psycopg2-binary pydbus \
8 | && pip install --no-cache-dir -r requirements.txt \
9 | && rm -rf /root/.cache
10 | COPY . /opt/hxtool
11 | VOLUME /opt/hxtool/data /opt/hxtool/bulkdownload /opt/hxtool/log
12 | EXPOSE 8080/tcp
13 | ENTRYPOINT ["/bin/sh", "docker-entrypoint.sh"]
14 |
--------------------------------------------------------------------------------
/templates/widget-textarea.html:
--------------------------------------------------------------------------------
1 | {% macro widget(elementPlaceholder, elementTitle="", elementHint="", elementId="", elementWidth="") -%}
2 | {% if elementTitle != "" %}
3 |
4 | {% endif %}
5 |
6 | {% if elementHint != "" %}
7 | {{elementHint}}
8 | {% endif %}
9 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/widget-panel-noheader.html:
--------------------------------------------------------------------------------
1 | {% macro widgetHeader(panelId="", panelDisplay="block", panelWidth="", elementAdditionalClass="", elementAdditionalBodyClass="") -%}
2 |
3 |
4 | {% endmacro %}
5 |
6 | {% macro widgetFooter() -%}
7 |
8 |
9 | {% endmacro %}
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/brands.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Font Awesome 5 Brands';
3 | font-style: normal;
4 | font-weight: normal;
5 | font-display: auto;
6 | src: url("../webfonts/fa-brands-400.eot");
7 | src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); }
8 |
9 | .fab {
10 | font-family: 'Font Awesome 5 Brands'; }
11 |
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/solid.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Font Awesome 5 Free';
3 | font-style: normal;
4 | font-weight: 900;
5 | font-display: auto;
6 | src: url("../webfonts/fa-solid-900.eot");
7 | src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); }
8 |
9 | .fa,
10 | .fas {
11 | font-family: 'Font Awesome 5 Free';
12 | font-weight: 900; }
13 |
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/regular.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Font Awesome 5 Free';
3 | font-style: normal;
4 | font-weight: 400;
5 | font-display: auto;
6 | src: url("../webfonts/fa-regular-400.eot");
7 | src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); }
8 |
9 | .far {
10 | font-family: 'Font Awesome 5 Free';
11 | font-weight: 400; }
12 |
--------------------------------------------------------------------------------
/gunicorn_container.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from gunicorn.app.base import Application
5 |
6 | class GunicornContainerApplication(Application):
7 | def __init__(self, app, options = {}):
8 | self.application = app
9 | self.options = options
10 | super(GunicornContainerApplication, self).__init__()
11 |
12 | def load_config(self):
13 | config = dict([(key, value) for key, value in self.options.items()
14 | if key in self.cfg.settings and value is not None])
15 | for key, value in config.items():
16 | self.cfg.set(key.lower(), value)
17 |
18 | def load(self):
19 | return self.application
20 |
--------------------------------------------------------------------------------
/hxtool_task_modules/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Base module
5 | from .task_module import *
6 |
7 | # HXTool packages modules here
8 | from .task_api_session_module import *
9 | from .bulk_acquisition_task_module import *
10 | from .bulk_download_monitor_task_module import *
11 | from .bulk_download_task_module import *
12 | from .enterprise_search_task_module import *
13 | from .stacking_task_module import *
14 | from .file_listing_task_module import *
15 | from .file_acquisition_task_module import *
16 | from .streaming_task_module import *
17 | from .file_write_task_module import *
18 | from .helix_task_module import *
19 | from .x15_postgres_task_module import *
20 | from .mongodb_ingest_task_module import *
21 |
22 | # Customer modules here
23 |
--------------------------------------------------------------------------------
/static/ico/windows.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
12 |
13 |
--------------------------------------------------------------------------------
/templates/widget-panel.html:
--------------------------------------------------------------------------------
1 | {% macro widgetHeader(panelTitle, panelId="", panelDisplay="block", panelWidth="", elementAdditionalClass="", elementAdditionalBodyClass="", panelIcon="") -%}
2 |
3 |
6 |
7 | {% endmacro %}
8 |
9 | {% macro widgetFooter() -%}
10 |
11 |
12 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/ht_settings.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Settings{% endblock %}
3 | {% block navlocation %}Settings{% endblock %}
4 | {% block content %}
5 |
6 |
17 |
18 | {{ htPanel.widgetHeader("Background processing", panelIcon="fa-table") }}
19 | Enter HX API credentials to use for background processing. This feature is used to post-process acquisitions as they come in (when you are not logged into HXTool). PLEASE NOTE: These credentials are stored in the database encrypted with a static key.
20 | {% if bgcreds %} {{ bgcreds|safe }} {% endif %}
21 |
22 | {{ htPanel.widgetFooter() }}
23 |
24 | {% endblock %}
25 |
--------------------------------------------------------------------------------
/hxtool_logging.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import threading
5 | import logging
6 | from multiprocessing import Queue, RLock
7 |
8 |
9 | root_logger_name = "hxtool"
10 |
11 | def setLoggerClass():
12 | logging.setLoggerClass(hxtool_logger)
13 |
14 | def getLoggerName(name):
15 | return "{}.{}".format(root_logger_name, name)
16 |
17 | def getLogger(name = None):
18 | _name = root_logger_name
19 | if name is not None:
20 | _name = getLoggerName(name)
21 |
22 | return logging.getLogger(_name)
23 |
24 | class hxtool_logger(logging.Logger):
25 | def __init__(self, name, level=logging.NOTSET):
26 | super(hxtool_logger, self).__init__(name, level=level)
27 |
28 | def callHandlers(self, record):
29 | with RLock():
30 | _thread = threading.Thread(target=super(hxtool_logger, self).callHandlers(record))
31 | _thread.start()
32 | _thread.join()
33 |
34 |
--------------------------------------------------------------------------------
/templates/widget-modal.html:
--------------------------------------------------------------------------------
1 | {% macro widgetHeader(modalTitle, modalId="", modalSize="medium", modalOverflow="false") -%}
2 |
3 |
4 |
5 |
6 |
12 |
13 |
14 | {% endmacro %}
15 |
16 | {% macro widgetMiddle() -%}
17 |
18 |
23 |
24 |
25 |
26 | {% endmacro %}
--------------------------------------------------------------------------------
/static/js/buttons.jqueryui.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | jQuery UI integration for DataTables' Buttons
3 | ©2016 SpryMedia Ltd - datatables.net/license
4 | */
5 | (function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-jqui","datatables.net-buttons"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-jqui")(a,b).$;b.fn.dataTable.Buttons||require("datatables.net-buttons")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){var a=c.fn.dataTable;c.extend(!0,a.Buttons.defaults,{dom:{container:{className:"dt-buttons ui-buttonset"},
6 | button:{className:"dt-button ui-button ui-state-default ui-button-text-only",disabled:"ui-state-disabled",active:"ui-state-active"},buttonLiner:{tag:"span",className:"ui-button-text"}}});a.ext.buttons.collection.text=function(a){return a.i18n("buttons.collection",'Collection ')};return a.Buttons});
7 |
--------------------------------------------------------------------------------
/static/ChartJS/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Chart.js Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/scripts/w32drivers-modulelist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application/vnd.mandiant.host+xml
5 |
6 |
7 | application/vnd.mandiant.auditresult+xml
8 |
9 |
25 |
--------------------------------------------------------------------------------
/scripts/files_listing_template.json:
--------------------------------------------------------------------------------
1 | {
2 | "commands": [{
3 | "name": "files-api",
4 | "parameters": [{
5 | "name": "Prevent Hibernation",
6 | "value": true
7 | }, {
8 | "name": "Depth",
9 | "value": -1
10 | }, {
11 | "name": "MD5",
12 | "value": true
13 | }, {
14 | "name": "SHA1",
15 | "value": false
16 | }, {
17 | "name": "SHA256",
18 | "value": true
19 | },{
20 | "name": "Strings",
21 | "value": false
22 | }, {
23 | "name": "AND Operator",
24 | "value": false
25 | }, {
26 | "name": "Include Files",
27 | "value": true
28 | }, {
29 | "name": "Include Directories",
30 | "value": true
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/static/alert_types.json:
--------------------------------------------------------------------------------
1 | {
2 | "IOC": {
3 | "label": "Realtime IOC Detection",
4 | "threat_key": "indicator.display_name"
5 | },
6 | "EXD": {
7 | "label": "Exploit Guard",
8 | "threat_key": "event_values.process_name"
9 | },
10 | "MAL": {
11 | "label": "Malware Protection",
12 | "threat_key": "event_values.detections.detection.#0.infection.infection-name"
13 | },
14 | "PROCESS_TRACKER": {
15 | "label": "Process Tracker",
16 | "threat_key": "event_values.#0.name"
17 | },
18 | "PROCGUARD": {
19 | "label": "Process Guard",
20 | "threat_key": "event_values.#0.name"
21 | },
22 | "LTALERT": {
23 | "label": "Logon Tracker",
24 | "threat_key": "event_values.#0.name"
25 | },
26 | "UACPROTECT": {
27 | "label": "UAC Protect",
28 | "threat_key": "event_values.#0.name"
29 | },
30 | "AMSI": {
31 | "label": "AMSI",
32 | "threat_key": "event_values.#0.name"
33 | },
34 | "TP": {
35 | "label": "Tamper Protection",
36 | "threat_key": "event_values.#0.name"
37 | },
38 | "DL": {
39 | "label": "Deny List",
40 | "threat_key": "event_values.#0.name"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-top-nav.css:
--------------------------------------------------------------------------------
1 | /* HXTool Top Navigation bar */
2 |
3 | .hxtool_topnav_dropdown {
4 | background: rgba(0, 0, 0, 0.6) !important;
5 | position: absolute;
6 | box-shadow: 0 0.5px 5px 0 rgba(0, 0, 0, 0.25);
7 | display: none;
8 | z-index: 50 !important;
9 | }
10 |
11 | .hxtool_topnav_dropdown_child {
12 | width: 100%;
13 | color: #0fb8dc;
14 | text-align: left;
15 | background: transparent;
16 | border: 0;
17 | }
18 |
19 | .hxtool_topnav_dropdown_child:hover {
20 | background: rgba(0, 0, 0, 0.6);
21 | color: #66ebff !important;
22 | }
23 |
24 | .hxtool_topnav_left_container-left {
25 | position: absolute;
26 | display: none;
27 | margin-left: 24px;
28 | }
29 |
30 | .hxtool_topnav_right_container-right {
31 | float: right;
32 | text-align: right;
33 | }
34 |
35 | .hxtool_topnav_dropdown_divider {
36 | width: 100%;
37 | margin-right: 0px;
38 | border-top: 1px solid;
39 | height: 16px;
40 | padding-bottom: 0px;
41 | padding-left: 8px;
42 | font-size: 10px;
43 | color: #b3cacf;
44 | }
45 |
46 | .hxtool_topnav_mainbutton {
47 | background: transparent;
48 | color: #0fb8dc;
49 | border: 0;
50 | }
51 |
52 | button.hxtool_topnav_mainbutton:hover {
53 | background: rgba(0, 0, 0, 0.6);
54 | color: #66ebff !important;
55 | }
--------------------------------------------------------------------------------
/static/ico/apple.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/data/conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "log_handlers": {
3 | "rotating_file_handler": {
4 | "file": "log/hxtool.log",
5 | "max_bytes": 5000000,
6 | "backup_count": 5,
7 | "level": "info",
8 | "format": "[%(asctime)s] {%(module)s} {%(threadName)s} %(levelname)s - %(message)s"
9 | }
10 | },
11 | "network": {
12 | "ssl": "enabled",
13 | "port": 8080,
14 | "listen_address": "0.0.0.0",
15 | "session_timeout": 30
16 | },
17 | "ssl": {
18 | "cert": "hxtool.crt",
19 | "key": "hxtool.key"
20 | },
21 | "scheduler": {
22 | "thread_count" : null,
23 | "defer_interval" : 30
24 | },
25 | "apicache": {
26 | "enabled": false,
27 | "types": ["host", "alert", "triage", "file", "live"],
28 | "intervals": {
29 | "host": {
30 | "fetcher_interval": 60,
31 | "objects_per_poll": 3,
32 | "refresh_interval": 60
33 | },
34 | "alert": {
35 | "fetcher_interval": 15,
36 | "objects_per_poll": 300,
37 | "refresh_interval": 15
38 | },
39 | "triage": {
40 | "fetcher_interval": 10,
41 | "objects_per_poll": 10,
42 | "refresh_interval": 30
43 | },
44 | "file": {
45 | "fetcher_interval": 10,
46 | "objects_per_poll": 5,
47 | "refresh_interval": 25
48 | },
49 | "live": {
50 | "fetcher_interval": 10,
51 | "objects_per_poll": 50,
52 | "refresh_interval": 35
53 | }
54 | }
55 | },
56 | "headers": {},
57 | "cookies": {}
58 | }
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-panel.css:
--------------------------------------------------------------------------------
1 | .hxtool_panel_wrapper {
2 | margin-bottom: 24px;
3 | margin-top: 16px;
4 | margin-left: 12px;
5 | }
6 |
7 | .hxtool-panel-toggle {
8 | outline: 0;
9 | }
10 |
11 | .hxtool_panel_float {
12 | position: fixed;
13 | display: none;
14 | left: 50%;
15 | top: 50%;
16 | transform: translate(-50%, -50%);
17 | z-index: 5;
18 | }
19 |
20 | .hxtool_panel_body_popup {
21 | padding: 24px;
22 | }
23 |
24 | .hxtool_panel_dashboard {
25 | height: 100%;
26 | display: flex;
27 | flex-direction: column;
28 | position: relative;
29 | }
30 |
31 | .hxtool_panel_dashboard_child {
32 | flex: 1;
33 | }
34 |
35 | .hxtool_panel_top_right {
36 | position: absolute;
37 | right: 0;
38 | padding-left: 6px;
39 | margin-top: 4px;
40 | }
41 |
42 | .hxtool_panel_top_right_alert {
43 | position: absolute;
44 | right: 12px;
45 | padding-left: 6px;
46 | margin-top: -32px;
47 | }
48 |
49 | .hxtool_panel_scriptbuilder {
50 | width: 1536px;
51 | height: calc(100vh - 190px);
52 | overflow-y: visible;
53 | }
54 |
55 | .hxtool_panel_stackinganalyze {
56 | max-height: calc(100vh - 190px);
57 | overflow-y: auto;
58 | }
59 |
60 | .hxtool_panel_multi_flist {
61 | max-height: calc(50vh - 125px);
62 | overflow-y: auto;
63 | }
64 |
65 | .hxtool_panel_multi_macq {
66 | max-height: calc(50vh - 125px);
67 | overflow-y: auto;
68 | }
69 |
70 | .hxtool_panel_dashboard_lastalerts {
71 | overflow-y: auto;
72 | }
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-rtioc.css:
--------------------------------------------------------------------------------
1 | .hxtool_rtioc_table_header_condition {
2 | text-align: left !important;
3 | border-right: none !important;
4 | border-left: none;
5 | font-weight: bold;
6 | font-size: 14px;
7 | background: rgba(0,0,0,0.2);
8 | padding-top: 12px !important;
9 | padding-bottom: 12px !important;
10 | vertical-align: middle;
11 | }
12 |
13 | .hxtool_rtioc_table_header_condition_right {
14 | text-align: center !important;
15 | border-right: none;
16 | border-left: none;
17 | background: rgba(0,0,0,0.2);
18 | padding-top: 12px;
19 | }
20 |
21 | .hxtool_rtioc_input {
22 | padding: 3px;
23 | }
24 |
25 | .hxtool_rtioc_table tbody tr:nth-child(odd) {
26 | background: transparent !important;
27 | }
28 |
29 |
30 | .hxtool_rtioc_table tbody td:nth-child(1) {
31 | text-align: center;
32 | width: 230px;
33 | }
34 |
35 | .hxtool_rtioc_table tbody td:nth-child(2) {
36 | text-align: center;
37 | width: 200px;
38 | }
39 |
40 | .hxtool_rtioc_table tbody td:nth-child(3) {
41 | text-align: center;
42 | width: 130px;
43 | }
44 |
45 | .hxtool_rtioc_table tbody td:nth-child(4) {
46 | text-align: center;
47 | width: 100px;
48 | }
49 |
50 | .hxtool_rtioc_table tbody td:nth-child(5) {
51 | text-align: center;
52 | width: 100px;
53 | }
54 |
55 | .hxtool_rtioc_table tbody td:nth-child(7) {
56 | text-align: center;
57 | width: 40px;
58 | }
59 |
60 | .hxtool_rtioc_table tbody td:nth-child(8) {
61 | text-align: center;
62 | width: 100px;
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/hxtool_x15_db.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | try:
5 | import psycopg2
6 | import psycopg2.extras
7 | except ImportError:
8 | print("HXTool with X15 integration requires the psycopg2 library please install it")
9 | exit(1)
10 |
11 | import hxtool_global
12 |
13 | class hxtool_x15:
14 | def __init__(self, x15conf = hxtool_global.hxtool_config['x15']):
15 |
16 | connect_string = "host={} dbname={} user={} port={} password={}".format(x15conf['host'], x15conf['db'], x15conf['user'], x15conf['port'], x15conf['password'])
17 | self.conn = psycopg2.connect(connect_string)
18 | self.cur = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
19 |
20 | def getAudits(self):
21 | self.cur.execute("SELECT bulk_acquisition_id, min(timestamps[1]['time']) as starttime, max(timestamps[1]['time']) as stoptime, count(*) as events FROM eventdata GROUP BY bulk_acquisition_id")
22 | return(self.cur.fetchall())
23 |
24 | def getAuditModules(self, bulk_list):
25 | self.cur.execute("SELECT generator, count(*) as events FROM eventdata WHERE bulk_acquisition_id IN %s GROUP BY generator", (tuple(bulk_list),))
26 | return(self.cur.fetchall())
27 |
28 | def getAuditData(self, generators, bulk_list):
29 | self.cur.execute("SELECT eventitem::string as eventitem FROM eventdata WHERE bulk_acquisition_id IN %(bulkids)s AND generator IN %(generators)s LIMIT 1", {"bulkids": tuple(bulk_list), "generators": tuple(generators)})
30 | return(self.cur.fetchall())
31 |
--------------------------------------------------------------------------------
/tests/test_scheduler.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import sys
5 | import random
6 | from time import sleep
7 | import logging
8 |
9 | sys.path.append('../')
10 |
11 | from hxtool_scheduler import *
12 | from hxtool_scheduler_task import hxtool_scheduler_task
13 | import hxtool_global
14 |
15 | class test_scheduler:
16 |
17 | def __init__(self):
18 | self.ht_scheduler = hxtool_scheduler()
19 | self.ht_scheduler.logger.addHandler(logging.StreamHandler(sys.stdout))
20 | self.ht_scheduler.logger.setLevel(logging.DEBUG)
21 |
22 | hxtool_global.hxtool_scheduler = self.ht_scheduler
23 |
24 | def run_test(self):
25 | print("Testing hxtool_scheduler...")
26 | self.ht_scheduler.start()
27 | for i in range(1, 500):
28 | ht_task = hxtool_scheduler_task('System', 'Test Task {}'.format(i), immutable = True, logger = self.ht_scheduler.logger)
29 | r = random.randint(1, 100)
30 | if r > 50:
31 | ht_task.set_schedule(minutes = random.randint(1, 5))
32 | ht_task.add_step(self, "test_scheduler_function", args = (random.randint(1, 60),))
33 | self.ht_scheduler.add(ht_task, should_store = False)
34 | ht_task = None
35 |
36 | try:
37 | while True:
38 | sleep(.1)
39 | except (KeyboardInterrupt, SystemExit):
40 | self.ht_scheduler.stop()
41 |
42 | def test_scheduler_function(self, n):
43 | print("Random number is: {}".format(n * random.randint(0, 500)))
44 | return True
45 |
46 | t = test_scheduler()
47 | t.run_test()
--------------------------------------------------------------------------------
/scripts/services-md5.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tools/xagentinput_parser.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | myjson = {}
4 |
5 | with open('../../xagtinput.json') as f:
6 | data = json.load(f)
7 |
8 | for key in ['modules-audits', 'modules-acquisitions']:
9 | for module in data[key]:
10 |
11 | for mymodule, val in module.items():
12 |
13 | myjson[val['module name']] = {}
14 | myjson[val['module name']]['description'] = val['usage']
15 | myjson[val['module name']]['platforms'] = val['platform']
16 | myjson[val['module name']]['parameters'] = []
17 |
18 | for parameter in val['parameters']:
19 |
20 | myparam = parameter
21 | myparam['platforms'] = ["win", "osx", "linux"]
22 |
23 | textlist = ["String", "ByteSize", "FilePath", "Numeric", "PID", "RegistryPath", "dateTime"]
24 |
25 | if parameter['required'] == "true":
26 | myparam['required'] = True
27 | elif parameter['required'] == "false":
28 | myparam['required'] = False
29 |
30 | if parameter['repeatable'] == "true":
31 | myparam['repeatable'] = True
32 | elif parameter['repeatable'] == "false":
33 | myparam['repeatable'] = False
34 |
35 | if parameter['type'] in textlist:
36 | myparam['type'] = "text"
37 | elif parameter['type'] == "Bool":
38 | myparam['type'] = "dropdown"
39 | myparam['values'] = ['true', 'false']
40 | elif parameter['type'] == "ArrayOfString":
41 | myparam['type'] = "textarea"
42 |
43 | myjson[val['module name']]['parameters'].append(myparam)
44 |
45 |
46 | print(json.dumps(myjson, indent=4, sort_keys=True))
--------------------------------------------------------------------------------
/scripts/w32mbr.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application/vnd.mandiant.host+xml
5 |
6 |
7 | application/vnd.mandiant.auditresult+xml
8 |
9 |
36 |
--------------------------------------------------------------------------------
/templates/widget-dropdown.html:
--------------------------------------------------------------------------------
1 | {% macro widgetHeader(elementValue, elementId, elementDefault, elementAdditionalClass="") -%}
2 |
3 |
{{elementValue}}
4 |
27 |
28 |
29 | {% if elementLabel != "" %}
30 | {{elementLabel}}
31 | {% endif %}
32 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/ht_sysinfo.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - System information{% endblock %}
3 | {% block content %}
4 |
5 |
34 |
35 | {{ htPanel.widgetHeader("System information", panelIcon="fa-info") }}
36 |
37 |
38 |
39 |
40 |
41 |
42 | {{ htPanel.widgetFooter() }}
43 |
44 | {{ htPanel.widgetHeader("API Cache", panelIcon="fa-info") }}
45 |
46 |
47 |
48 | {{ htPanel.widgetFooter() }}
49 |
50 | {% endblock %}
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Font Awesome Free License
2 | -------------------------
3 |
4 | Font Awesome Free is free, open source, and GPL friendly. You can use it for
5 | commercial projects, open source projects, or really almost whatever you want.
6 | Full Font Awesome Free license: https://fontawesome.com/license/free.
7 |
8 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
9 | In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
10 | packaged as SVG and JS file types.
11 |
12 | # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL)
13 | In the Font Awesome Free download, the SIL OFL license applies to all icons
14 | packaged as web and desktop font files.
15 |
16 | # Code: MIT License (https://opensource.org/licenses/MIT)
17 | In the Font Awesome Free download, the MIT license applies to all non-font and
18 | non-icon files.
19 |
20 | # Attribution
21 | Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
22 | Awesome Free files already contain embedded comments with sufficient
23 | attribution, so you shouldn't need to do anything additional when using these
24 | files normally.
25 |
26 | We've kept attribution comments terse, so we ask that you do not actively work
27 | to remove them from files, especially code. They're a great way for folks to
28 | learn about Font Awesome.
29 |
30 | # Brand Icons
31 | All brand icons are trademarks of their respective owners. The use of these
32 | trademarks does not indicate endorsement of the trademark holder by Font
33 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except
34 | to represent the company, product, or service to which they refer.**
35 |
--------------------------------------------------------------------------------
/templates/voltron_data.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Analysis data{% endblock %}
3 | {% block navlocation %}Analysis data{% endblock %}
4 | {% block content %}
5 |
6 |
47 |
48 | {{ htPanel.widgetHeader("Analysis data", panelIcon="fa-desktop") }}
49 |
50 | {{ htPanel.widgetFooter() }}
51 |
52 |
53 | {% endblock %}
54 |
--------------------------------------------------------------------------------
/scripts/w32tasks.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application/vnd.mandiant.host+xml
5 |
6 |
7 | application/vnd.mandiant.auditresult+xml
8 |
9 |
43 |
44 |
--------------------------------------------------------------------------------
/hxtool_task_modules/task_api_session_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # This is a system task module that performs the API logins needed by the task scheduler.
5 |
6 | from .task_module import *
7 | from hx_lib import *
8 |
9 | class task_api_session_module(task_module):
10 | def __init__(self, parent_task):
11 | super(type(self), self).__init__(parent_task)
12 |
13 | @staticmethod
14 | def input_args():
15 | return [
16 | {
17 | 'name' : 'profile_id',
18 | 'type' : str,
19 | 'required' : True,
20 | 'user_supplied' : True,
21 | 'description' : "The profile ID of the HXTool profile."
22 | },
23 | {
24 | 'name' : 'username',
25 | 'type' : str,
26 | 'required' : True,
27 | 'user_supplied' : True,
28 | 'description' : "The HX API username."
29 | },
30 | {
31 | 'name' : 'password',
32 | 'type' : str,
33 | 'required' : True,
34 | 'user_supplied' : True,
35 | 'description' : "The HX API password."
36 | }
37 | ]
38 |
39 | @staticmethod
40 | def output_args():
41 | return []
42 |
43 | def run(self, profile_id = None, username = None, password = None):
44 | ret = False
45 | hx_api_object = self.parent_task.scheduler.task_hx_api_sessions.get(profile_id, None)
46 | if hx_api_object is not None:
47 | (ret, response_code, response_data) = hx_api_object.restLogin(username, password, auto_renew_token = True)
48 | if ret:
49 | self.logger.info("Successfully initialized task API session for host {} ({})".format(hx_api_object.hx_host, profile_id))
50 | else:
51 | self.logger.warn("Failed to initialize task API session for host {} ({}). Response code: {}, response data: {}".format(hx_api_object.hx_host, profile_id, response_code, response_data))
52 | del self.parent_task.scheduler.task_hx_api_sessions[profile_id]
53 | password = None
54 | hx_api_object = None
55 | return ret
--------------------------------------------------------------------------------
/static/js/buttons.print.min.js:
--------------------------------------------------------------------------------
1 | (function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(f){return d(f,window,document)}):"object"===typeof exports?module.exports=function(f,b){f||(f=window);if(!b||!b.fn.dataTable)b=require("datatables.net")(f,b).$;b.fn.dataTable.Buttons||require("datatables.net-buttons")(f,b);return d(b,f,f.document)}:d(jQuery,window,document)})(function(d,f,b){var i=d.fn.dataTable,h=b.createElement("a"),m=function(a){h.href=a;a=h.host;-1===a.indexOf("/")&&
2 | 0!==h.pathname.indexOf("/")&&(a+="/");return h.protocol+"//"+a+h.pathname+h.search};i.ext.buttons.print={className:"buttons-print",text:function(a){return a.i18n("buttons.print","Print")},action:function(a,b,h,e){var c=b.buttons.exportData(e.exportOptions),k=function(a,c){for(var b="",d=0,e=a.length;d"+a[d]+""+c+">";return b+" "},a='';e.header&&(a+=""+k(c.header,"th")+" ");for(var a=a+"",l=0,i=c.body.length;l<
3 | i;l++)a+=k(c.body[l],"td");a+=" ";e.footer&&c.footer&&(a+=""+k(c.footer,"th")+" ");var g=f.open("",""),c=e.title;"function"===typeof c&&(c=c());-1!==c.indexOf("*")&&(c=c.replace("*",d("title").text()));g.document.close();var j=""+c+" ";d("style, link").each(function(){var a=j,b=d(this).clone()[0];"link"===b.nodeName.toLowerCase()&&(b.href=m(b.href));j=a+b.outerHTML});try{g.document.head.innerHTML=j}catch(n){d(g.document.head).html(j)}g.document.body.innerHTML=""+
4 | c+" "+("function"===typeof e.message?e.message(b,h,e):e.message)+"
"+a;d(g.document.body).addClass("dt-print-view");d("img",g.document.body).each(function(a,b){b.setAttribute("src",m(b.getAttribute("src")))});e.customize&&e.customize(g);setTimeout(function(){e.autoPrint&&(g.print(),g.close())},250)},title:"*",message:"",exportOptions:{},header:!0,footer:!1,autoPrint:!0,customize:null};return i.Buttons});
5 |
--------------------------------------------------------------------------------
/static/hxtool-js/hxtool-widgets.js:
--------------------------------------------------------------------------------
1 | function hxtoolAddInput(title, name, id, placeholder, hint) {
2 |
3 | html = '';
4 | html += '' + title + ' ';
5 | html += ' ';
6 | html += '' + hint + ' ';
7 | html += '
';
8 |
9 | return(html);
10 | }
11 |
12 | function generateDropDown(elementValue, elementId, elementDefault, entries=[{}], elementAdditionalClass, elementLabel) {
13 | var r = "";
14 |
15 | // Header
16 | r += "";
19 | r += '
' + elementValue + ' ';
20 | r += '
';
21 | r += '
";
37 | r += "
";
38 | r += "
";
39 |
40 | // Label
41 | if (elementLabel != false) {
42 | r += "" + elementLabel + " ";
43 | }
44 |
45 | r += " ";
46 |
47 | return(r);
48 | }
--------------------------------------------------------------------------------
/data/hxtool.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIF6TCCA9GgAwIBAgIJAKodHBtwAe/tMA0GCSqGSIb3DQEBCwUAMIGKMQswCQYD
3 | VQQGEwJTRTEQMA4GA1UECAwHSGFsbGFuZDEPMA0GA1UEBwwGT25zYWxhMRAwDgYD
4 | VQQKDAdGaXJlRXllMQswCQYDVQQLDAJIWDEPMA0GA1UEAwwGSFhUT09MMSgwJgYJ
5 | KoZIhvcNAQkBFhloZW5yaWsub2xzc29uQGZpcmVleWUuY29tMB4XDTE3MDIyMTEy
6 | NTY0OVoXDTQ0MDcwODEyNTY0OVowgYoxCzAJBgNVBAYTAlNFMRAwDgYDVQQIDAdI
7 | YWxsYW5kMQ8wDQYDVQQHDAZPbnNhbGExEDAOBgNVBAoMB0ZpcmVFeWUxCzAJBgNV
8 | BAsMAkhYMQ8wDQYDVQQDDAZIWFRPT0wxKDAmBgkqhkiG9w0BCQEWGWhlbnJpay5v
9 | bHNzb25AZmlyZWV5ZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
10 | AQDFTAPsfC7RVJn18fgU+XuaplfgcYFKF1OaFkJKfuuwyejhm+v738tn/h1+RGPL
11 | KMqlJI9l+6IXshau+IQHmq7chZEbWw373BYVsBbnSELLUgQ4TvZbLyvw7eewwF4S
12 | J9aRLzNiXGBEzwt0SuyGLF199ZkTQFnFtC5QK5GZXZ1LuJKryzgoq5L15IkrNatG
13 | dhJYQc6WWz2yBP4ZA+KAMvkn5rV0QCE3w9uQumzMm+Qw5v5LGzyX+wgCdYn1rMZp
14 | ipN5pmSA3QRVQlcfFBTbv9LQGNNuM0ZgetXBpuH7Otq6Us9eXWzZx+Z4hpKNX2Ri
15 | T7aj29XNf3iMAKsNjxA1ey3EqGursoGR0UzlUaXwPccblKaUnFIawVZVneO1Hcoe
16 | jbwbqESGHgMEeiZfEWInsJ8Vd/L8DxJPTjoths8OGb1/o8bNFe9ZvuOLXxZt5VpZ
17 | 1/y4YMRg8FWn8pR9+EyszLQzDPnnC5Q7Z5fhX957M7O5XxgbKoBnbH21MXptSAfv
18 | ++w94GSopQNXU4EmlT3C3bcMYwlE+ryovWt/ySM4vOHt3XAH6Yc25MIxpIwZA/JT
19 | X7Yk6jIlt3x4V2vPE7AqbB8eg0d4/uzCrxkw+OGgP3jZtdo/SWJGT/8j4i9145gg
20 | Ff/tCH3trf5+nWSLhEln2hLxGmUtPuNlEQ64X9qOm4uxFQIDAQABo1AwTjAdBgNV
21 | HQ4EFgQUDxKDVBW9F8mKWV91HeHU/zqvHoIwHwYDVR0jBBgwFoAUDxKDVBW9F8mK
22 | WV91HeHU/zqvHoIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAwvOB
23 | cNMJcqfHhk1zUhMKkMBpFpjmlz/YinrxddseOKgv2kwGSq9zm//J8sNJcmJbOPW4
24 | w0H2D+7Y/5aioRWpRz23fc5ycstQHT/Srw8yTKSASeu2yrpbCTKV+o3EwTWfu5YR
25 | 9JYJe3Po1cFr5qsAu80IFJRQnu5+xr8lhP7rbWcFiiCnbnvksU47GeYBnQ+y1Ka+
26 | OPlZkg6av2cutBEhDOqCB/w5+uqM1D8IT392dzJvRPefKAlPzppcOzrGgV4HuA80
27 | fjVVeuvXr7HhLR8yzq6y4cTYFQ3VxEEnUKOwkEiyTeAMjPjxGVhgPHtcw0S8k7v/
28 | W7Y2qrmBoHMI7LAEq7L72ivhH9cvwbie3zBVg3HF5Etq/M8s7DZCBGzdvVhSQ0wT
29 | 2mTGYlC/ANqyvis/MKw4RJ+OsLHXYeBYTqMUPi99mtln6A+r49VeZ/7cU+/tFO6c
30 | yh2SQ0nT9xgqR2yPzcFDlmmKO/JcreSzRqxQq18VD3WrAIJV7qWF4OBaqS7wThy9
31 | O0f/xd0cLfHaADr9lWpU2F5uV1ZkjG8TXKNLPUIC6D9SqENB93ks7dYs01DManOn
32 | jvUcB/+kK28qeiA17z2TlPllglLr2T9MDa6O3F2crbwDWjwuWp6cus8BNerbdUrj
33 | /n2gCnpF8KMxxHN1w3B1L7h1zg2DwjlBtqA80Nc=
34 | -----END CERTIFICATE-----
35 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-datatables.css:
--------------------------------------------------------------------------------
1 | .hxtool_datatables_buttons {
2 | position: absolute;
3 | right: 0;
4 | margin-top: -45px;
5 | margin-right: 12px;
6 | }
7 |
8 | .hxtool_datatables_popup_buttons {
9 | position: absolute;
10 | right: 0;
11 | margin-top: -42px;
12 | }
13 |
14 |
15 | .dt-button {
16 | font-size: 12px;
17 | font-weight: bold;
18 | line-height: 100%;
19 | text-transform: uppercase;
20 | background: rgba(255, 255, 255, 0.2) !important;
21 | color: rgba(255, 255, 255, 0.9) !important;
22 | border-color: #0000 !important;
23 | border-radius: 0 !important;
24 | padding: 5px !important;
25 | }
26 |
27 | .dt-button:hover, .dt-button:focus, .dt-button.focus {
28 | background-color: rgba(255, 255, 255, 0.5) !important;
29 | color: rgba(255, 255, 255, 1.0) !important;
30 | border-color: rgba(255, 255, 255, 0.1) !important;
31 | }
32 |
33 | .dt-button-info {
34 | background: rgb(31, 31, 31) !important;
35 | color: rgba(255, 255, 255, 0.9) !important;
36 | border: 1px solid rgba(255, 255, 255, 0.2) !important;
37 | }
38 |
39 | .dt-button-info h2 {
40 | background: #000000 !important;
41 | color: rgba(255, 255, 255, 0.9) !important;
42 | }
43 |
44 | .dataTables_filter {
45 | position: absolute;
46 | right: 0;
47 | margin-top: -47px;
48 | margin-right: 218px;
49 | font-family: 'Open Sans'
50 | font-size: 12px;
51 | font-weight: bold;
52 | }
53 |
54 | .dataTables_filter input {
55 | padding: 4px;
56 | font-weight: bold;
57 | display: inline-block;
58 | width: 120px;
59 | margin-left: 6px;
60 | }
61 |
62 | .dataTables_filter label {
63 | font-size: 12px;
64 | }
65 |
66 | .dataTables_paginate {
67 | text-align: right;
68 | font-family: 'Open Sans';
69 | margin-top: 12px;
70 | margin-bottom: 12px;
71 | }
72 |
73 | .paginate_button {
74 | line-height: 100%;
75 | font-size: 10px;
76 | font-weight: bold;
77 | text-transform: uppercase;
78 | background: rgba(255, 255, 255, 0.2) !important;
79 | border-color: #0000 !important;
80 | border-radius: 0 !important;
81 | padding: 5px !important;
82 | margin-right: 6px;
83 | }
84 |
85 | .disabled {
86 | color: rgba(255, 255, 255, 0.3) !important;
87 | }
88 |
89 | .paginate_button:hover {
90 | cursor: pointer;
91 | }
92 |
--------------------------------------------------------------------------------
/scripts/w32drivers-signature.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application/vnd.mandiant.host+xml
5 |
6 |
7 | application/vnd.mandiant.auditresult+xml
8 |
9 |
53 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | HXTool™ Software License 2.0
2 |
3 |
4 | Copyright © 2017 - 2020 by FireEye, Inc. All rights reserved.
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files made available with this software (the "Software") to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7 |
8 | • The above copyright notice, this permission notice, and the following provisions shall be included in all copies or substantial portions of the Software.
9 | • You agree to be bound to any and all license provisions applicable to third-party software, if any, contained in the Software.
10 | • You give the authors, copyright holder, and others the right to freely use any of your ideas, comments, suggestions, or modifications pertaining to the Software or its use that you choose to disclose.
11 | • You shall not use the trade names, trademarks, service marks, or product names of the Licensor (including, without limitation, HXTool), except HXTool may be used (i) as required for reasonable and customary use in describing the origin of the Software, and (ii) in connection with or referring to the original Software that is not modified by you.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY SUPPORT OR MAINTENANCE OF THE SOFTWARE, ITS INTEGRATION OR COMPATIBILITY WITH OTHER PRODUCTS, ANY ERROR, DEFECT OR VULNERABILITY IN THE SOFTWARE, OR ANY CLAIM, DAMAGES (INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, SPECIAL, EXEMPLARY, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER), OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF, INABILITY TO USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF ADVISED OF THE POSSBILITY OF SUCH DAMAGES. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR DEALING IN THE SOFTWARE, AND ASSUME ANY RISKS ASSOCIATED WITH YOUR EXERCISE OF PERMISSIONS UNDER THIS LICENSE.
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-scriptbuilder.css:
--------------------------------------------------------------------------------
1 | .hxtool_scriptbuilder_scriptarea {
2 | height: calc(100vh - 580px);
3 | overflow-y: auto;
4 | padding-right: 12px;
5 | padding-top: 6px;
6 | }
7 |
8 | .auditParameterPlaceholder {
9 | margin-top: 12px;
10 | }
11 |
12 | .auditParameterTitleOptional {
13 | font-family: "Open Sans";
14 | font-size: 14px;
15 | font-weight: 700;
16 | -webkit-font-smoothing: antialiased;
17 | margin-bottom: 4px;
18 | }
19 |
20 | .auditParameterTitle {
21 | font-family: "Open Sans";
22 | font-size: 14px;
23 | font-weight: 700;
24 | -webkit-font-smoothing: antialiased;
25 | margin-bottom: 4px;
26 | }
27 |
28 | .auditDescription {
29 | font-family: "Open Sans";
30 | font-size: 12px;
31 | font-weight: 400;
32 | -webkit-font-smoothing: antialiased;
33 | }
34 |
35 | .auditName {
36 | font-family: "Open Sans";
37 | font-size: 16px;
38 | text-transform: capitalize;
39 | font-weight: 700;
40 | -webkit-font-smoothing: antialiased;
41 | margin-bottom: 12px;
42 | border-bottom: 1px solid rgba(255, 255, 255, 0.2);
43 | }
44 |
45 | .auditNameUUID {
46 | font-family: "Open Sans";
47 | font-size: 12px;
48 | font-weight: 600;
49 | -webkit-font-smoothing: antialiased;
50 | margin-bottom: 12px;
51 | display: none;
52 | }
53 |
54 | .tabMenu {
55 | padding: 0;
56 | }
57 |
58 | .tabMenu li {
59 | border: 0.5px solid rgba(255, 255, 255, 0.1);
60 | color: rgba(255, 255, 255, 0.8);
61 | background: rgba(255, 255, 255, 0.2);
62 | padding: 3px;
63 | margin-bottom: 4px;
64 | font-family: "Open Sans";
65 | font-size: 12px;
66 | font-weight: 700;
67 | -webkit-font-smoothing: antialiased;
68 | text-transform: uppercase;
69 | }
70 |
71 | .tabMenu li:hover {
72 | background: rgba(255, 255, 255, 0.5);
73 | cursor: pointer;
74 | }
75 |
76 | .auditContent {
77 | padding-left: 8px;
78 | }
79 |
80 | .auditRemove {
81 | float: right;
82 | margin-top: -40px;
83 | margin-bottom: 4px;
84 | }
85 |
86 | .auditRemove:hover {
87 | background: rgba(255, 255, 255, 0.5);
88 | cursor: pointer;
89 | }
90 |
91 | .auditParameterRemove {
92 | margin-left: 6px;
93 | font-size: 10px;
94 | line-height: 12px;
95 | height: 16px;
96 | float: right;
97 | }
98 |
99 | .auditParameterRemove:hover {
100 | color: #b20032;
101 | cursor: pointer;
102 | }
103 |
104 | .auditParameterPlaceholder {
105 | margin-top: 12px;
106 | }
107 |
108 |
109 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-grid.css:
--------------------------------------------------------------------------------
1 | .dash-grid-container {
2 | display: grid;
3 | height: 90vh;
4 | grid-template-columns: 1fr;
5 | grid-template-rows: 1fr 1fr 1fr;
6 | margin: 12px;
7 | }
8 |
9 | .top {
10 | display: grid;
11 | grid-area: 1 / 1 / 2 / 2;
12 | grid-template-columns: 1fr 1fr 1fr;
13 | grid-template-rows: 1fr;
14 | grid-gap: 0 12px;
15 | padding-bottom: 12px;
16 | }
17 |
18 | .cell1 {
19 | grid-area: 1 / 1 / 2 / 2;
20 | }
21 |
22 | .cell2 {
23 | grid-area: 1 / 2 / 2 / 3;
24 | }
25 |
26 | .cell3 {
27 | grid-area: 1 / 3 / 2 / 4;
28 | }
29 |
30 | .middle {
31 | display: grid;
32 | grid-area: 2 / 1 / 3 / 2;
33 | grid-template-columns: 2fr 1fr;
34 | grid-template-rows: 1fr;
35 | grid-gap: 0 12px;
36 | padding-bottom: 12px;
37 | }
38 |
39 | .cell4 {
40 | grid-area: 1 / 1 / 2 / 2;
41 | }
42 |
43 | .cell5 {
44 | padding-left: 4px;
45 | grid-area: 1 / 2 / 2 / 3;
46 | }
47 |
48 | .cell6 {
49 | grid-area: 3 / 1 / 4 / 2;
50 | }
51 |
52 |
53 | /* AV dashboard */
54 |
55 | .avdash-grid-container {
56 | display: grid;
57 | grid-template-columns: 1fr 1fr 1fr;
58 | grid-template-rows: 0.7fr 1fr;
59 | grid-template-areas: "avcell1 avcell2 avcell3" "avtable avtable avtable";
60 | margin: 12px;
61 | height: 90vh;
62 | }
63 |
64 | .avtable { grid-area: avtable; padding-top: 12px; }
65 |
66 | .avcell1 { grid-area: avcell1; padding-right: 12px;}
67 |
68 | .avcell2 { grid-area: avcell2; padding-right: 12px;}
69 |
70 | .avcell3 { grid-area: avcell3; }
71 |
72 | /* Agent dashboard */
73 |
74 | .agentdash-grid-container {
75 | display: grid;
76 | grid-template-columns: 1fr 1fr 1fr;
77 | grid-template-rows: 1fr 1fr 1fr;
78 | grid-template-areas: "agentcell1 agentcell2 agentcell3" "agentcell4 agentcell5 agentcell6" "agentcell7 agentcell8 agentcell8";
79 | margin: 12px;
80 | height: 90vh;
81 | }
82 |
83 | .agentcell1 { grid-area: agentcell1; padding-right: 12px;}
84 |
85 | .agentcell2 { grid-area: agentcell2; padding-right: 12px;}
86 |
87 | .agentcell3 { grid-area: agentcell3; }
88 |
89 | .agentcell4 { grid-area: agentcell4; padding-right: 12px; padding-top: 12px;}
90 |
91 | .agentcell5 { grid-area: agentcell5; padding-right: 12px; padding-top: 12px;}
92 |
93 | .agentcell6 { grid-area: agentcell6; padding-top: 12px;}
94 |
95 | .agentcell7 { grid-area: agentcell7; padding-right: 12px; padding-top: 12px;}
96 |
97 | .agentcell8 { grid-area: agentcell8; padding-top: 12px;}
98 |
99 |
100 |
--------------------------------------------------------------------------------
/hxtool_task_modules/file_listing_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 |
6 | import hxtool_global
7 | from .task_module import *
8 | from hxtool_data_models import *
9 | from hx_audit import *
10 |
11 | class file_listing_task_module(task_module):
12 | def __init__(self, parent_task):
13 | super(type(self), self).__init__(parent_task)
14 |
15 | @staticmethod
16 | def input_args():
17 | return [
18 | {
19 | 'name' : 'bulk_download_eid',
20 | 'type' : int,
21 | 'required' : True,
22 | 'user_supplied' : False,
23 | 'description' : "The document ID of the bulk download job."
24 | },
25 | {
26 | 'name' : 'host_name',
27 | 'type' : str,
28 | 'required' : True,
29 | 'user_supplied' : False,
30 | 'description' : "The host name of this bulk acquisition package."
31 | },
32 | {
33 | 'name' : 'bulk_download_path',
34 | 'type' : str,
35 | 'required' : True,
36 | 'user_supplied' : False,
37 | 'description' : "The fully qualified path to the bulk acquisition package."
38 | },
39 | {
40 | 'name' : 'delete_bulk_download',
41 | 'type' : bool,
42 | 'required' : False,
43 | 'user_supplied' : True,
44 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
45 | }
46 | ]
47 |
48 | @staticmethod
49 | def output_args():
50 | return []
51 |
52 |
53 | def run(self, bulk_download_eid = None, host_name = None, bulk_download_path = None, delete_bulk_download = False):
54 | ret = False
55 | result = {}
56 | try:
57 | file_listing = hxtool_global.hxtool_db.fileListingGetByBulkId(self.parent_task.profile_id, bulk_download_eid)
58 | generator = 'files-raw'
59 | if file_listing and 'api_mode' in file_listing['cfg'] and file_listing['cfg']['api_mode']:
60 | generator = 'files-api'
61 | with AuditPackage(bulk_download_path) as audit_pkg:
62 | audit_data = audit_pkg.get_audit(generator = generator, open_only=True)
63 | if audit_data:
64 | files = get_audit_records(audit_data, generator, 'FileItem', hostname=host_name)
65 | if files:
66 | hxtool_global.hxtool_db.fileListingAddResult(self.parent_task.profile_id, bulk_download_eid, files)
67 | self.logger.debug("File Listing added to the database. bulk job: {0} host: {1}".format(bulk_download_eid, host_name))
68 | ret = True
69 | else:
70 | self.logger.warn("File Listing: No audit data for {} from bulk download job {}".format(host_name, bulk_download_eid))
71 | audit_data.close()
72 |
73 | except Exception as e:
74 | self.logger.error(pretty_exceptions(e))
75 | finally:
76 | return(ret, result)
--------------------------------------------------------------------------------
/hxtool_task_modules/mongodb_ingest_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | import json
6 |
7 | import hxtool_global
8 | from .task_module import *
9 | from hx_audit import *
10 | from hxtool_util import *
11 |
12 | class mongodb_ingest_task_module(task_module):
13 | def __init__(self, parent_task):
14 | super(type(self), self).__init__(parent_task)
15 |
16 | @staticmethod
17 | def input_args():
18 | return [
19 | {
20 | 'name' : 'host_name',
21 | 'type' : str,
22 | 'required' : True,
23 | 'user_supplied' : False,
24 | 'description' : "The host name belonging to the bulk acquisition package."
25 | },
26 | {
27 | 'name' : 'agent_id',
28 | 'type' : str,
29 | 'required' : False,
30 | 'user_supplied' : False,
31 | 'description' : "The host/agent ID of the bulk acquisition to download."
32 | },
33 | {
34 | 'name' : 'bulk_download_path',
35 | 'type' : str,
36 | 'required' : True,
37 | 'user_supplied' : False,
38 | 'description' : "The fully qualified path to the bulk acquisition package."
39 | },
40 | {
41 | 'name' : 'bulk_acquisition_id',
42 | 'type' : int,
43 | 'required' : True,
44 | 'description' : "The bulk acquisition ID assigned to the bulk acquisition job by the controller."
45 | },
46 | {
47 | 'name' : 'batch_mode',
48 | 'type' : bool,
49 | 'required' : False,
50 | 'user_supplied' : True,
51 | 'description' : "Flag whether to batch each audit as single JSON object versus sending each record as a separate object. Defaults to False"
52 | },
53 | {
54 | 'name' : 'delete_bulk_download',
55 | 'type' : bool,
56 | 'required' : False,
57 | 'user_supplied' : True,
58 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
59 | }
60 | ]
61 |
62 | @staticmethod
63 | def output_args():
64 | return []
65 |
66 | def run(self, host_name = None, agent_id = None, bulk_download_path = None, bulk_acquisition_id = None, batch_mode = False, delete_bulk_download = False):
67 | ret = False
68 | result = {}
69 | try:
70 | if bulk_download_path:
71 | for audit_object in self.yield_audit_results(bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id):
72 | hxtool_global.hxtool_db.auditInsert(audit_object)
73 | ret = True
74 | if ret and delete_bulk_download:
75 | os.remove(os.path.realpath(bulk_download_path))
76 |
77 | else:
78 | self.logger.error("bulk_download_path is empty!")
79 | except Exception as e:
80 | self.logger.error(pretty_exceptions(e))
81 | finally:
82 | return(ret, result)
--------------------------------------------------------------------------------
/static/multi-select.css:
--------------------------------------------------------------------------------
1 | .ms-container{
2 | background: transparent url('../img/switch.png') no-repeat 50% 50%;
3 | width: 370px;
4 | }
5 |
6 | .ms-container:after{
7 | content: ".";
8 | display: block;
9 | height: 0;
10 | line-height: 0;
11 | font-size: 0;
12 | clear: both;
13 | min-height: 0;
14 | visibility: hidden;
15 | }
16 |
17 | .ms-container .ms-selectable, .ms-container .ms-selection{
18 | background: #fff;
19 | color: #555555;
20 | float: left;
21 | width: 45%;
22 | }
23 | .ms-container .ms-selection{
24 | float: right;
25 | }
26 |
27 | .ms-container .ms-list{
28 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
29 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
30 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
31 | -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
32 | -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
33 | -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
34 | -o-transition: border linear 0.2s, box-shadow linear 0.2s;
35 | transition: border linear 0.2s, box-shadow linear 0.2s;
36 | border: 1px solid #ccc;
37 | -webkit-border-radius: 0px;
38 | -moz-border-radius: 0px;
39 | border-radius: 0px;
40 | position: relative;
41 | height: 200px;
42 | padding: 0;
43 | overflow-y: auto;
44 | }
45 |
46 | .ms-container .ms-list.ms-focus{
47 | border-color: rgba(82, 168, 236, 0.8);
48 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
49 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
50 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
51 | outline: 0;
52 | outline: thin dotted \9;
53 | }
54 |
55 | .ms-container ul{
56 | margin: 0;
57 | list-style-type: none;
58 | padding: 0;
59 | }
60 |
61 | .ms-container .ms-optgroup-container{
62 | width: 100%;
63 | }
64 |
65 | .ms-container .ms-optgroup-label{
66 | margin: 0;
67 | padding: 5px 0px 0px 5px;
68 | cursor: pointer;
69 | color: #999;
70 | }
71 |
72 | .ms-container .ms-selectable li.ms-elem-selectable,
73 | .ms-container .ms-selection li.ms-elem-selection{
74 | border-bottom: 1px #eee solid;
75 | padding: 2px 10px;
76 | color: #555;
77 | font-size: 14px;
78 | }
79 |
80 | .ms-container .ms-selectable li.ms-hover,
81 | .ms-container .ms-selection li.ms-hover{
82 | cursor: pointer;
83 | color: #fff;
84 | text-decoration: none;
85 | background-color: #08c;
86 | }
87 |
88 | .ms-container .ms-selectable li.disabled,
89 | .ms-container .ms-selection li.disabled{
90 | background-color: #eee;
91 | color: #aaa;
92 | cursor: text;
93 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HXTool
2 |
3 | ## Summary
4 | HXTool is a web-based, standalone tool that can be used with Trellix Endpoint Security (HX).
5 |
6 | HXTool provides additional features not directly available in the product by leveraging Trellix Endpoint Security (HX)'s rich API.
7 |
8 | ### Version
9 | 4.8-pre
10 |
11 | ## Installation
12 | To install HXTool:
13 | 1. Ensure that you have a working Python installation, see the [Dependencies](#dependencies) section below for version requirements.
14 | 2. Unzip the distribution archive; Or, if you have code repository access, fetch the repo and place the files in a directory.
15 | 2. Install HXTool's dependencies by running `pip install -r requirements.txt` from your operating system's command shell.
16 | - On Windows systems, `pip.exe` can be found in the "scripts" folder under your Python installation directory.
17 | 3. After installing the dependencies, run `python hxtool.py` from your operating system's command shell and the server will start listening to tcp port 8080 (HTTPS).
18 | - Alternatively, on Windows, you should be able to double-click on the `hxtool.py` file.
19 | 4. Access the web user interface via a browser: https://127.0.0.1:8080 (tested with Google Chrome and Mozilla Firefox)
20 | 5. You will need an account on the Endpoint Security (HX) controller that has either the `api_admin` or `api_analyst` role.
21 | 6. Don't forget to set the Background Processing credentials under Admin --> HXTool Settings. These credentials are used by the scheduler, and can be the same as what you have logged in with, or a separate set.
22 |
23 | ### Dependencies
24 | Python 3.6+
25 |
26 | Full dependency list available in [requirements.txt](requirements.txt).
27 |
28 | Optionally, the [pymongo](https://pypi.org/project/pymongo/) library may be installed for additional database functionality.
29 |
30 | ### Configuration
31 | Configuration for HXTool is held in the `conf.json` file, documentation is in [README.CONFIG](README.CONFIG).
32 |
33 | ### Docker
34 | To build a Docker image from the HXTool source, execute the following:
35 | ```bash
36 | docker build --pull -t hxtool:latest .
37 | ```
38 |
39 | To run HXTool once the image build process is complete, execute the following:
40 | ```bash
41 | docker run -p 8080:8080/tcp -d --cap-add=IPC_LOCK --name hxtool hxtool:latest
42 | ```
43 | IPC_LOCK is needed for the GNOME keyring daemon. See [README.DOCKER](README.DOCKER)
44 |
45 | ## Contribution
46 |
47 | ### Guidelines
48 | None so far
49 |
50 | ### Who do I talk to?
51 | * [Henrik Olsson](mailto:henrik.olsson@trellix.com)
52 |
53 | ### Contributors
54 | * [Elazar Broad](mailto:elazar.broad@trellix.com)
55 | * [Matthew Briggs](mailto:matthew.briggs@trellix.com)
56 | * [Martin Holste](mailto:martin.holste@trellix.com)
57 |
--------------------------------------------------------------------------------
/pytests/test_flask.py:
--------------------------------------------------------------------------------
1 | from hxtool import app, hxtool_run_main, app_init_1, hxtool_global
2 | import unittest
3 |
4 | class FlaskSimpleTests(unittest.TestCase):
5 |
6 | client = None
7 | profileName = 'unit_TEST_profile'
8 | hx_host = '10.61.152.126'
9 | profile_id = None
10 |
11 | @classmethod
12 | def setUpClass(cls):
13 | # Flask initialization
14 | app.testing = True
15 | cls.client = app.test_client()
16 | # special HXTool initialization
17 | app_init_1(True)
18 | # clean up any dirt from prior tests
19 | cls.removeProfile()
20 |
21 | @classmethod
22 | def tearDownClass(cls):
23 | cls.removeProfile()
24 |
25 | def setUp(self):
26 | pass
27 |
28 | def tearDown(self):
29 | pass
30 |
31 | def test_verifyAccessToHomePage(self):
32 | assert FlaskSimpleTests.client != None
33 | response = FlaskSimpleTests.client.get('/', follow_redirects=True)
34 | self.assertEqual(response.status_code, 200)
35 |
36 | def test_verifyUnitTestControllerProfileCreate(self):
37 | FlaskSimpleTests.createProfile()
38 | self.assertIsNotNone(FlaskSimpleTests.profile_id)
39 |
40 | def test_verifyLogin(self):
41 | FlaskSimpleTests.createProfile()
42 | response = FlaskSimpleTests.client.post(
43 | '/login',
44 | data=dict(
45 | ht_user='api_admin',
46 | ht_pass='dev3rd25!',
47 | controllerProfileDropdown=FlaskSimpleTests.profile_id
48 | ),
49 | follow_redirects=True
50 | )
51 | self.assertEqual(response.status_code, 200)
52 |
53 |
54 | @classmethod
55 | def createProfile(cls):
56 | if not FlaskSimpleTests.profile_id:
57 | #create the controller profile for unit testing
58 | hxtool_global.hxtool_db.profileCreate(
59 | hx_name=FlaskSimpleTests.profileName,
60 | hx_host=FlaskSimpleTests.hx_host,
61 | hx_port='3000')
62 | cls.profile_id = cls.getProfileId()
63 |
64 | @classmethod
65 | def removeProfile(cls):
66 | if hxtool_global.hxtool_db:
67 | # remove all instances of the unit test profile from the db
68 | for profile in hxtool_global.hxtool_db.profileList():
69 | if profile['hx_name'] == cls.profileName:
70 | hxtool_global.hxtool_db.profileDelete(profile_id=profile['profile_id'])
71 |
72 | @classmethod
73 | # Return the profile_id of our unit test profile
74 | def getProfileId(cls):
75 | for profile in hxtool_global.hxtool_db.profileList():
76 | if profile['hx_name'] == cls.profileName:
77 | return profile['profile_id']
78 | return None
79 |
--------------------------------------------------------------------------------
/hxtool_task_modules/task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import hxtool_logging
5 | from hx_lib import *
6 | from hx_audit import *
7 | from hxtool_util import *
8 |
9 | class task_module(object):
10 | MAX_RETRY = 10
11 |
12 | # TODO: parent_task should probably be renamed to just task, as modules are associated with tasks
13 | # and this confuses the parent/child task relationship.
14 | def __init__(self, task):
15 | self.parent_task = task
16 | self.logger = hxtool_logging.getLogger(__name__)
17 | self.enabled = True
18 | self.retry_count = 0
19 |
20 | def get_task_api_object(self):
21 | s = self.parent_task.scheduler.task_hx_api_sessions.get(self.parent_task.profile_id, None)
22 | if s is not None and s.restIsSessionValid():
23 | return s
24 | else:
25 | self.logger.error("There is no valid background task API session for profile {}".format(self.parent_task.profile_id))
26 | return None
27 |
28 | def can_retry(self, err):
29 | return('connection' in str(type(err)).lower() and self.retry_count < task_module.MAX_RETRY)
30 |
31 | def yield_audit_results(self, bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = None):
32 | hx_host = None
33 | api_object = self.get_task_api_object()
34 | if api_object:
35 | hx_host = api_object.hx_host
36 | api_object = None
37 |
38 | with AuditPackage(bulk_download_path) as audit_package:
39 | for audit in audit_package.audits:
40 | try:
41 | for audit_object in audit_package.audit_to_dict(audit, host_name, agent_id = agent_id, batch_mode = batch_mode):
42 | audit_object.update({
43 | 'hx_host' : hx_host,
44 | 'bulk_acquisition_id' : bulk_acquisition_id
45 | })
46 | yield audit_object
47 | except EmptyAuditException as e:
48 | self.logger.warning(e)
49 |
50 | # Input and output args are a list of dictionary objects containing the following five keys: name, type, required user_supplied, and description
51 | # these define the modules inputs and outputs, for example:
52 | # @staticmethod
53 | # def input_args():
54 | # return [ {'name' : 'foo', 'type' : str, 'required' : True, 'user_supplied' : True, 'description' : "Foo argument"} ]
55 | #
56 | @staticmethod
57 | def input_args():
58 | raise NotImplementedError("You must define a list of arguments that your module's run() function requires!")
59 |
60 | @staticmethod
61 | def output_args():
62 | raise NotImplementedError("You must define a list of arguments that your module will output!")
63 |
64 | # Note: function return must be a tuple of (boolean, result)
65 | def run(self, **kwargs):
66 | raise NotImplementedError("You must override run() in your task module.")
67 |
68 | # Used by the task scheduler to signal that we are an HXTool Task Module
69 | @staticmethod
70 | def hxtool_task_module():
71 | return True
--------------------------------------------------------------------------------
/static/hxtool-js/hxtool-generic.js:
--------------------------------------------------------------------------------
1 | function hxtool_ajax_post_request(endpoint, mydata, successCallback, contentType=false) {
2 | $.ajax
3 | ({
4 | type: "POST",
5 | url: endpoint,
6 | dataType: 'json',
7 | contentType: contentType,
8 | processData: false,
9 | data: mydata,
10 | success: successCallback,
11 | error: hxtoolActionFail
12 | })
13 | }
14 |
15 | function hxtool_ajax_get_request(endpoint, myargs, successCallback) {
16 | $.ajax
17 | ({
18 | url: endpoint,
19 | dataType: 'json',
20 | contentType: 'application/json',
21 | data: myargs,
22 | success: successCallback,
23 | error: hxtoolActionFail
24 | })
25 | }
26 |
27 | function hxtoolActionFail(xhr,status,error) {
28 | $("#hxtoolMessageBody").html(JSON.stringify(xhr['responseText']));
29 | $("#hxtoolMessage").show();
30 | }
31 |
32 |
33 | function getHistoricDate(days) {
34 | var historicDate = new Date();
35 | historicDate.setDate(historicDate.getDate() - days);
36 | return(historicDate.toISOString().substr(0, 10))
37 | }
38 |
39 | function updateChartJS(name, url) {
40 | var jsonData = $.ajax({
41 | url: url,
42 | dataType: 'json',
43 | }).done(function (myChartData) {
44 | name.data = myChartData;
45 | name.options.animation.duration = 0;
46 | name.update();
47 | });
48 | }
49 |
50 | var getUrlParameter = function getUrlParameter(sParam) {
51 | var sPageURL = window.location.search.substring(1),
52 | sURLVariables = sPageURL.split('&'),
53 | sParameterName,
54 | i;
55 |
56 | for (i = 0; i < sURLVariables.length; i++) {
57 | sParameterName = sURLVariables[i].split('=');
58 |
59 | if (sParameterName[0] === sParam) {
60 | return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
61 | }
62 | }
63 | };
64 |
65 | function hxtoolGenerateNestedTable(myData) {
66 | var r = "";
83 | return(r);
84 | }
85 |
86 | function hxtoolGenerateNestedObjectView(myData) {
87 | var r = "";
88 | console.log(myData);
89 | $.each( myData, function( index, value ) {
90 | r += "";
91 | r += index + ": ";
92 | if (isObject(value)) {
93 | hxtoolGenerateNestedObjectView(value);
94 | }
95 | else {
96 | r += value;
97 | }
98 | r += "
";
99 | });
100 | }
101 |
102 | function isObject(obj) {
103 | return obj === Object(obj);
104 | }
105 |
--------------------------------------------------------------------------------
/hxtool_task_modules/file_acquisition_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | import time
6 |
7 | import hxtool_global
8 | from .task_module import *
9 | from hxtool_util import *
10 |
11 | class file_acquisition_task_module(task_module):
12 | def __init__(self, parent_task):
13 | super(type(self), self).__init__(parent_task)
14 |
15 | @staticmethod
16 | def input_args():
17 | return [
18 | {
19 | 'name' : 'multi_file_eid',
20 | 'type' : int,
21 | 'required' : True,
22 | 'user_supplied' : False,
23 | 'description' : "The document ID of the multi-file download job."
24 | },
25 | {
26 | 'name' : 'file_acquisition_id',
27 | 'type' : int,
28 | 'required' : True,
29 | 'user_supplied' : False,
30 | 'description' : "The ID assigned to the file acquisition by the controller."
31 | },
32 | {
33 | 'name' : 'host_name',
34 | 'type' : str,
35 | 'required' : True,
36 | 'user_supplied' : False,
37 | 'description' : "The host name of this file acquisition package."
38 | }
39 | ]
40 |
41 | @staticmethod
42 | def output_args():
43 | return []
44 |
45 | def run(self, multi_file_eid = None, file_acquisition_id = None, host_name = None):
46 | ret = False
47 | result = {}
48 | try:
49 | hx_api_object = self.get_task_api_object()
50 | if hx_api_object:
51 | self.logger.debug("Processing multi file acquisition job: {0}.".format(multi_file_eid))
52 | download_directory = make_download_directory(hx_api_object.hx_host, multi_file_eid, job_type = 'multi_file')
53 | (ret, response_code, response_data) = hx_api_object.restFileAcquisitionById(file_acquisition_id)
54 | if ret and response_data and response_data['data']['state'] == "COMPLETE" and response_data['data']['url']:
55 | self.logger.debug("Processing multi file acquisition host: {0}".format(host_name))
56 | full_path = os.path.join(download_directory, get_download_filename(host_name, file_acquisition_id))
57 | (ret, response_code, response_data) = hx_api_object.restDownloadFile('{}.zip'.format(response_data['data']['url']), full_path)
58 | if ret:
59 | hxtool_global.hxtool_db.multiFileUpdateFile(self.parent_task.profile_id, multi_file_eid, file_acquisition_id)
60 | self.logger.info("File Acquisition download complete. Acquisition ID: {0}, Batch: {1}".format(file_acquisition_id, multi_file_eid))
61 | elif response_code == 404:
62 | self.logger.error("File acquisition ID: {} not found on the controller.".format(file_acquisition_id))
63 | self.parent_task.stop()
64 | else:
65 | self.logger.debug("Deferring file acquisition for: {}".format(host_name))
66 | self.parent_task.defer()
67 | else:
68 | self.logger.warn("No task API session for profile: {}".format(self.parent_task.profile_id))
69 | except Exception as e:
70 | self.logger.error(e)
71 | finally:
72 | return(ret, result)
--------------------------------------------------------------------------------
/hxtool_task_modules/enterprise_search_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import hxtool_global
5 | from .task_module import *
6 | from hx_lib import *
7 |
8 | class enterprise_search_task_module(task_module):
9 | def __init__(self, parent_task):
10 | super(type(self), self).__init__(parent_task)
11 |
12 | @staticmethod
13 | def input_args():
14 | return [
15 | {
16 | 'name' : 'script',
17 | 'type' : str,
18 | 'required' : True,
19 | 'user_supplied' : True,
20 | 'description' : "The OpenIOC 1.1 formatted script to utilize."
21 | },
22 | {
23 | 'name' : 'hostset_id',
24 | 'type' : int,
25 | 'required' : True,
26 | 'user_supplied' : True,
27 | 'description' : "The ID of the host set to execute the script against."
28 | },
29 | {
30 | 'name' : 'ignore_unsupported_items',
31 | 'type' : bool,
32 | 'required' : False,
33 | 'user_supplied' : True,
34 | 'description' : "Specifies whether to instruct the HX controller to ignore unsupported items in the script. Defaults to False"
35 | },
36 | {
37 | 'name' : 'skip_base64',
38 | 'type' : bool,
39 | 'required' : False,
40 | 'user_supplied' : True,
41 | 'description' : "Specifies whether the contents of the script argument are already base64 encoded. Defaults to False"
42 | },
43 | {
44 | 'name' : 'displayname',
45 | 'type' : str,
46 | 'required' : False,
47 | 'user_supplied' : True,
48 | 'description' : "Specifies the display name of the search. Defaults to False"
49 | }
50 | ]
51 |
52 | @staticmethod
53 | def output_args():
54 | return [
55 | {
56 | 'name' : 'enterprise_search_id',
57 | 'type' : int,
58 | 'required' : True,
59 | 'description' : "The Enterprise Search ID assigned to the search job by the controller."
60 | }
61 | ]
62 |
63 | def run(self, script = None, hostset_id = None, ignore_unsupported_items = False, skip_base64 = False, displayname = False):
64 | ret = False
65 | result = {}
66 | if script:
67 | hx_api_object = self.get_task_api_object()
68 | if hx_api_object and hx_api_object.restIsSessionValid():
69 | (ret, response_code, response_data) = hx_api_object.restSubmitSweep(script, hostset_id, ignore_unsupported_items = ignore_unsupported_items, skip_base64 = skip_base64, displayname = displayname)
70 | if ret:
71 | result['enterprise_search_id'] = response_data['data']['_id']
72 | self.parent_task.name = "Enterprise Search ID: {}".format(response_data['data']['_id'])
73 | self.logger.info("Enterprise Search ID: {} successfully submitted.".format(result['enterprise_search_id']))
74 | else:
75 | self.logger.error("Enterprise Search submission failed. Response code: {}, response data: {}".format(response_code, response_data))
76 | else:
77 | self.logger.warn("No task API session for profile: {}".format(self.parent_task.profile_id))
78 | return(ret, result)
--------------------------------------------------------------------------------
/static/spinner.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/ht_hostsearch.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Find a host{% endblock %}
3 | {% block navlocation %}Find a host{% endblock %}
4 | {% block content %}
5 |
6 |
73 |
74 | {{ htPanel.widgetHeader("Matching hosts", panelIcon="fa-desktop") }}
75 |
76 | {{ htPanel.widgetFooter() }}
77 |
78 |
79 | {% endblock %}
80 |
--------------------------------------------------------------------------------
/hxtool_task_modules/stacking_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 |
6 | import hxtool_global
7 | from .task_module import *
8 | from hxtool_data_models import *
9 | from hx_audit import *
10 |
11 | class stacking_task_module(task_module):
12 | def __init__(self, parent_task):
13 | super(type(self), self).__init__(parent_task)
14 |
15 | @staticmethod
16 | def input_args():
17 | return [
18 | {
19 | 'name' : 'bulk_download_eid',
20 | 'type' : int,
21 | 'required' : True,
22 | 'user_supplied' : False,
23 | 'description' : "The document ID of the bulk download job."
24 | },
25 | {
26 | 'name' : 'host_name',
27 | 'type' : str,
28 | 'required' : True,
29 | 'user_supplied' : False,
30 | 'description' : "The host name of this bulk acquisition package."
31 | },
32 | {
33 | 'name' : 'bulk_download_path',
34 | 'type' : str,
35 | 'required' : True,
36 | 'user_supplied' : False,
37 | 'description' : "The fully qualified path to the bulk acquisition package."
38 | },
39 | {
40 | 'name' : 'delete_bulk_download',
41 | 'type' : bool,
42 | 'required' : False,
43 | 'user_supplied' : True,
44 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
45 | }
46 | ]
47 |
48 | @staticmethod
49 | def output_args():
50 | return []
51 |
52 | def run(self, bulk_download_eid = None, host_name = None, bulk_download_path = None, delete_bulk_download = False):
53 | try:
54 | ret = False
55 | if bulk_download_path:
56 | stack_job = hxtool_global.hxtool_db.stackJobGet(profile_id = self.parent_task.profile_id, bulk_download_eid = bulk_download_eid)
57 | stack_model = hxtool_data_models(stack_job['stack_type']).stack_type
58 | with AuditPackage(bulk_download_path) as audit_pkg:
59 | audit_data = audit_pkg.get_audit(generator=stack_model['audit_module'], open_only=True)
60 | if audit_data:
61 | records = get_audit_records(audit_data, stack_model['audit_module'], stack_model['item_name'], fields=stack_model['fields'], post_process=stack_model['post_process'], hostname=host_name)
62 | if records:
63 | hxtool_global.hxtool_db.stackJobAddResult(self.parent_task.profile_id, bulk_download_eid, host_name, records)
64 | self.logger.debug("Stacking records added to the database for host {}".format(host_name))
65 | ret = True
66 | else:
67 | self.logger.warn("Stacking: No audit data for {}".format(host_name))
68 |
69 | # Explicitly close
70 | audit_data.close()
71 |
72 | if ret and delete_bulk_download:
73 | try:
74 | os.remove(os.path.realpath(bulk_download_path))
75 | except:
76 | self.logger.warn("Failed to remove {}".format(os.path.realpath(bulk_download_path)))
77 |
78 | else:
79 | self.logger.error("bulk_download_path is empty!")
80 |
81 | return(ret, None)
82 | except Exception as e:
83 | self.logger.error(pretty_exceptions(e))
84 | return(False, None)
--------------------------------------------------------------------------------
/scripts/w32processes-memory.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application/vnd.mandiant.host+xml
5 |
6 |
7 | application/vnd.mandiant.auditresult+xml
8 |
9 |
72 |
--------------------------------------------------------------------------------
/templates/widget-schedule.html:
--------------------------------------------------------------------------------
1 | {% import 'widget-radio.html' as htRadio %}
2 | {% import 'widget-dropdown.html' as htDropdown %}
3 | {% import 'widget-input.html' as htInput %}
4 |
5 | {% macro widgetHeader() -%}
6 |
37 |
38 |
73 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/ht_search_dd.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Enterprise Search{% endblock %}
3 | {% block navlocation %}Enterprise Search - Drilldown{% endblock %}
4 | {% block content %}
5 |
6 |
68 |
69 | {{ htPanelNoHeader.widgetHeader(panelDisplay="inline-block") }}
70 | back
71 | {{ htPanelNoHeader.widgetFooter() }}
72 |
73 |
74 |
75 |
76 |
77 | {% endblock %}
78 |
--------------------------------------------------------------------------------
/hxtool_task_modules/file_write_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | import json
6 |
7 | import hxtool_global
8 | from .task_module import *
9 | from hx_audit import *
10 | from hxtool_util import *
11 |
12 | class file_write_task_module(task_module):
13 | def __init__(self, parent_task):
14 | super(type(self), self).__init__(parent_task)
15 |
16 | @staticmethod
17 | def input_args():
18 | return [
19 | {
20 | 'name' : 'host_name',
21 | 'type' : str,
22 | 'required' : True,
23 | 'user_supplied' : False,
24 | 'description' : "The host name belonging to the bulk acquisition package."
25 | },
26 | {
27 | 'name' : 'agent_id',
28 | 'type' : str,
29 | 'required' : False,
30 | 'user_supplied' : False,
31 | 'description' : "The host/agent ID of the bulk acquisition to download."
32 | },
33 | {
34 | 'name' : 'bulk_download_path',
35 | 'type' : str,
36 | 'required' : True,
37 | 'user_supplied' : False,
38 | 'description' : "The fully qualified path to the bulk acquisition package."
39 | },
40 | {
41 | 'name' : 'bulk_acquisition_id',
42 | 'type' : int,
43 | 'required' : True,
44 | 'description' : "The bulk acquisition ID assigned to the bulk acquisition job by the controller."
45 | },
46 | {
47 | 'name' : 'batch_mode',
48 | 'type' : bool,
49 | 'required' : False,
50 | 'user_supplied' : True,
51 | 'description' : "Flag whether to batch each audit as single JSON object versus sending each record as a separate object. Defaults to False"
52 | },
53 | {
54 | 'name' : 'delete_bulk_download',
55 | 'type' : bool,
56 | 'required' : False,
57 | 'user_supplied' : True,
58 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
59 | },
60 | {
61 | 'name' : 'file_name',
62 | 'type' : str,
63 | 'required' : True,
64 | 'user_supplied' : True,
65 | 'description' : "The fully qualified path of the file to write to."
66 | }
67 | ]
68 |
69 | @staticmethod
70 | def output_args():
71 | return []
72 |
73 | def run(self, host_name = None, agent_id = None, bulk_download_path = None, bulk_acquisition_id = None, batch_mode = False, delete_bulk_download = False, file_name = None):
74 | ret = False
75 | result = {}
76 | try:
77 | if bulk_download_path:
78 | # TODO: Ultimately, this should be converted to utilizing the Python rotating log handler.
79 | with TemporaryFileLock(os.path.dirname(file_name), file_name = "{}.lock".format(os.path.basename(file_name))):
80 | with open(file_name, 'a') as f:
81 | for audit_object in self.yield_audit_results(bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id):
82 | json.dump(audit_object, f, sort_keys = False)
83 | f.write('\n')
84 | f.close()
85 | ret = True
86 | if ret and delete_bulk_download:
87 | os.remove(os.path.realpath(bulk_download_path))
88 |
89 | else:
90 | self.logger.error("bulk_download_path is empty!")
91 | except Exception as e:
92 | self.logger.error(pretty_exceptions(e))
93 | finally:
94 | return(ret, result)
--------------------------------------------------------------------------------
/templates/ht_auditmanager.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Audit Manager{% endblock %}
3 | {% block navlocation %}Audit Manager{% endblock %}
4 | {% block content %}
5 |
6 |
83 |
84 | {{ htPanel.widgetHeader("Collected acquisitions and audits", panelIcon="fa-table") }}
85 |
86 | {{ htPanel.widgetFooter() }}
87 |
88 | {% endblock %}
89 |
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-host.css:
--------------------------------------------------------------------------------
1 | .host-grid-container {
2 | display: grid;
3 | grid-template-columns: 0.5fr 1fr 0.4fr;
4 | grid-template-rows: 160px;
5 | grid-template-areas: "top top top" "alerts content acquisitions";
6 | height: calc(100vh - 160px);
7 | }
8 |
9 | .host-top {
10 | grid-area: top;
11 | }
12 |
13 | .host-alerts {
14 | grid-area: alerts;
15 | }
16 |
17 | .host-content {
18 | grid-area: content;
19 | padding-left: 12px;
20 | padding-right: 12px;
21 | }
22 |
23 | .host-acquisitions {
24 | grid-area: acquisitions;
25 | }
26 |
27 | .hxtool_host_panel_read_more {
28 | background: #0d1a2b;
29 | padding: 3px;
30 | padding-left: 24px;
31 | padding-right: 24px;
32 | font-size: 10px;
33 | font-weight: bold;
34 | border-top: 1px solid rgba(15, 184, 220, 0.4);
35 | }
36 |
37 | .hxtool_host_panel_read_more:hover {
38 | background: rgba(255, 255, 255, 0.2);
39 | cursor: pointer;
40 | }
41 |
42 | .panelHostClass {
43 | }
44 |
45 | .panelAlertsClass {
46 | overflow: auto;
47 | height: calc(100vh - 290px);
48 | }
49 |
50 | .panelContentClass {
51 | overflow: auto;
52 | height: calc(100vh - 290px);
53 | }
54 |
55 | .panelAcqClass {
56 | overflow: auto;
57 | height: calc(100vh - 290px);
58 | }
59 |
60 | .hxtool_host_alert_table tbody tr:hover {
61 | background: rgba(255,255,255,0.1);
62 | cursor: pointer;
63 | }
64 |
65 | .hxtool_host_acq_table tbody tr:hover {
66 | background: rgba(255,255,255,0.1);
67 | cursor: pointer;
68 | }
69 |
70 | .hxtool_host_ul {
71 | list-style-type: none;
72 | background: url(/static/vlines/vline.png) repeat-y;
73 | margin-left: 40px;
74 | padding: 0;
75 | }
76 |
77 | .hxtool_host_ul li {
78 | margin: 0;
79 | padding: 0px 12px;
80 | line-height: 34px;
81 | background: url(/static/vlines/node.png) no-repeat;
82 | }
83 |
84 | .hxtool_host_ul li:last-child {
85 | background: url(/static/vlines/lastnode.png) no-repeat;
86 | }
87 |
88 | .hxtool_host_table {
89 | width: 100%;
90 | }
91 |
92 | .hxtool_host_table tbody td:nth-child(1) {
93 | width: 150px;
94 | }
95 |
96 | .hxtool_host_table tbody tr:nth-child(odd) {
97 | background: transparent;
98 | }
99 |
100 | .hxtool_host_table tbody td {
101 | border-right: 0;
102 | }
103 |
104 | .hxtool_host_table tbody tr {
105 | border-bottom: 0;
106 | }
107 |
108 | .product {
109 | text-align: center;
110 | }
111 |
112 | .hxtool_host_info_cell {
113 | background: rgba(0,0,0,0.2);
114 | width: 120px;
115 | font-weight: bold;
116 | }
117 |
118 | .hxtool_table_host_alert {
119 | width: 100%;
120 | margin-bottom: 24px;
121 | }
122 |
123 | .hxtool_table_host_alert tbody tr:nth-child(odd) {
124 | background: transparent;
125 | }
126 |
127 | .hxtool_alert_header {
128 | margin-block-start: 6px;
129 | margin-block-end: 0;
130 | border-bottom: 1px solid rgba(15, 184, 220, 0.4);
131 | font-size: 14px;
132 | padding-bottom: 3px;
133 | padding-left: 2px;
134 | }
135 |
136 | .hxtool_alert_json_item {
137 | font-weight: bold;
138 | border: 1px solid #10455B;
139 | padding: 3px;
140 | border-radius: 2px;
141 | background: #0A0F18;
142 |
143 | }
144 |
145 | .hxtool_host_alert_goLink {
146 | margin-right: 6px;
147 | }
148 |
149 | .acqRemove {
150 | margin-left: 6px;
151 | }
152 |
153 | .allAcqDetailsButton {
154 | display: block;
155 | margin-top: 24px;
156 | }
157 |
--------------------------------------------------------------------------------
/data/hxtool.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDFTAPsfC7RVJn1
3 | 8fgU+XuaplfgcYFKF1OaFkJKfuuwyejhm+v738tn/h1+RGPLKMqlJI9l+6IXshau
4 | +IQHmq7chZEbWw373BYVsBbnSELLUgQ4TvZbLyvw7eewwF4SJ9aRLzNiXGBEzwt0
5 | SuyGLF199ZkTQFnFtC5QK5GZXZ1LuJKryzgoq5L15IkrNatGdhJYQc6WWz2yBP4Z
6 | A+KAMvkn5rV0QCE3w9uQumzMm+Qw5v5LGzyX+wgCdYn1rMZpipN5pmSA3QRVQlcf
7 | FBTbv9LQGNNuM0ZgetXBpuH7Otq6Us9eXWzZx+Z4hpKNX2RiT7aj29XNf3iMAKsN
8 | jxA1ey3EqGursoGR0UzlUaXwPccblKaUnFIawVZVneO1HcoejbwbqESGHgMEeiZf
9 | EWInsJ8Vd/L8DxJPTjoths8OGb1/o8bNFe9ZvuOLXxZt5VpZ1/y4YMRg8FWn8pR9
10 | +EyszLQzDPnnC5Q7Z5fhX957M7O5XxgbKoBnbH21MXptSAfv++w94GSopQNXU4Em
11 | lT3C3bcMYwlE+ryovWt/ySM4vOHt3XAH6Yc25MIxpIwZA/JTX7Yk6jIlt3x4V2vP
12 | E7AqbB8eg0d4/uzCrxkw+OGgP3jZtdo/SWJGT/8j4i9145ggFf/tCH3trf5+nWSL
13 | hEln2hLxGmUtPuNlEQ64X9qOm4uxFQIDAQABAoICAHBz9UCTP3Qczmw6cHY0BNmO
14 | ukO5LkH2rbYDveEMGnZ3fv8oigbT9fHeCx1vCZpAM9CQ2BL+q9LptLgh+c8DwWr7
15 | zktTSNMnDIdsCIHm0/tjUfhuOUibyGXYk9hQrM2YW1oBFz6W/F/7ysGL+ug23Urv
16 | 80Hfycs/+a3ER4asrvz7xM2aVPYJZQg2LGCuhGLy5V3clE1qz+1pnxLO/gioBQ9T
17 | FlWeP9CzF7CUMXMl35hn8MUKTy0o7dXI/MtEoQqC66/IwTwZvWCDIXkbTxA5c4Uc
18 | wVXsb86J9NAduGwjjYvpqzxT77jpkVldCqb9mg/W83jN0j0AzMqvjs95nXl+LgUI
19 | 40HOjFIWWfu6zXxwg7OchyYwI/5VaP12rhhxKlxBhAP8yfKwvP+yTRxzdf0DCQUh
20 | ImwWqxi+IJ3ndzuA+aV2Iq13q+FILX37LVrLYu0aklNXF1novTAxcJ6jeBvCyr33
21 | PXEVGoV5oYiG5mC6oqTFHPMD6iLzNnu61wkt1/hRH+is4tQAzk/zC0THo/tvTGc+
22 | Bv6Xub1rzsM4XvwlHkbGe/oU7NLgRSiQXLV2svfjVd/0uDolj1IB+dVWmqEZHuaX
23 | uekNJhQcZMw5bX7mdeb/xBRPHU9Uy87u8niOFBj/2VXyZCzWv1tjN6vo2ImpMdY/
24 | /q7xkXq2sDwX8ySpFTwBAoIBAQD/CejN7UuiAulZ5fg7So5S6fguSGH8361y4t6K
25 | eZGYQrjWhIBgLQkdisdTEtgUN+nOvkDASbQL4ZJUMytPSfrl3VpqUiqqLNHNKtIl
26 | AmLWPdC2omWoNMo4pSOsKbp3ogo9HLyqFqKsmOsb/qGQcxYhQqsP5ChE0uIkpFY3
27 | 4l4CGE00+0Jq7vL63SIRbFoa6rEHLtf7obd3H496xCVH649ppYooTD40nI4p5aOD
28 | 2aGdV2aKZe6/ApsOqLkPz1ufPB5lJfgnDoMP1gaB3pglkeVNfJDQbWO27FdH6M1I
29 | 8pU62ehtOLH4NJOtYGRq9/DZFLMi6U+z6sQxlkQndOFg90+VAoIBAQDGCmPaGz1a
30 | XmEXJMJjnHlMWq98rOyVNRsBRPdr+I692bvaP6mrQHBW6fnoJ0G7leVDJiOtQXnn
31 | AlKGMsM5DnE9G+6zK72hU1KkTjpxQgRf0ZZ4WGPrBmRgaTRpVyIfE6l2kaAvp+C3
32 | jHSDukvcxST2oR5Z7WluTUGLYo5jNxYWVhYqaF1/iwSti5tyZD3gqpDvcgD/Glvj
33 | bdCKOiWJCjCHl42ieuMbMjOwyHBn0aYGNMdSE3hMVlbvnWIxqKPKWdprg/QDa5jZ
34 | d+6zv4Ye8NPGONZg0lrcGubYha93piNbbVzdprFxv1JPPjvm8WsmQFpvy3sujsiJ
35 | +bBnt8oQ8HuBAoIBAQDQmOdMPxFEcsMv31O4ExPzpyBxooxaywxP0lWYxzQZaEFM
36 | W9WwVEWHXzIGtXv8lXrruVq2q9HSge4wZiW/VVAcYH8KRShWRhBXkfWNhbUXbDng
37 | l1U0TfE0gYV61CqKnQNo1q9NIvRs3So3nH3C6w6np6LIfaGeISoMNEm8ra6cYgoM
38 | EpJRah1cqC+sNoZAS8L9kAfh7XRkv3CYRgQEHhwPmfE1Yp7iY0Y36HZkakWwroLV
39 | IegzXMs8Iy4ySzSyOfbWXkbokwsJkdGCuXCSEhGN3huIDmCnhgkhbL0zNA5wszhS
40 | 1TNjQoWjIhsgDql0tGSMYm3pR1SvBiu6ZfPNXpo9AoIBAQCO2zHaRGoGhSxOUJL0
41 | 3gvV21jZe7gRjcRULxa3yQ3Wv3i139SZlxsyZweBwse09FT0ElAMC75OuKsk6PtQ
42 | bi2bYknW70eUVxG3OkMILhIPuJVtbH1vLSY9Mca/8j3H4xwMTtIZbmU4olXuK/XL
43 | ZF7cla7aOdsi2RHd5RNHWJZTOHg20SAZAAQ42AsjAlJsfT2drEQxwSblsPKMs5Md
44 | /r6xIM7nlPO8S4NkE8KZ8W5s7aeWejr9/g4qPQJ3ReoY7qYThpT/3p7cyJnlCdRK
45 | /3gUdi2WnEc0nSdGq3C+w5afvg0OSs+XeOZ8CS2W0zFy31sdZ9AM7qyUcwwgVUCq
46 | 5X6BAoIBAQDxaX4VflY3VppXNAtBNhJKUR2b3on/3vsbFWdJT4gg/9bPGBTakkA+
47 | yjtSVWeMRwavFPG21VctCoo7l1GcvL8vhG1napBMcV14iVADy3FU5r0Hku52ccHp
48 | w1mvS01FXK64UAPwMld7T+ORsuWEciuIsfEtVU46XPqX2/OqqgcEPBqNRcBqVGo1
49 | A6cWPQ0m4sVWDVewX2I6JOzoUhG+ipwhJpffH/kazXnnJwwAq1VBSHMHU2jq57ly
50 | CBLC/FUnfsWqCXWi/hPVWPqjRlxZUy2gcHLPFpMThpMhQKsOD3FFrMbjoA70imqB
51 | cG9cTrUzc+/QoXPcKlacyHhYdT8wrgr1
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/static/fireeye.svg:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
8 |
10 |
13 |
15 |
17 |
20 |
22 |
25 |
27 |
30 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/templates/ht_stacking_analyze.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Stacking analysis{% endblock %}
3 | {% block navlocation %}Stacking analysis{% endblock %}
4 | {% block content %}
5 |
6 |
76 |
77 | {{ htPanelNoHeader.widgetHeader(panelDisplay="inline-block") }}
78 | back
79 | {{ htPanelNoHeader.widgetFooter() }}
80 |
81 | {{ htPanel.widgetHeader("Stacking results", panelId="iocTableContainer", panelIcon="fa-table", elementAdditionalBodyClass="hxtool_panel_stackinganalyze") }}
82 |
83 | {{ htPanel.widgetFooter() }}
84 |
85 | {{ htModal.widgetHeader("Matching endpoints", modalId="endpointViewPopup", modalSize="medium") }}
86 | {{ htModal.widgetMiddle() }}
87 | Dismiss
88 | {{ htModal.widgetFooter() }}
89 |
90 | {% endblock %}
--------------------------------------------------------------------------------
/static/hxtool-css/hxtool-table.css:
--------------------------------------------------------------------------------
1 | /* Generic datatables table */
2 |
3 | .hxtool_table {
4 | border-collapse: collapse;
5 | font-weight: 400;
6 | }
7 |
8 | .hxtool_table td, .hxtool_table tr, .hxtool_table th {
9 |
10 | }
11 |
12 | .hxtool_table thead td, .hxtool_table thead th {
13 | padding: 2px;
14 | padding-top: 4px;
15 | padding-bottom: 4px;
16 | font-size: 11px;
17 | border-right: 1px solid rgba(15, 184, 220, 0.4);;
18 | border-bottom: 1px solid rgba(15, 184, 220, 0.4);;
19 | vertical-align: bottom;
20 | }
21 |
22 | .hxtool_table thead td:last-child, .hxtool_table thead th:last-child {
23 | border-right: none;
24 | }
25 |
26 |
27 | .hxtool_table tbody td {
28 | padding: 2px;
29 | padding-top: 4px;
30 | padding-bottom: 4px;
31 | border-right: 1px solid rgba(15, 184, 220, 0.4);
32 | font-size: 11px;
33 | vertical-align: middle;
34 | }
35 |
36 | .hxtool_table tbody td:last-child {
37 | border-right: none;
38 | }
39 |
40 | .hxtool_table tbody tr {
41 | border-bottom: 1px solid rgba(15, 184, 220, 0.1);
42 | }
43 |
44 | .hxtool_table tbody tr:hover {
45 | background: rgba(255,255,255,0.1);
46 | }
47 |
48 | /* Zebra striping?
49 | .hxtool_table tbody tr:nth-child(odd) {
50 | background: rgba(0,0,0,0.2);
51 | }
52 | */
53 |
54 | .hxtool_table tbody tr:last-child {
55 | border-bottom: none;
56 | }
57 |
58 | .hxtool_table a:link, a:visited {
59 | font-size: 12px;
60 | font-weight: bold;
61 | color: rgba(255, 255, 255, 0.8);
62 | }
63 |
64 | .hxtool_table a:hover {
65 | color: #0fb8dc;
66 | }
67 |
68 | .streaming_ioc_id {
69 | font-size: xx-small;
70 | color: #006b8c
71 | }
72 |
73 | .streaming_condition_id {
74 | font-size: xx-small;
75 | color: #0fb8dc
76 | }
77 |
78 | /* Generic datatables Exceptions */
79 |
80 | .hxtool_table_cell_center {
81 | text-align: center;
82 | }
83 |
84 | .hxtool_table_cell_vertical {
85 | transform: rotate(-65deg);
86 | transform-origin: top left;
87 | text-align: left;
88 | padding: 0;
89 | position: absolute;
90 | margin-top: -10px;
91 | }
92 |
93 | .hxtool_table_header_es thead th:nth-child(n+12):nth-last-child(n+3) {
94 | padding: 0;
95 | height: 80px;
96 | min-width: 40px;
97 | max-width: 40px;
98 | }
99 |
100 | .hxtool_table_header_es thead th:nth-child(3) {
101 | text-align: left;
102 | padding-left: 5px;
103 | }
104 |
105 | .hxtool_alerts_filter th, td {
106 | padding-left: 6px;
107 | padding-right: 6px;
108 | text-align: left;
109 | }
110 |
111 | .hxtool_alerts_filter th:nth-child(1) {
112 | width: 300px;
113 | }
114 |
115 | .hxtool_alerts_filter th:nth-child(2) {
116 | width: 300px;
117 | }
118 |
119 | .hxtool_alerts_filter th:nth-child(3) {
120 | width: 400px;
121 | }
122 |
123 | .hxtool_alerts_filter th:nth-child(4) {
124 | width: 150px;
125 | }
126 |
127 | .hxtool_alerts_filter th:nth-child(5) {
128 | width: 150px;
129 | }
130 |
131 |
132 | /* Dashboard grid table */
133 |
134 | .hxtool_table_dashboard {
135 | width: 100%;
136 | }
137 |
138 | .hxtool_table_dashboard td {
139 | padding: 5px;
140 | vertical-align: top;
141 | }
142 |
143 | .auditFilter:hover {
144 | background: rgba(255, 255, 255, 0.2);
145 | cursor: pointer;
146 | }
147 |
148 | .auditFilterContainer {
149 | width: 200px;
150 | margin-top: 4px;
151 | z-index: 999;
152 | padding: 10px;
153 | position: absolute;
154 | display: none;
155 | background: #49515d;
156 | border: 1px solid #31363d;
157 | border-radius: 3px;
158 | }
159 |
160 | .auditFilterDropdownChild {
161 | width: 100%;
162 | display: block;
163 | color: #0fb8dc;
164 | text-align: left;
165 | background: #49515d;
166 | border: 0;
167 | padding-bottom: 10px;
168 | padding-top: 10px;
169 | }
170 |
171 | .auditFilterDropdownChild:hover {
172 | background: rgba(0, 0, 0, 0.6);
173 | color: #66ebff !important;
174 | }
--------------------------------------------------------------------------------
/hxtool_task_modules/streaming_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import socket
5 | import os
6 | import json
7 |
8 | import hxtool_global
9 | from .task_module import *
10 | from hx_audit import *
11 |
12 | class streaming_task_module(task_module):
13 | def __init__(self, parent_task):
14 | super(type(self), self).__init__(parent_task)
15 |
16 | @staticmethod
17 | def input_args():
18 | return [
19 | {
20 | 'name' : 'host_name',
21 | 'type' : str,
22 | 'required' : True,
23 | 'user_supplied' : False,
24 | 'description' : "The host name belonging to the bulk acquisition package."
25 | },
26 | {
27 | 'name' : 'agent_id',
28 | 'type' : str,
29 | 'required' : False,
30 | 'user_supplied' : False,
31 | 'description' : "The host/agent ID of the bulk acquisition to download."
32 | },
33 | {
34 | 'name' : 'bulk_download_path',
35 | 'type' : str,
36 | 'required' : True,
37 | 'user_supplied' : False,
38 | 'description' : "The fully qualified path to the bulk acquisition package."
39 | },
40 | {
41 | 'name' : 'bulk_acquisition_id',
42 | 'type' : int,
43 | 'required' : True,
44 | 'description' : "The bulk acquisition ID assigned to the bulk acquisition job by the controller."
45 | },
46 | {
47 | 'name' : 'batch_mode',
48 | 'type' : bool,
49 | 'required' : False,
50 | 'user_supplied' : True,
51 | 'description' : "Flag whether to batch each audit as single JSON object versus sending each record as a separate object. Defaults to False"
52 | },
53 | {
54 | 'name' : 'delete_bulk_download',
55 | 'type' : bool,
56 | 'required' : False,
57 | 'user_supplied' : True,
58 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
59 | },
60 | {
61 | 'name' : 'stream_protocol',
62 | 'type' : str,
63 | 'required' : False,
64 | 'user_supplied' : True,
65 | 'description' : "The protocol to use when streaming. Defaults to TCP"
66 | },
67 | {
68 | 'name' : 'stream_host',
69 | 'type' : str,
70 | 'required' : True,
71 | 'user_supplied' : True,
72 | 'description' : "The FQDN or IP address of the host to stream to."
73 | },
74 | {
75 | 'name' : 'stream_port',
76 | 'type' : int,
77 | 'required' : True,
78 | 'user_supplied' : True,
79 | 'description' : "The port on which to stream to."
80 | }
81 |
82 | ]
83 |
84 | @staticmethod
85 | def output_args():
86 | return []
87 |
88 | def run(self, host_name = None, agent_id = None, bulk_download_path = None, bulk_acquisition_id = None, batch_mode = False, delete_bulk_download = False, stream_host = None, stream_port = None, stream_protocol = 'tcp'):
89 | try:
90 | ret = False
91 | if bulk_download_path:
92 |
93 | socket_type = socket.SOCK_STREAM
94 | if stream_protocol == 'udp':
95 | socket_type = socket.SOCK_DGRAM
96 |
97 | for res in socket.getaddrinfo(stream_host, int(stream_port), socket.AF_UNSPEC, socket_type):
98 | address_family, socktype, proto, canonname, sockaddr = res
99 |
100 | stream_socket = socket.socket(address_family, socktype, proto)
101 |
102 | stream_socket.connect(sockaddr)
103 |
104 | for audit_object in self.yield_audit_results(bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id):
105 | stream_socket.sendall(json.dumps(audit_object, sort_keys = False).encode('utf-8') + '\n'.encode('utf-8'))
106 |
107 | stream_socket.close()
108 |
109 | ret = True
110 |
111 | if ret and delete_bulk_download:
112 | os.remove(os.path.realpath(bulk_download_path))
113 |
114 | else:
115 | self.logger.error("bulk_download_path is empty!")
116 |
117 | return(ret, None)
118 | except Exception as e:
119 | self.logger.error(pretty_exceptions(e))
120 | return(False, None)
--------------------------------------------------------------------------------
/hxtool_task_modules/helix_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import socket
5 | import os
6 | import json
7 | import time
8 | import tempfile
9 | import gzip
10 |
11 | import requests
12 |
13 | import hxtool_global
14 | from .task_module import *
15 | from hx_audit import *
16 |
17 | class helix_task_module(task_module):
18 | def __init__(self, parent_task):
19 | super(type(self), self).__init__(parent_task)
20 |
21 | @staticmethod
22 | def input_args():
23 | return [
24 | {
25 | 'name' : 'host_name',
26 | 'type' : str,
27 | 'required' : True,
28 | 'user_supplied' : False,
29 | 'description' : "The host name belonging to the bulk acquisition package."
30 | },
31 | {
32 | 'name' : 'agent_id',
33 | 'type' : str,
34 | 'required' : False,
35 | 'user_supplied' : False,
36 | 'description' : "The host/agent ID of the bulk acquisition to download."
37 | },
38 | {
39 | 'name' : 'bulk_download_path',
40 | 'type' : str,
41 | 'required' : True,
42 | 'user_supplied' : False,
43 | 'description' : "The fully qualified path to the bulk acquisition package."
44 | },
45 | {
46 | 'name' : 'bulk_acquisition_id',
47 | 'type' : int,
48 | 'required' : True,
49 | 'description' : "The bulk acquisition ID assigned to the bulk acquisition job by the controller."
50 | },
51 | {
52 | 'name' : 'delete_bulk_download',
53 | 'type' : bool,
54 | 'required' : False,
55 | 'user_supplied' : True,
56 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
57 | },
58 | {
59 | 'name' : 'apikey',
60 | 'type' : str,
61 | 'required' : True,
62 | 'user_supplied' : True,
63 | 'description' : "The API key for uploading"
64 | },
65 | {
66 | 'name' : 'url',
67 | 'type' : str,
68 | 'required' : True,
69 | 'user_supplied' : True,
70 | 'description' : "The URL to which the upload is sent"
71 | }
72 |
73 | ]
74 |
75 | @staticmethod
76 | def output_args():
77 | return []
78 |
79 | def _write_fh(self, gz_fh, bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id=None):
80 | gz = gzip.GzipFile(fileobj=gz_fh, mode='wb')
81 | for audit_object in self.yield_audit_results(bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id):
82 | gz.write(json.dumps(audit_object, sort_keys = False).encode('utf-8') + '\n'.encode('utf-8'))
83 | gz.close()
84 | gz_fh.seek(0)
85 |
86 | def run(self, host_name = None, agent_id = None, bulk_download_path = None, bulk_acquisition_id = None, batch_mode = False, delete_bulk_download = False, apikey = None, url = None):
87 | try:
88 | if not bulk_download_path:
89 | self.logger.error("bulk_download_path is empty!")
90 | return (False, None)
91 |
92 | resp = requests.post(url, headers={"x-api-key": apikey}, data={"host_name": host_name, "agent_id": agent_id, "bulk_acquisition_id": bulk_acquisition_id})
93 | if not resp:
94 | raise Exception("Unable to get upload link from URL {}: {}".format(url, resp))
95 | resp = resp.json()
96 | self.logger.debug("Uploading id {} from {} to {}".format(bulk_acquisition_id, bulk_download_path, resp["url"]))
97 |
98 | start = time.time()
99 | with tempfile.TemporaryFile(mode='r+b') as gz_fh:
100 | self._write_fh(gz_fh, bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id)
101 | resp = requests.post(resp["url"], data=resp["fields"], files={"file": (str(time.time()), gz_fh)})
102 | if not resp:
103 | raise Exception("Unable to upload: {} {}".format(resp, resp.text))
104 | self.logger.info("Uploaded id {} in {}".format(bulk_acquisition_id, (time.time() - start)))
105 | if delete_bulk_download:
106 | os.remove(os.path.realpath(bulk_download_path))
107 | return(True, None)
108 | except Exception as e:
109 | self.logger.error(pretty_exceptions(e))
110 | return(False, None)
--------------------------------------------------------------------------------
/static/css/buttons.jqueryui.min.css:
--------------------------------------------------------------------------------
1 | @keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-buttons{position:relative;float:left}div.dt-buttons .dt-button{margin-right:0}div.dt-buttons .dt-button span.ui-icon{display:inline-block;vertical-align:middle;margin-top:-2px}div.dt-buttons .dt-button:active{outline:none}div.dt-buttons .dt-button:hover>span{background-color:rgba(0,0,0,0.05)}div.dt-button-collection{position:absolute;top:0;left:0;width:150px;margin-top:3px;padding:8px 8px 4px 8px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.4);background-color:#f3f3f3;background-color:rgba(255,255,255,0.3);overflow:hidden;z-index:2002;border-radius:5px;box-shadow:3px 3px 5px rgba(0,0,0,0.3);z-index:2002;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px;-webkit-column-gap:0;-moz-column-gap:0;-ms-column-gap:0;-o-column-gap:0;column-gap:0}div.dt-button-collection .dt-button{position:relative;left:0;right:0;display:block;float:none;margin-right:0}div.dt-button-collection .dt-button:last-child{margin-bottom:4px}div.dt-button-collection .dt-button:hover>span{background-color:rgba(0,0,0,0.05)}div.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}div.dt-button-collection.fixed.two-column{margin-left:-150px}div.dt-button-collection.fixed.three-column{margin-left:-225px}div.dt-button-collection.fixed.four-column{margin-left:-300px}div.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}div.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}div.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}div.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);background:-ms-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-moz-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-o-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0,0,0,0.3)), color-stop(1, rgba(0,0,0,0.7)));background:-webkit-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:radial-gradient(ellipse farthest-corner at center, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);z-index:2001}@media screen and (max-width: 640px){div.dt-buttons{float:none !important;text-align:center}}button.dt-button.processing,div.dt-button.processing,a.dt-button.processing{color:rgba(0,0,0,0.2)}button.dt-button.processing:after,div.dt-button.processing:after,a.dt-button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
2 |
--------------------------------------------------------------------------------
/templates/ht_scheduler.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Scheduler{% endblock %}
3 | {% block navlocation %}Scheduler{% endblock %}
4 | {% block content %}
5 |
6 |
107 |
108 | {{ htPanelNoHeader.widgetHeader(panelDisplay="inline-block") }}
109 |
110 | {{ htPanelNoHeader.widgetFooter() }}
111 |
112 | {{ htPanel.widgetHeader("Scheduler tasks", panelIcon="fa-table") }}
113 |
114 | {{ htPanel.widgetFooter() }}
115 |
116 | {% endblock %}
117 |
--------------------------------------------------------------------------------
/static/fontawesome-free-5.7.2-web/css/svg-with-js.min.css:
--------------------------------------------------------------------------------
1 | .svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;transform:translate(-50%,-50%);transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;transform:scale(.25);transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;transform:scale(.25);transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;transform:scale(.25);transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;transform:scale(.25);transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;transform:scale(.25);transform-origin:top left}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:fa-spin 2s infinite linear}.fa-pulse{animation:fa-spin 1s infinite steps(8)}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}
--------------------------------------------------------------------------------
/hxtool_task_modules/x15_postgres_task_module.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import json
5 | try:
6 | from io import StringIO
7 | except ModuleNotFoundError:
8 | from cStringIO import StringIO
9 |
10 | import hxtool_global
11 | from .task_module import *
12 | from hx_audit import *
13 | from hxtool_util import *
14 |
15 | class x15_postgres_task_module(task_module):
16 | def __init__(self, parent_task):
17 | super(type(self), self).__init__(parent_task)
18 |
19 | @staticmethod
20 | def input_args():
21 | return [
22 | {
23 | 'name' : 'host_name',
24 | 'type' : str,
25 | 'required' : True,
26 | 'user_supplied' : False,
27 | 'description' : "The host name belonging to the bulk acquisition package."
28 | },
29 | {
30 | 'name' : 'agent_id',
31 | 'type' : str,
32 | 'required' : False,
33 | 'user_supplied' : False,
34 | 'description' : "The host/agent ID of the bulk acquisition to download."
35 | },
36 | {
37 | 'name' : 'bulk_download_path',
38 | 'type' : str,
39 | 'required' : True,
40 | 'user_supplied' : False,
41 | 'description' : "The fully qualified path to the bulk acquisition package."
42 | },
43 | {
44 | 'name' : 'bulk_acquisition_id',
45 | 'type' : int,
46 | 'required' : True,
47 | 'description' : "The bulk acquisition ID assigned to the bulk acquisition job by the controller."
48 | },
49 | {
50 | 'name' : 'batch_mode',
51 | 'type' : bool,
52 | 'required' : False,
53 | 'user_supplied' : True,
54 | 'description' : "Flag whether to batch each audit as single JSON object versus sending each record as a separate object. Defaults to False"
55 | },
56 | {
57 | 'name' : 'delete_bulk_download',
58 | 'type' : bool,
59 | 'required' : False,
60 | 'user_supplied' : True,
61 | 'description' : "Flag whether to delete the bulk acquisition package locally once complete. Defaults to False"
62 | },
63 | {
64 | 'name' : 'x15_host',
65 | 'type' : str,
66 | 'required' : True,
67 | 'user_supplied' : True,
68 | 'description' : "The IP address or fully qualified domain name of the X15 server."
69 | },
70 | {
71 | 'name' : 'x15_port',
72 | 'type' : int,
73 | 'required' : True,
74 | 'user_supplied' : True,
75 | 'description' : "The Postgres port on the X15 server."
76 | },
77 | {
78 | 'name' : 'x15_user',
79 | 'type' : str,
80 | 'required' : True,
81 | 'user_supplied' : True,
82 | 'description' : "The username with which to authenticate to the X15 server."
83 | },
84 | {
85 | 'name' : 'x15_password',
86 | 'type' : str,
87 | 'required' : True,
88 | 'user_supplied' : True,
89 | 'description' : "The password with which to authenticate to the X15 server."
90 | },
91 | {
92 | 'name' : 'x15_database',
93 | 'type' : str,
94 | 'required' : True,
95 | 'user_supplied' : True,
96 | 'description' : "The database to utilize on the X15 server."
97 | },
98 | {
99 | 'name' : 'x15_table',
100 | 'type' : str,
101 | 'required' : True,
102 | 'user_supplied' : True,
103 | 'description' : "The table in the database to utilize."
104 | }
105 | ]
106 |
107 | @staticmethod
108 | def output_args():
109 | return []
110 |
111 | def run(self, host_name = None, agent_id = None, bulk_download_path = None, bulk_acquisition_id = None, batch_mode = False, delete_bulk_download = False, x15_host = None, x15_port = None, x15_user = None, x15_password = None, x15_database = None, x15_table = None):
112 |
113 | ret = False
114 | result = {}
115 | try:
116 | import psycopg2
117 |
118 | if bulk_download_path:
119 | x15_connection_string = "host={} port={} dbname={} user={} password={}".format(x15_host, x15_port, x15_database, x15_user, x15_password)
120 | x15_connection = psycopg2.connect(x15_connection_string)
121 | x15_cursor = x15_connection.cursor()
122 | x15_query = "COPY {} from stdin".format(x15_table)
123 |
124 | for audit_object in self.yield_audit_results(bulk_download_path, batch_mode, host_name, agent_id, bulk_acquisition_id = bulk_acquisition_id):
125 | buffer = StringIO()
126 | json.dump(audit_object, buffer)
127 | buffer.seek(0)
128 | x15_cursor.copy_expert(x15_query, buffer, size=16384)
129 |
130 | x15_connection.commit()
131 | x15_connection.close()
132 |
133 | ret = True
134 | if ret and delete_bulk_download:
135 | os.remove(os.path.realpath(bulk_download_path))
136 |
137 | else:
138 | self.logger.error("bulk_download_path is empty!")
139 | except Exception as e:
140 | self.logger.error(pretty_exceptions(e))
141 | finally:
142 | return(ret, result)
--------------------------------------------------------------------------------
/hxtool_config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import json
5 | import logging
6 | from os import path
7 | import sys, logging, logging.handlers, socket
8 |
9 | import hxtool_logging
10 | from hxtool_util import combine_app_path
11 |
12 | logger = hxtool_logging.getLogger(__name__)
13 |
14 | class hxtool_config:
15 | """
16 | Default hard coded config
17 | """
18 | DEFAULT_CONFIG = {
19 | 'log_handlers' : {
20 | 'rotating_file_handler' : {
21 | 'file' : 'log/hxtool.log',
22 | 'max_bytes' : 5000000,
23 | 'backup_count' : 5,
24 | 'level' : 'info',
25 | 'format' : '[%(asctime)s] {%(module)s} {%(threadName)s} %(levelname)s - %(message)s'
26 | }
27 | },
28 | 'network' : {
29 | 'ssl' : 'enabled',
30 | 'port' : 8080,
31 | 'listen_address' : '0.0.0.0',
32 | 'session_timeout' : 30
33 | },
34 | 'ssl' : {
35 | 'cert' : 'hxtool.crt',
36 | 'key' : 'hxtool.key'
37 | },
38 | 'scheduler' : {
39 | 'thread_count' : None,
40 | 'defer_interval' : 30
41 | },
42 | 'headers' : {
43 | },
44 | 'cookies' : {
45 | }
46 | }
47 |
48 | LOG_LEVELS = {
49 | 'debug' : logging.DEBUG,
50 | 'info' : logging.INFO,
51 | 'warning' : logging.WARNING,
52 | 'error' : logging.ERROR,
53 | 'critical' : logging.CRITICAL
54 | }
55 |
56 | def __init__(self, config_file):
57 |
58 | logger.info('Reading configuration file %s', config_file)
59 | if path.isfile(config_file):
60 | with open(config_file, 'r') as config_file_handle:
61 | self._config = json.load(config_file_handle)
62 | logger.info('Checking configuration file %s', config_file)
63 | if not {'log_handlers', 'network', 'ssl', 'scheduler'} <= set(self._config.keys()):
64 | raise ValueError('Configuration file is missing key elements!')
65 | else:
66 | logger.info('Configuration file %s is OK.', config_file)
67 |
68 | if 'proxies' in self._config['network']:
69 | if len(list(filter(lambda x: x == 'http' or x == 'https' or x == 'use_pac' or x == 'pac_url', self._config['network']['proxies']))) == 0:
70 | logger.warning("Ignoring invalid proxy configuration! Please see http://docs.python-requests.org/en/master/user/advanced/")
71 | del self._config['network']['proxies']
72 | else:
73 | logger.warning('Unable to open config file: %s, loading default config.', config_file)
74 | self._config = self.DEFAULT_CONFIG
75 |
76 | def __getitem__(self, key, default = None):
77 | v = self._config.get(key)
78 | if not v:
79 | v = default
80 | return v
81 |
82 | def get_child_item(self, parent_key, child_key, default = None):
83 | try:
84 | if self[parent_key] is not None:
85 | return self[parent_key].get(child_key, default)
86 | except TypeError:
87 | return default
88 |
89 | def get_config(self):
90 | return self._config
91 |
92 | def log_handlers(self):
93 | for handler_name in self._config['log_handlers']:
94 | if handler_name == 'rotating_file_handler':
95 | handler_config = self._config['log_handlers'][handler_name]
96 | if 'file' in handler_config:
97 | h = logging.handlers.RotatingFileHandler(combine_app_path(handler_config['file']))
98 |
99 | if 'max_bytes' in handler_config:
100 | h.maxBytes = handler_config['max_bytes']
101 | if 'backup_count' in handler_config:
102 | h.backupCount = handler_config['backup_count']
103 |
104 | self._set_level_and_format(handler_config, h)
105 | yield(h)
106 |
107 | elif handler_name == 'syslog_handler':
108 | handler_config = self._config['log_handlers'][handler_name]
109 |
110 | syslog_address = '127.0.0.1'
111 | syslog_port = logging.handlers.SYSLOG_UDP_PORT
112 | if 'address' in handler_config:
113 | syslog_address = handler_config['address']
114 | if 'port' in handler_config and 0 < handler_config['port'] < 65535:
115 | syslog_port = handler_config['port']
116 |
117 | facility = logging.handlers.SysLogHandler.LOG_USER
118 | if 'facility' in handler_config:
119 | facility = logging.handlers.SysLogHandler.facility_names.get(handler_config['facility'])
120 |
121 | socket_type = socket.SOCK_DGRAM
122 | if 'protocol' in handler_config and handler_config['protocol'].lower() == 'tcp':
123 | socket_type = socket.SOCK_STREAM
124 |
125 | h = logging.handlers.SysLogHandler(address = (syslog_address, syslog_port), facility = facility, socktype = socket_type)
126 |
127 | self._set_level_and_format(handler_config, h)
128 | yield(h)
129 |
130 | def _set_level_and_format(self, handler_config, handler):
131 | level = logging.WARNING
132 | if 'level' in handler_config:
133 | level = self.LOG_LEVELS.get(handler_config['level'].lower())
134 |
135 | handler.setLevel(level)
136 |
137 | if 'format' in handler_config:
138 | handler.setFormatter(logging.Formatter(handler_config['format']))
139 |
--------------------------------------------------------------------------------
/hxtool_session.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from werkzeug.datastructures import CallbackDict
5 | from flask.sessions import SessionInterface, SessionMixin
6 | import os
7 | import hmac
8 | import hashlib
9 | import threading
10 | import datetime
11 |
12 | import hxtool_global
13 | import hxtool_logging
14 | from hx_lib import *
15 | from hxtool_scheduler_task import hxtool_scheduler_task
16 |
17 | logger = hxtool_logging.getLogger(__name__)
18 |
19 | class hxtool_session(CallbackDict, SessionMixin):
20 | def __init__(self, app_secret):
21 | def on_update(self):
22 | if self.accessed == False:
23 | self.modified = True
24 |
25 | self.secret = app_secret
26 | self.id = None
27 | self.new = True
28 | self.accessed = False
29 | self.modified = False
30 | self.permanent = True
31 | CallbackDict.__init__(self, on_update=on_update)
32 |
33 | def create(self):
34 | self.id = str(hmac.new(self.secret, os.urandom(32), digestmod=hashlib.sha256).hexdigest())
35 |
36 | def load(self, id, session_record):
37 | if session_record is not None:
38 | logger.debug("Loading saved session data.")
39 | # Set accessed to True for set/update so we don't loop into on_update()
40 | self.accessed = True
41 | # Explicitly set modified to False
42 | self.modified = False
43 | self.id = id
44 | self.update(session_record['session_data'])
45 | self.accessed = False
46 |
47 | # expiration_delta is in minutes
48 | class hxtool_session_interface(SessionInterface):
49 | def __init__(self, app, expiration_delta=30):
50 | self.session_cache = {}
51 | self.expiration_delta = expiration_delta
52 |
53 | # Schedule session_reaper
54 | session_reaper_task = hxtool_scheduler_task("System", "Session Reaper", immutable=True)
55 | session_reaper_task.set_schedule(minutes=30)
56 | session_reaper_task.add_step(self, "session_reaper", args = (app,))
57 | hxtool_global.hxtool_scheduler.add(session_reaper_task)
58 |
59 | def get_expiration_time(self, app, session):
60 | delta = datetime.timedelta(minutes=self.expiration_delta)
61 | if session.permanent:
62 | delta = app.permanent_session_lifetime
63 | return datetime.datetime.utcnow() + delta
64 |
65 | def open_session(self, app, request):
66 | session = hxtool_session(app.secret_key)
67 |
68 | session_id = request.cookies.get(app.config['SESSION_COOKIE_NAME'])
69 | if session_id:
70 | cached_session = self.session_cache.get(session_id)
71 | if not cached_session:
72 | session_record = hxtool_global.hxtool_db.sessionGet(session_id)
73 | if session_record is not None:
74 | session.load(session_id, session_record)
75 | logger.debug("We have an existing database session with id: {0}".format(session.id))
76 | else:
77 | session = cached_session
78 | logger.debug("We have an existing cached session with id: {0}".format(session.id))
79 |
80 |
81 | return session
82 |
83 | def save_session(self, app, session, response):
84 | cookie_domain = self.get_cookie_domain(app)
85 | if not session:
86 | if not session.new:
87 | self.delete_session(app, session.id)
88 | if session.modified:
89 | response.delete_cookie(app.config['SESSION_COOKIE_NAME'], domain=cookie_domain)
90 | return
91 |
92 | if not self.should_set_cookie(app, session):
93 | return
94 |
95 | if session.new:
96 | session.create()
97 | hxtool_global.hxtool_db.sessionCreate(session.id)
98 | logger.debug("Created a new session with id: {0}".format(session.id))
99 | session.new = False
100 |
101 | logger.debug("Saving session with id: {0}".format(session.id))
102 | hxtool_global.hxtool_db.sessionUpdate(session.id, session)
103 | session.modified = False
104 |
105 | self.session_cache[session.id] = session
106 |
107 | cookie_path = self.get_cookie_path(app)
108 | http_only = self.get_cookie_httponly(app)
109 | secure = self.get_cookie_secure(app)
110 | response.set_cookie(app.config['SESSION_COOKIE_NAME'], session.id, expires=self.get_expiration_time(app, session), path=cookie_path, httponly=http_only, secure=secure, domain=cookie_domain)
111 |
112 | def delete_session(self, app, session_id):
113 | logger.debug("Deleting session with id: {0}".format(session_id))
114 | hxtool_global.hxtool_db.sessionDelete(session_id)
115 | if session_id in self.session_cache:
116 | del self.session_cache[session_id]
117 |
118 | def session_reaper(self, app):
119 | logger.debug("session_reaper() called.")
120 | for s in hxtool_global.hxtool_db.sessionList():
121 | if not s['update_timestamp'] or (datetime.datetime.utcnow() - HXAPI.dt_from_str(s['update_timestamp'])) >= (app.permanent_session_lifetime or datetime.timedelta(minutes=self.expiration_delta)):
122 | logger.debug("Deleting session id: {} with update_timestamp: {}".format(s['session_id'], s['update_timestamp']))
123 | self.delete_session(app, s['session_id'])
124 | return True
--------------------------------------------------------------------------------
/static/hxtool-js/hxtool-doc-ready.js:
--------------------------------------------------------------------------------
1 | function collapse_all_dropdowns() {
2 | $(".fe-dropdown__list-container").each(function() {
3 | $(this).css("opacity", 0);
4 | $(this).hide();
5 | });
6 | }
7 |
8 | function hxtool_doc_ready() {
9 |
10 | /* Global stuff */
11 |
12 | // Set the background to proper gradient size depending on browser width
13 | // var myGradient = "radial-gradient(" + Math.round($( window ).width() * 0.52) + "px at 50% 0%, #355881 0%, #222 100%)";
14 | // $("body").css({ "background": myGradient });
15 |
16 | $(document).click(function(e) {
17 | // Collapse all top navbar dropdowns
18 | $(".hxtool_topnav_dropdown").hide(100);
19 |
20 | // Collapse all drop-down menus
21 | collapse_all_dropdowns();
22 |
23 | e.stopPropagation();
24 | });
25 |
26 | $("#hxtoolMessageCancel").click(function(e) {
27 | $("#hxtoolMessage").hide();
28 | e.stopPropagation();
29 | });
30 |
31 | /* TOP NAV BAR */
32 | $(".hxtool_topnav_mainbutton").click(function(e) {
33 | if($(this).attr("data-link") !== undefined) {
34 | window.location.href = $(this).attr('data-link');
35 | }
36 | else {
37 | $(".hxtool_topnav_dropdown").hide(100);
38 | $(this).next("div").show(100);
39 | }
40 | e.stopPropagation();
41 | });
42 |
43 | $("#hxtool_topnavSearch").click(function(e) {
44 | myWidth = $("#hxtool_topnavSearch").closest("div").width();
45 |
46 | if ($("#hxtool_topnavSearch").data("clicked") == false) {
47 | $("#hxtool_topnavSearch").closest("div").animate({
48 | width: myWidth + 235
49 | }, 200, function() {
50 | $("#hxtool_topnav_left_container-search").show();
51 | $("#hxtool_topnavSearch").data("clicked", true);
52 | $("#hxtool_global_search").focus();
53 | });
54 | }
55 | else {
56 | $("#hxtool_topnav_left_container-search").hide();
57 | $("#hxtool_topnavSearch").closest("div").animate({
58 | width: myWidth - 235
59 | }, 200, function() {
60 | $("#hxtool_topnavSearch").data("clicked", false);
61 | });
62 | }
63 | e.stopPropagation();
64 | });
65 |
66 | $("#hxtool_global_search").keypress(function (e) {
67 | var key = e.which;
68 | if(key == 13) {
69 | location.href = "/hostsearch?q=" + $("#hxtool_global_search").val();
70 | }
71 | });
72 |
73 | $(".hxtool_topnav_dropdown_child").click(function(e) {
74 | window.location.href = $(this).attr('data-link');
75 | e.stopPropagation();
76 | });
77 |
78 | $("#hxtoolLogout").click(function(e) {
79 | window.location.href = "/logout"
80 | e.stopPropagation();
81 | });
82 |
83 | /* Panel */
84 |
85 | // show/hide panel
86 | $(".hxtool-panel-toggle").click(function(e) {
87 | if ($(this).closest("div").next("div").css("display") == "none") {
88 | $(this).closest("div").next("div").show(200);
89 | }
90 | else {
91 | $(this).closest("div").next("div").hide(200);
92 | }
93 | });
94 |
95 | /* DROP DOWN MENUS */
96 | $(document).on("click", ".fe-dropdown", function(e) {
97 | collapse_all_dropdowns();
98 | $(this).find("div").show();
99 | $(this).find("div").fadeTo( "fast" , 1);
100 | e.stopPropagation();
101 | });
102 |
103 | $(document).on("click", ".fe-dropdown__item-link", function(e) {
104 | $(this).closest("div").parent().find("button").html($(this).find(".fe-dropdown__item-link-text").html() + " ");
105 | $(this).closest("div").parent().find("button").data("id", $(this).find(".fe-dropdown__item-link-text").data("id") );
106 | $(this).closest("div").fadeTo( "fast", 0, function() {
107 | $(".fe-dropdown__list-container").hide();
108 | });
109 |
110 | e.stopPropagation();
111 | });
112 |
113 | /* MODAL */
114 | $(".fe-modal-close").click(function(){
115 | $(this).closest("div").parent().parent().parent().parent().hide();
116 | });
117 |
118 | /* Detects when OS scaling is active and resizes HXTool to avoid it, doesn't work in FF */
119 | if (window.devicePixelRatio !== 1 && screen.width <= 1920) {
120 | console.log("HXTool: OS Scaling active. Enforcing HXTool scaling");
121 | let scaleValue = (1/window.devicePixelRatio);
122 | $(document.body).css('zoom',scaleValue);
123 | var myNewHeight = (window.innerHeight * window.devicePixelRatio);
124 | $(".hxtool5_container").css('min-height',myNewHeight);
125 | $(".hxtool5_container").css('max-height',myNewHeight);
126 | $(".hxtool5_container").css('height',myNewHeight);
127 | $(".hxtool5_content").css('min-height',myNewHeight - 60);
128 | $(".hxtool5_content").css('max-height',myNewHeight - 60);
129 | $(".hxtool5_content").css('height',myNewHeight - 60);
130 | $(".panelAlertsClass").css('height',myNewHeight - 290);
131 | $(".panelContentClass").css('height',myNewHeight - 290);
132 | $(".panelAcqClass").css('height',myNewHeight - 290);
133 | $(".hxtool_panel_stackinganalyze").css('min-height',myNewHeight - 190);
134 | $(".hxtool_panel_scriptbuilder").css('height',myNewHeight - 120);
135 | $(".hxtool_scriptbuilder_scriptarea").css('height',myNewHeight - 450);
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/templates/ht_categories.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}HXTool - Categories{% endblock %}
3 | {% block navlocation %}Manage Categories{% endblock %}
4 | {% block content %}
5 |
6 |
71 |
72 | {{ htPanelNoHeader.widgetHeader(panelDisplay="inline-block") }}
73 | Create new category
74 | {{ htPanelNoHeader.widgetFooter() }}
75 |
76 | {{ htPanel.widgetHeader("Rule categories", panelId="categoryTableContainer", panelIcon="fa-table") }}
77 |
78 | {{ htPanel.widgetFooter() }}
79 |
80 |
81 | {{ htModal.widgetHeader("Create new category", modalId="categoryNewPopup", modalSize="medium", modalOverflow="true") }}
82 |
83 |
84 | Enter a name for your new category
85 |
86 |
87 | {{ htDropdown.widgetHeader("Select a policy", "retention_policy", "false") }}
88 | {{ htDropdown.widgetItem("manual", "manual", elementIcon="fa-check") }}
89 | {{ htDropdown.widgetItem("auto", "auto", elementIcon="fa-check") }}
90 | {{ htDropdown.widgetItem("intel", "intel", elementIcon="fa-check") }}
91 | {{ htDropdown.widgetFooter() }}
92 |
93 |
94 |
95 | {{ htDropdown.widgetHeader("Select a policy", "edit_policy", "false") }}
96 | {{ htDropdown.widgetItem("full", "full", elementIcon="fa-check") }}
97 | {{ htDropdown.widgetItem("edit_delete", "edit_delete", elementIcon="fa-check") }}
98 | {{ htDropdown.widgetItem("delete", "delete", elementIcon="fa-check") }}
99 | {{ htDropdown.widgetItem("read-only", "read-only", elementIcon="fa-check") }}
100 | {{ htDropdown.widgetFooter() }}
101 |
102 | {{ htModal.widgetMiddle() }}
103 | Cancel
104 | Submit
105 | {{ htModal.widgetFooter() }}
106 |
107 | {% endblock %}
108 |
--------------------------------------------------------------------------------
/README.CONFIG:
--------------------------------------------------------------------------------
1 | The HXTool configuration lives in conf.json, and is/should be well formatted JSON.
2 | What follows is a description of the available configuration elements.
3 |
4 | 1. "log_handlers" # You can have as many handlers in this section as you'd like.
5 | - "handler type" : { .. configuration options .. }
6 | - Valid handler types are: "rotating_file_handler" and "syslog_handler"
7 | - Valid options for both handlers:
8 | - "level" : "string; optional; The name of the logging level to use. Valid values are debug, info, warning, error and critical. Defaults to warning"
9 | - "format" : "string; optiona; The logging entry format to use when writing to this log. See https://docs.python.org/2/howto/logging.html#formatters for valid options.
10 | - Valid options for "rotating_file_handler": # See https://docs.python.org/2/library/logging.handlers.html#logging.handlers.RotatingFileHandler
11 | - "file" : "string; required; The path and file name that the log will be written to, relative paths are allowed."
12 | - "max_bytes" : long integer; optional; The file size threshold of which the file will be rolled over and a new log file created.
13 | - "backup_count" : integer; optional; The number of previous (rolled over) log files to retain.
14 | - Valid options for "syslog_handler": # See https://docs.python.org/2/library/logging.handlers.html#sysloghandler
15 | - "address" : "string; optional; The fully qualified domain name(FQDN) or IP address of the logging target. Defaults to 127.0.0.1"
16 | - "port" : integer; optional; The port with which to connect to the logging target on. Defaults to 514
17 | - "facility" : "string; optional; The name of the logging facility to use. Defaults to LOG_USER, see the above link for valid names."
18 | - "protocol" : "string; optional; The protocol with which to communicate with the logging target. Valid values are tcp or udp. Defaults to udp"
19 |
20 | 2. "network"
21 | - "ssl" : "string; required; Enable or disable SSL/TLS for the HXTool web interface. Valid values are enabled or disabled. Defaults to enabled."
22 | - "listen_address" : "string; required; The IP address with which the HXTool web interface listens on. Defaults to 0.0.0.0 (any)."
23 | - "port" : integer; required; The port with which the HXTool web interface listens on. Defaults to 8080
24 | - "session_timeout" : integer; optional; Unused (at the moment)
25 | - "proxies" : { .. "http" or "https" .. } # Note: only HTTPS will be used, and only the first entry
26 | - "https" : "string; optional; The fully qualified URN of the proxy to use when communicating with the HX controller. Valid values are https://user:password@host:port or socks5://user:password@host:port"
27 |
28 | 3. "ssl"
29 | - "cert" : "string; required if ssl is enabled in network; The path to the SSL certificate file."
30 | - "key" : "string; required if ssl is enabled in network; The path to the SSL certificate key file."
31 |
32 | 4. "headers" : { "name" : "value" .. }
33 | - "name" : "value" - string; optional; The name and value of any headers to add to any API request made to the HX controller. You can add as many as you'd like.
34 |
35 | 5. "cookies" : { "name" : "value" .. }
36 | - "name" : "value" - string; optional; The name and value of any cookies to add to any API request made to the HX controller. You can add as many as you'd like.
37 |
38 | 6 "scheduler" - Used by the scheduler.
39 | - "thread_count" : value - integer; required; The number of threads to be used by the scheduler. Defaults to null, which means the scheduler will use the number of CPUs in the system plus 1.
40 | - "defer_interval" : value - integer; required; The number of seconds the scheduler will use as a base to defer a task, i.e. bulk acquisition that hasn't completed yet.
41 |
42 | 7. "apicache" (requires background credentials set)
43 | - "enabled" : "boolean; required; Enables and disables the API cache in TinyDB"
44 | - "fetcher_interval" : "integer; number of seconds between each attempt to get new data from HX"
45 | - "updater_interval" : "integer; number of seconds between each attempt to update dirty cache records"
46 | - "objects_per_poll" : "integer; number of new objects that will be transferred for each attempt"
47 | - "max_refresh_per_run" : "integer; number of dirty objects that will be updated each attempt to update"
48 | - "refresh_interval" : "integer; age (seconds) when an object is considered to be dirty"
49 |
50 | 8. "db" (right now only for MongoDB usage)
51 | - "type" : "string; required; only acceptable value is mongodb"
52 | - "host" : "string; required; IP or FQDN of the database server"
53 | - "port" : "integer; optional; the port with which to contact the database server on, defaults vary by database type"
54 | - "user" : "string; required; username with which to authenticate with"
55 | - "password" : "string; required; password with which to authenticate with"
56 | - "auth_source" : "string; required; MongoDB only, authentication source database"
57 | - "auth_mechanism" : "string; optional; MongoDB only, the authentication mechanism to use, defaults to SCRAM-SHA-256"
58 | - "db_name" : "string; optional; The name of the database to use, defaults to hxtool"
--------------------------------------------------------------------------------