├── .github ├── labeler.yml ├── release-drafter.yml └── workflows │ ├── docker-build-dev-base.yml │ ├── docker-build-dev-elasticsearch.yml │ ├── docker-build-dev-jupyter.yml │ ├── docker-build-dev-kibana.yml │ ├── docker-build-dev-logstash.yml │ ├── docker-build-prd-base.yml │ ├── docker-build-prd-elasticsearch.yml │ ├── docker-build-prd-jupyter.yml │ ├── docker-build-prd-kibana.yml │ ├── docker-build-prd-logstash.yml │ ├── label.yml │ ├── lint.yml │ └── release-drafter.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── VERSION ├── c2servers ├── cron.d │ ├── redelk_cobaltstrike │ ├── redelk_outflankstage1 │ └── redelk_sliver ├── filebeat │ ├── filebeat_redelk_main.yml.example │ └── inputs.d │ │ ├── filebeat_cobaltstrike.yml │ │ ├── filebeat_outflankstage1.yml │ │ ├── filebeat_poshc2.yml │ │ └── filebeat_sliver.yml ├── install-c2server.sh ├── remove-redelkinstall-on-c2servers-USEATOWNRISK.sh └── scripts │ ├── copydownloads_cobaltstrike.sh │ ├── copydownloads_outflankstage1.sh │ ├── export_cobaltstrikedata.sh │ └── exportcsdata.py ├── certs └── config.cnf.example ├── elkserver ├── .env.tmpl ├── docker │ ├── redelk-base │ │ ├── Dockerfile │ │ └── redelkinstalldata │ │ │ ├── 42_redelk-base-docker-init.sh │ │ │ ├── kibana │ │ │ └── redelklogo.json │ │ │ ├── scripts │ │ │ ├── .pylintrc │ │ │ ├── __init__.py │ │ │ ├── config.py │ │ │ ├── daemon.py │ │ │ ├── getremotelogs.sh │ │ │ ├── makethumbnail.py │ │ │ ├── modules │ │ │ │ ├── __init__.py │ │ │ │ ├── alarm_backendalarm │ │ │ │ │ └── module.py │ │ │ │ ├── alarm_dummy │ │ │ │ │ └── module.py │ │ │ │ ├── alarm_filehash │ │ │ │ │ ├── ioc_hybridanalysis.py │ │ │ │ │ ├── ioc_ibm.py │ │ │ │ │ ├── ioc_vt.py │ │ │ │ │ └── module.py │ │ │ │ ├── alarm_httptraffic │ │ │ │ │ ├── module.py │ │ │ │ │ └── readme.md │ │ │ │ ├── alarm_lastline │ │ │ │ │ └── module.py │ │ │ │ ├── alarm_manual │ │ │ │ │ └── module.py │ │ │ │ ├── alarm_useragent │ │ │ │ │ └── module.py │ │ │ │ ├── email │ │ │ │ │ ├── module.py │ │ │ │ │ ├── redelk.png │ │ │ │ │ └── redelk_white.png │ │ │ │ ├── enrich_csbeacon │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_domainscategorization │ │ │ │ │ ├── cat_bluecoat.py │ │ │ │ │ ├── cat_ibmxforce.py │ │ │ │ │ ├── cat_mcafee.py │ │ │ │ │ ├── cat_vt.py │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_greynoise │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_iplists │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_sliver │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_stage1 │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_syncdomainslists │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_synciplists │ │ │ │ │ └── module.py │ │ │ │ ├── enrich_tor │ │ │ │ │ └── module.py │ │ │ │ ├── helpers.py │ │ │ │ ├── msteams │ │ │ │ │ └── module.py │ │ │ │ └── slack │ │ │ │ │ └── module.py │ │ │ ├── requirements.txt │ │ │ ├── run_daemon.sh │ │ │ ├── run_roguedomainsupdate.sh │ │ │ └── run_torexitnodeupdate.sh │ │ │ └── templates │ │ │ ├── diff │ │ │ ├── redelk_kibana_dashboard.json │ │ │ ├── redelk_kibana_index-pattern_.siem-signals.json │ │ │ ├── redelk_kibana_index-pattern_bluecheck.json │ │ │ ├── redelk_kibana_index-pattern_credentials.json │ │ │ ├── redelk_kibana_index-pattern_email.json │ │ │ ├── redelk_kibana_index-pattern_implantsdb.json │ │ │ ├── redelk_kibana_index-pattern_iplist.json │ │ │ ├── redelk_kibana_index-pattern_redelk.json │ │ │ ├── redelk_kibana_index-pattern_redirtraffic.json │ │ │ ├── redelk_kibana_index-pattern_rtops.json │ │ │ ├── redelk_kibana_map.json │ │ │ ├── redelk_kibana_search.json │ │ │ └── redelk_kibana_visualization.json │ │ │ ├── redelk_elasticsearch_ilm.json │ │ │ ├── redelk_elasticsearch_template_bluecheck.json │ │ │ ├── redelk_elasticsearch_template_credentials.json │ │ │ ├── redelk_elasticsearch_template_email.json │ │ │ ├── redelk_elasticsearch_template_implantsdb.json │ │ │ ├── redelk_elasticsearch_template_iplist.json │ │ │ ├── redelk_elasticsearch_template_redelk.json │ │ │ ├── redelk_elasticsearch_template_redirtraffic.json │ │ │ ├── redelk_elasticsearch_template_rtops.json │ │ │ ├── redelk_kibana_dashboard.ndjson │ │ │ ├── redelk_kibana_index-pattern_.siem-signals.ndjson │ │ │ ├── redelk_kibana_index-pattern_bluecheck.ndjson │ │ │ ├── redelk_kibana_index-pattern_credentials.ndjson │ │ │ ├── redelk_kibana_index-pattern_email.ndjson │ │ │ ├── redelk_kibana_index-pattern_implantsdb.ndjson │ │ │ ├── redelk_kibana_index-pattern_redelk-domainslist.ndjson │ │ │ ├── redelk_kibana_index-pattern_redelk-iplist.ndjson │ │ │ ├── redelk_kibana_index-pattern_redelk.ndjson │ │ │ ├── redelk_kibana_index-pattern_redirtraffic.ndjson │ │ │ ├── redelk_kibana_index-pattern_rtops.ndjson │ │ │ ├── redelk_kibana_map.ndjson │ │ │ ├── redelk_kibana_search.ndjson │ │ │ ├── redelk_kibana_settings.json │ │ │ ├── redelk_kibana_visualization.ndjson │ │ │ └── redelk_siem_detection_rules.ndjson │ ├── redelk-elasticsearch │ │ ├── Dockerfile │ │ └── redelkinstalldata │ │ │ ├── init-elasticsearch.sh │ │ │ ├── instances.yml │ │ │ └── redelk-entrypoint.sh │ ├── redelk-jupyter │ │ └── Dockerfile │ ├── redelk-kibana │ │ └── Dockerfile │ └── redelk-logstash │ │ └── Dockerfile ├── init-letsencrypt.sh ├── install-elkserver.sh ├── mounts │ ├── bloodhound-config │ │ └── bloodhound.config.json │ ├── elasticsearch-config │ │ └── jvm.options.d │ │ │ └── jvm.options │ ├── jupyter-workbooks │ │ └── RedELK_Jupyter_Notebook_startup_test.ipynb │ ├── logstash-config │ │ ├── config │ │ │ └── pipelines.yml │ │ └── redelk-main │ │ │ ├── conf.d │ │ │ ├── 10-input_filebeat_logstash.conf │ │ │ ├── 11-input_localfiles_logstash.conf │ │ │ ├── 12-input_email_logstash.conf │ │ │ ├── 20-filter-redir-haproxy_logstash.conf │ │ │ ├── 21-filter-redir-apache_logstash.conf │ │ │ ├── 22-filter-redir-nginx_logstash.conf │ │ │ ├── 30-filter-email_logstash.conf │ │ │ ├── 50-filter-c2-outflankstage1_logstash.conf │ │ │ ├── 51-filter-c2-cobaltstrike_logstash.conf │ │ │ ├── 52-filter-c2-poshc2_logstash.conf │ │ │ ├── 53-filter-c2-sliver_logstash.conf │ │ │ ├── 70-filter-pstools_logstash.conf │ │ │ ├── 80-filter-bluecheck_domainchecks_logstash.conf │ │ │ ├── 80-filter-bluecheck_logstash.conf │ │ │ └── 99-outputs_logstash.conf │ │ │ └── scripts │ │ │ ├── bluecheck_make_sectools_object.rb │ │ │ ├── cs_makebeaconlogpath.rb │ │ │ ├── cs_makedownloadspath.rb │ │ │ ├── cs_makekeystrokespath.rb │ │ │ ├── cs_makekeystrokespath_beforecs4.2.rb │ │ │ ├── cs_makescreenshotpath.rb │ │ │ ├── cs_makescreenshotpath_beforecs4.2.rb │ │ │ ├── outflankstage1_makedownloadspath.rb │ │ │ └── outflankstage1_makelogpath.rb │ ├── nginx-config │ │ ├── default.conf.template │ │ ├── full.bloodhound-conf.template │ │ ├── full.location-conf.template │ │ ├── full.neo4j-conf.template │ │ ├── htpasswd.users.template │ │ └── ssl-dhparams.pem.template │ ├── redelk-config │ │ └── etc │ │ │ ├── cron.d │ │ │ └── redelk.example │ │ │ └── redelk │ │ │ ├── config.json.example │ │ │ ├── domainslist_redteam.conf.example │ │ │ ├── iplist_alarmed.conf.example │ │ │ ├── iplist_blueteam.conf.example │ │ │ ├── iplist_customer.conf.example │ │ │ ├── iplist_redteam.conf.example │ │ │ ├── iplist_unknown.conf.example │ │ │ ├── rogue_useragents.conf.example │ │ │ └── roguedomains.conf.example │ ├── redelk-logs │ │ └── redteamdomaincheck.txt │ ├── redelk-www │ │ └── c2logs │ │ │ └── .gitkeep │ └── sample-data │ │ ├── filebeat.yml │ │ └── logs │ │ ├── apache2.log │ │ ├── cobaltstrike │ │ ├── logs │ │ │ ├── 200329 │ │ │ │ ├── 10.99.1.4 │ │ │ │ │ ├── beacon_1233239984.log │ │ │ │ │ ├── beacon_2019412980.log │ │ │ │ │ ├── beacon_496538698.log │ │ │ │ │ ├── keystrokes │ │ │ │ │ │ └── keystrokes_496538698.txt │ │ │ │ │ └── screenshots │ │ │ │ │ │ ├── screen_012702_496538698.jpg │ │ │ │ │ │ └── screen_030037_2019412980.jpg │ │ │ │ ├── events.log │ │ │ │ └── weblog_80.log │ │ │ ├── 200330 │ │ │ │ ├── 10.1.2.10 │ │ │ │ │ └── beacon_455228.log │ │ │ │ ├── 10.1.3.10 │ │ │ │ │ ├── beacon_358093816.log │ │ │ │ │ ├── beacon_688141424.log │ │ │ │ │ ├── beacon_936715360.log │ │ │ │ │ ├── keystrokes │ │ │ │ │ │ └── keystrokes_936715360.txt │ │ │ │ │ └── screenshots │ │ │ │ │ │ ├── screen_075707_936715360.jpg │ │ │ │ │ │ ├── screen_075830_936715360.jpg │ │ │ │ │ │ └── screen_080335_936715360.jpg │ │ │ │ ├── 10.1.3.11 │ │ │ │ │ └── beacon_1282172642.log │ │ │ │ ├── 10.1.4.10 │ │ │ │ │ ├── beacon_22170412.log │ │ │ │ │ └── beacon_702687076.log │ │ │ │ ├── downloads.log │ │ │ │ ├── events.log │ │ │ │ └── weblog_80.log │ │ │ ├── 200331 │ │ │ │ └── weblog_80.log │ │ │ ├── 200401 │ │ │ │ └── weblog_80.log │ │ │ ├── 200402 │ │ │ │ └── weblog_80.log │ │ │ └── 200403 │ │ │ │ └── weblog_80.log │ │ ├── profiles │ │ │ ├── .DS_Store │ │ │ └── MallableConfig-DomainFronting.profile │ │ └── uploads │ │ │ └── OfferNr2020F6592_salary.doc │ │ ├── haproxy.log │ │ └── nginx.log ├── redelk-dev.yml ├── redelk-full.yml ├── redelk-limited.yml └── remove-redelkinstall-on-elkserver-USEATOWNRISK.sh ├── example-data-and-configs ├── Apache │ └── redelk-redir-apache.conf ├── CobaltStrike │ └── MallableConfig-DomainFronting.profile ├── ExampleData │ ├── Readme.md │ ├── c2server1_cobaltstrike.zip │ ├── c2server2_cobaltstrike.zip │ ├── cslogs.tgz │ ├── redelk_elasticsearch-backup.tgz │ ├── redira1_access-redelk.log │ └── redirb1_haproxy.log ├── HAProxy │ └── haproxy.cfg ├── RedELKFieldnames.md ├── RedELKFieldnamesV2.md └── nginx │ └── redelk-redir-nginx.conf ├── helper-scripts ├── export_kibana_config.py ├── get_fields_mappings.sh ├── requirements.txt └── reset_ES_readwrite.sh ├── images ├── dashboard-add-ioc.png ├── dashboard-alarm.png ├── dashboard-downloads.png ├── dashboard-health.png ├── dashboard-implants.png ├── dashboard-ioc.png ├── dashboard-mitre-attack-navigator.png ├── dashboard-overview.png ├── dashboard-rtops.png ├── dashboard-summary.png ├── dashboard-tasks.png ├── dashboard-traffic.png ├── redelk_IOC.jpg ├── redelk_dashboard.jpg ├── redelk_dashboard2.jpg ├── redelk_dashboard3.jpg ├── redelk_downloads.jpg ├── redelk_keystrokes.jpg ├── redelk_opening.jpg ├── redelk_overview.jpg ├── redelk_overview.png ├── redelk_redirtraffic.jpg ├── redelk_screenshots.jpg ├── redelk_timeline.jpg └── redelk_timeline_details.jpg ├── initial-setup.sh ├── redirs ├── filebeat │ └── filebeat.yml.example ├── install-redir.sh └── remove-redelkinstall-on-redirs-USEATOWNRISK.sh └── releasenotes.txt /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Adds lable to PR based on file changes 2 | 3 | # C2 server files 4 | c2servers: 5 | - "c2servers/**/*" 6 | 7 | # ELK server files 8 | elkserver: 9 | - "elkserver/**/*" 10 | 11 | # Redirector files 12 | redirs: 13 | - "redirs/**/*" 14 | 15 | # Helper scripts 16 | helpers: 17 | - "helper-scripts/**/*" 18 | 19 | # Documentation 20 | documentation: 21 | - "README.md" 22 | - "LICENSE" 23 | - "VERSION" 24 | - "releasenotes.txt" 25 | - "images/**/*" 26 | - "example-data-and-configs/**/*" 27 | 28 | # Installer files 29 | installer: 30 | - "initial-setup.sh" 31 | - "c2servers/install-c2server-*.sh" 32 | - "elkserver/install-elkserver.sh" 33 | - "elkserver/redelk-*.yml" 34 | - "redirs/install-redir.sh" 35 | 36 | # Docker files 37 | docker: 38 | - "elkserver/docker/**/*" 39 | 40 | # GitHub workflows and CI/CD files 41 | githubci: 42 | - ".github/**/*" 43 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: "v$RESOLVED_VERSION" 2 | tag-template: "v$RESOLVED_VERSION" 3 | categories: 4 | - title: "🚀 Features" 5 | labels: 6 | - "feature" 7 | - "enhancement" 8 | - title: "🐛 Bug Fixes" 9 | labels: 10 | - "fix" 11 | - "bugfix" 12 | - "bug" 13 | change-template: "- $TITLE @$AUTHOR (#$NUMBER)" 14 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 15 | version-resolver: 16 | major: 17 | labels: 18 | - "major" 19 | minor: 20 | labels: 21 | - "minor" 22 | patch: 23 | labels: 24 | - "patch" 25 | default: patch 26 | template: | 27 | ## What's new? 28 | 29 | $CHANGES 30 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-dev-base.yml: -------------------------------------------------------------------------------- 1 | name: Build docker base image (dev) 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request_target: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Prepare 18 | id: prepare 19 | run: | 20 | if [[ "x$DOCKER_REPO" == "x" ]]; then 21 | DOCKER_REPO=outflanknl 22 | fi 23 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-base" 24 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 25 | echo ::set-output name=docker_repo::${DOCKER_REPO} 26 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 27 | VCS_REF=${GITHUB_SHA::8} 28 | env: 29 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 30 | - name: Docker meta 31 | id: docker_meta 32 | uses: crazy-max/ghaction-docker-meta@v1 33 | with: 34 | images: ${{ steps.prepare.outputs.docker_image }} 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v1 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | - name: Login to DockerHub 40 | uses: docker/login-action@v1 41 | if: ${{ github.event_name != 'pull_request' }} 42 | with: 43 | username: ${{ secrets.DOCKER_USERNAME }} 44 | password: ${{ secrets.DOCKER_PASSWORD }} 45 | - name: Cache Docker layers 46 | uses: actions/cache@v2 47 | id: cache 48 | with: 49 | path: /tmp/.buildx-cache 50 | key: ${{ runner.os }}-buildx-base-${{ github.sha }} 51 | restore-keys: | 52 | ${{ runner.os }}-buildx-base- 53 | - name: Build and push 54 | uses: docker/build-push-action@v2 55 | with: 56 | context: elkserver/docker/redelk-base 57 | file: ./elkserver/docker/redelk-base/Dockerfile 58 | platforms: linux/amd64,linux/arm64 59 | push: true 60 | tags: ${{ steps.docker_meta.outputs.tags }} 61 | labels: ${{ steps.docker_meta.outputs.labels }} 62 | build-args: ${{ steps.prepare.outputs.build_args }} 63 | cache-from: type=local,src=/tmp/.buildx-cache 64 | cache-to: type=local,dest=/tmp/.buildx-cache 65 | # tags: | 66 | # ${{ steps.semver_parser.outputs.major }} 67 | # ${{ steps.semver_parser.outputs.major }}.${{ steps.semver_parser.outputs.minor }} 68 | # ${{ steps.semver_parser.outputs.major }}.${{ steps.semver_parser.outputs.minor }}.${{ steps.semver_parser.outputs.patch }} 69 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-dev-elasticsearch.yml: -------------------------------------------------------------------------------- 1 | name: Build docker elasticsearch image (dev) 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request_target: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Prepare 18 | id: prepare 19 | run: | 20 | if [[ "x$DOCKER_REPO" == "x" ]]; then 21 | DOCKER_REPO=outflanknl 22 | fi 23 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-elasticsearch" 24 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 25 | echo ::set-output name=docker_repo::${DOCKER_REPO} 26 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 27 | VCS_REF=${GITHUB_SHA::8} 28 | env: 29 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 30 | - name: Docker meta 31 | id: docker_meta 32 | uses: crazy-max/ghaction-docker-meta@v1 33 | with: 34 | images: ${{ steps.prepare.outputs.docker_image }} 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v1 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | - name: Login to DockerHub 40 | uses: docker/login-action@v1 41 | if: ${{ github.event_name != 'pull_request' }} 42 | with: 43 | username: ${{ secrets.DOCKER_USERNAME }} 44 | password: ${{ secrets.DOCKER_PASSWORD }} 45 | - name: Cache Docker layers 46 | uses: actions/cache@v2 47 | id: cache 48 | with: 49 | path: /tmp/.buildx-cache 50 | key: ${{ runner.os }}-buildx-elasticsearch-${{ github.sha }} 51 | restore-keys: | 52 | ${{ runner.os }}-buildx-elasticsearch- 53 | - name: Build and push 54 | uses: docker/build-push-action@v2 55 | with: 56 | context: elkserver/docker/redelk-elasticsearch 57 | file: ./elkserver/docker/redelk-elasticsearch/Dockerfile 58 | platforms: linux/amd64,linux/arm64 59 | push: true 60 | tags: ${{ steps.docker_meta.outputs.tags }} 61 | labels: ${{ steps.docker_meta.outputs.labels }} 62 | build-args: ${{ steps.prepare.outputs.build_args }} 63 | cache-from: type=local,src=/tmp/.buildx-cache 64 | cache-to: type=local,dest=/tmp/.buildx-cache 65 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-dev-jupyter.yml: -------------------------------------------------------------------------------- 1 | name: Build docker jupyter image (dev) 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request_target: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Prepare 18 | id: prepare 19 | run: | 20 | if [[ "x$DOCKER_REPO" == "x" ]]; then 21 | DOCKER_REPO=outflanknl 22 | fi 23 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-jupyter" 24 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 25 | echo ::set-output name=docker_repo::${DOCKER_REPO} 26 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 27 | VCS_REF=${GITHUB_SHA::8} 28 | env: 29 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 30 | - name: Docker meta 31 | id: docker_meta 32 | uses: crazy-max/ghaction-docker-meta@v1 33 | with: 34 | images: ${{ steps.prepare.outputs.docker_image }} 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v1 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | - name: Login to DockerHub 40 | uses: docker/login-action@v1 41 | if: ${{ github.event_name != 'pull_request' }} 42 | with: 43 | username: ${{ secrets.DOCKER_USERNAME }} 44 | password: ${{ secrets.DOCKER_PASSWORD }} 45 | - name: Cache Docker layers 46 | uses: actions/cache@v2 47 | id: cache 48 | with: 49 | path: /tmp/.buildx-cache 50 | key: ${{ runner.os }}-buildx-jupyter-${{ github.sha }} 51 | restore-keys: | 52 | ${{ runner.os }}-buildx-jupyter- 53 | - name: Build and push 54 | uses: docker/build-push-action@v2 55 | with: 56 | context: elkserver/docker/redelk-jupyter 57 | file: ./elkserver/docker/redelk-jupyter/Dockerfile 58 | platforms: linux/amd64,linux/arm64 59 | push: true 60 | tags: ${{ steps.docker_meta.outputs.tags }} 61 | labels: ${{ steps.docker_meta.outputs.labels }} 62 | build-args: ${{ steps.prepare.outputs.build_args }} 63 | cache-from: type=local,src=/tmp/.buildx-cache 64 | cache-to: type=local,dest=/tmp/.buildx-cache 65 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-dev-kibana.yml: -------------------------------------------------------------------------------- 1 | name: Build docker kibana image (dev) 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request_target: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Prepare 18 | id: prepare 19 | run: | 20 | if [[ "x$DOCKER_REPO" == "x" ]]; then 21 | DOCKER_REPO=outflanknl 22 | fi 23 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-kibana" 24 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 25 | echo ::set-output name=docker_repo::${DOCKER_REPO} 26 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 27 | VCS_REF=${GITHUB_SHA::8} 28 | env: 29 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 30 | - name: Docker meta 31 | id: docker_meta 32 | uses: crazy-max/ghaction-docker-meta@v1 33 | with: 34 | images: ${{ steps.prepare.outputs.docker_image }} 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v1 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | - name: Login to DockerHub 40 | uses: docker/login-action@v1 41 | if: ${{ github.event_name != 'pull_request' }} 42 | with: 43 | username: ${{ secrets.DOCKER_USERNAME }} 44 | password: ${{ secrets.DOCKER_PASSWORD }} 45 | - name: Cache Docker layers 46 | uses: actions/cache@v2 47 | id: cache 48 | with: 49 | path: /tmp/.buildx-cache 50 | key: ${{ runner.os }}-buildx-kibana-${{ github.sha }} 51 | restore-keys: | 52 | ${{ runner.os }}-buildx-kibana- 53 | - name: Build and push 54 | uses: docker/build-push-action@v2 55 | with: 56 | context: elkserver/docker/redelk-kibana 57 | file: ./elkserver/docker/redelk-kibana/Dockerfile 58 | platforms: linux/amd64,linux/arm64 59 | push: true 60 | tags: ${{ steps.docker_meta.outputs.tags }} 61 | labels: ${{ steps.docker_meta.outputs.labels }} 62 | build-args: ${{ steps.prepare.outputs.build_args }} 63 | cache-from: type=local,src=/tmp/.buildx-cache 64 | cache-to: type=local,dest=/tmp/.buildx-cache 65 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-dev-logstash.yml: -------------------------------------------------------------------------------- 1 | name: Build docker logstash image (dev) 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request_target: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Prepare 18 | id: prepare 19 | run: | 20 | if [[ "x$DOCKER_REPO" == "x" ]]; then 21 | DOCKER_REPO=outflanknl 22 | fi 23 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-logstash" 24 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 25 | echo ::set-output name=docker_repo::${DOCKER_REPO} 26 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 27 | VCS_REF=${GITHUB_SHA::8} 28 | env: 29 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 30 | - name: Docker meta 31 | id: docker_meta 32 | uses: crazy-max/ghaction-docker-meta@v1 33 | with: 34 | images: ${{ steps.prepare.outputs.docker_image }} 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v1 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | - name: Login to DockerHub 40 | uses: docker/login-action@v1 41 | if: ${{ github.event_name != 'pull_request' }} 42 | with: 43 | username: ${{ secrets.DOCKER_USERNAME }} 44 | password: ${{ secrets.DOCKER_PASSWORD }} 45 | - name: Cache Docker layers 46 | uses: actions/cache@v2 47 | id: cache 48 | with: 49 | path: /tmp/.buildx-cache 50 | key: ${{ runner.os }}-buildx-logstash-${{ github.sha }} 51 | restore-keys: | 52 | ${{ runner.os }}-buildx-logstash- 53 | - name: Build and push 54 | uses: docker/build-push-action@v2 55 | with: 56 | context: elkserver/docker/redelk-logstash 57 | file: ./elkserver/docker/redelk-logstash/Dockerfile 58 | platforms: linux/amd64,linux/arm64 59 | push: true 60 | tags: ${{ steps.docker_meta.outputs.tags }} 61 | labels: ${{ steps.docker_meta.outputs.labels }} 62 | build-args: ${{ steps.prepare.outputs.build_args }} 63 | cache-from: type=local,src=/tmp/.buildx-cache 64 | cache-to: type=local,dest=/tmp/.buildx-cache 65 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-prd-base.yml: -------------------------------------------------------------------------------- 1 | name: Build docker base image (prd) 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | paths: 8 | - "*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Prepare 17 | id: prepare 18 | run: | 19 | if [[ "x$DOCKER_REPO" == "x" ]]; then 20 | DOCKER_REPO=outflanknl 21 | fi 22 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-base" 23 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 24 | echo ::set-output name=docker_repo::${DOCKER_REPO} 25 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 26 | VCS_REF=${GITHUB_SHA::8} 27 | env: 28 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 29 | - name: Docker meta 30 | id: docker_meta 31 | uses: crazy-max/ghaction-docker-meta@v1 32 | with: 33 | images: ${{ steps.prepare.outputs.docker_image }} 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v1 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | - name: Login to DockerHub 39 | uses: docker/login-action@v1 40 | if: ${{ github.event_name != 'pull_request' }} 41 | with: 42 | username: ${{ secrets.DOCKER_USERNAME }} 43 | password: ${{ secrets.DOCKER_PASSWORD }} 44 | - name: Cache Docker layers 45 | uses: actions/cache@v2 46 | id: cache 47 | with: 48 | path: /tmp/.buildx-cache 49 | key: ${{ runner.os }}-buildx-base-${{ github.sha }} 50 | restore-keys: | 51 | ${{ runner.os }}-buildx-base- 52 | - name: Build and push 53 | uses: docker/build-push-action@v2 54 | with: 55 | context: elkserver/docker/redelk-base 56 | file: ./elkserver/docker/redelk-base/Dockerfile 57 | platforms: linux/amd64,linux/arm64 58 | push: ${{ github.event_name != 'pull_request' }} 59 | tags: ${{ steps.docker_meta.outputs.tags }} 60 | labels: ${{ steps.docker_meta.outputs.labels }} 61 | build-args: ${{ steps.prepare.outputs.build_args }} 62 | cache-from: type=local,src=/tmp/.buildx-cache 63 | cache-to: type=local,dest=/tmp/.buildx-cache 64 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-prd-elasticsearch.yml: -------------------------------------------------------------------------------- 1 | name: Build docker elasticsearch image (prd) 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | paths: 8 | - "*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Prepare 17 | id: prepare 18 | run: | 19 | if [[ "x$DOCKER_REPO" == "x" ]]; then 20 | DOCKER_REPO=outflanknl 21 | fi 22 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-elasticsearch" 23 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 24 | echo ::set-output name=docker_repo::${DOCKER_REPO} 25 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 26 | VCS_REF=${GITHUB_SHA::8} 27 | env: 28 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 29 | - name: Docker meta 30 | id: docker_meta 31 | uses: crazy-max/ghaction-docker-meta@v1 32 | with: 33 | images: ${{ steps.prepare.outputs.docker_image }} 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v1 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | - name: Login to DockerHub 39 | uses: docker/login-action@v1 40 | if: ${{ github.event_name != 'pull_request' }} 41 | with: 42 | username: ${{ secrets.DOCKER_USERNAME }} 43 | password: ${{ secrets.DOCKER_PASSWORD }} 44 | - name: Cache Docker layers 45 | uses: actions/cache@v2 46 | id: cache 47 | with: 48 | path: /tmp/.buildx-cache 49 | key: ${{ runner.os }}-buildx-elasticsearch-${{ github.sha }} 50 | restore-keys: | 51 | ${{ runner.os }}-buildx-elasticsearch- 52 | - name: Build and push 53 | uses: docker/build-push-action@v2 54 | with: 55 | context: elkserver/docker/redelk-elasticsearch 56 | file: ./elkserver/docker/redelk-elasticsearch/Dockerfile 57 | platforms: linux/amd64,linux/arm64 58 | push: ${{ github.event_name != 'pull_request' }} 59 | tags: ${{ steps.docker_meta.outputs.tags }} 60 | labels: ${{ steps.docker_meta.outputs.labels }} 61 | build-args: ${{ steps.prepare.outputs.build_args }} 62 | cache-from: type=local,src=/tmp/.buildx-cache 63 | cache-to: type=local,dest=/tmp/.buildx-cache 64 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-prd-jupyter.yml: -------------------------------------------------------------------------------- 1 | name: Build docker jupyter image (prd) 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | paths: 8 | - "*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Prepare 17 | id: prepare 18 | run: | 19 | if [[ "x$DOCKER_REPO" == "x" ]]; then 20 | DOCKER_REPO=outflanknl 21 | fi 22 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-jupyter" 23 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 24 | echo ::set-output name=docker_repo::${DOCKER_REPO} 25 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 26 | VCS_REF=${GITHUB_SHA::8} 27 | env: 28 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 29 | - name: Docker meta 30 | id: docker_meta 31 | uses: crazy-max/ghaction-docker-meta@v1 32 | with: 33 | images: ${{ steps.prepare.outputs.docker_image }} 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v1 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | - name: Login to DockerHub 39 | uses: docker/login-action@v1 40 | if: ${{ github.event_name != 'pull_request' }} 41 | with: 42 | username: ${{ secrets.DOCKER_USERNAME }} 43 | password: ${{ secrets.DOCKER_PASSWORD }} 44 | - name: Cache Docker layers 45 | uses: actions/cache@v2 46 | id: cache 47 | with: 48 | path: /tmp/.buildx-cache 49 | key: ${{ runner.os }}-buildx-jupyter-${{ github.sha }} 50 | restore-keys: | 51 | ${{ runner.os }}-buildx-jupyter- 52 | - name: Build and push 53 | uses: docker/build-push-action@v2 54 | with: 55 | context: elkserver/docker/redelk-jupyter 56 | file: ./elkserver/docker/redelk-jupyter/Dockerfile 57 | platforms: linux/amd64,linux/arm64 58 | push: ${{ github.event_name != 'pull_request' }} 59 | tags: ${{ steps.docker_meta.outputs.tags }} 60 | labels: ${{ steps.docker_meta.outputs.labels }} 61 | build-args: ${{ steps.prepare.outputs.build_args }} 62 | cache-from: type=local,src=/tmp/.buildx-cache 63 | cache-to: type=local,dest=/tmp/.buildx-cache 64 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-prd-kibana.yml: -------------------------------------------------------------------------------- 1 | name: Build docker kibana image (prd) 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | paths: 8 | - "*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Prepare 17 | id: prepare 18 | run: | 19 | if [[ "x$DOCKER_REPO" == "x" ]]; then 20 | DOCKER_REPO=outflanknl 21 | fi 22 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-kibana" 23 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 24 | echo ::set-output name=docker_repo::${DOCKER_REPO} 25 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 26 | VCS_REF=${GITHUB_SHA::8} 27 | env: 28 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 29 | - name: Docker meta 30 | id: docker_meta 31 | uses: crazy-max/ghaction-docker-meta@v1 32 | with: 33 | images: ${{ steps.prepare.outputs.docker_image }} 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v1 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | - name: Login to DockerHub 39 | uses: docker/login-action@v1 40 | if: ${{ github.event_name != 'pull_request' }} 41 | with: 42 | username: ${{ secrets.DOCKER_USERNAME }} 43 | password: ${{ secrets.DOCKER_PASSWORD }} 44 | - name: Cache Docker layers 45 | uses: actions/cache@v2 46 | id: cache 47 | with: 48 | path: /tmp/.buildx-cache 49 | key: ${{ runner.os }}-buildx-kibana-${{ github.sha }} 50 | restore-keys: | 51 | ${{ runner.os }}-buildx-kibana- 52 | - name: Build and push 53 | uses: docker/build-push-action@v2 54 | with: 55 | context: elkserver/docker/redelk-kibana 56 | file: ./elkserver/docker/redelk-kibana/Dockerfile 57 | platforms: linux/amd64,linux/arm64 58 | push: ${{ github.event_name != 'pull_request' }} 59 | tags: ${{ steps.docker_meta.outputs.tags }} 60 | labels: ${{ steps.docker_meta.outputs.labels }} 61 | build-args: ${{ steps.prepare.outputs.build_args }} 62 | cache-from: type=local,src=/tmp/.buildx-cache 63 | cache-to: type=local,dest=/tmp/.buildx-cache 64 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-prd-logstash.yml: -------------------------------------------------------------------------------- 1 | name: Build docker logstash image (prd) 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | paths: 8 | - "*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Prepare 17 | id: prepare 18 | run: | 19 | if [[ "x$DOCKER_REPO" == "x" ]]; then 20 | DOCKER_REPO=outflanknl 21 | fi 22 | DOCKER_IMAGE="${DOCKER_REPO}/redelk-logstash" 23 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 24 | echo ::set-output name=docker_repo::${DOCKER_REPO} 25 | echo ::set-output name=build_args::BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ 26 | VCS_REF=${GITHUB_SHA::8} 27 | env: 28 | DOCKER_REPO: ${{ secrets.DOCKER_REPO }} 29 | - name: Docker meta 30 | id: docker_meta 31 | uses: crazy-max/ghaction-docker-meta@v1 32 | with: 33 | images: ${{ steps.prepare.outputs.docker_image }} 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v1 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | - name: Login to DockerHub 39 | uses: docker/login-action@v1 40 | if: ${{ github.event_name != 'pull_request' }} 41 | with: 42 | username: ${{ secrets.DOCKER_USERNAME }} 43 | password: ${{ secrets.DOCKER_PASSWORD }} 44 | - name: Cache Docker layers 45 | uses: actions/cache@v2 46 | id: cache 47 | with: 48 | path: /tmp/.buildx-cache 49 | key: ${{ runner.os }}-buildx-logstash-${{ github.sha }} 50 | restore-keys: | 51 | ${{ runner.os }}-buildx-logstash- 52 | - name: Build and push 53 | uses: docker/build-push-action@v2 54 | with: 55 | context: elkserver/docker/redelk-logstash 56 | file: ./elkserver/docker/redelk-logstash/Dockerfile 57 | platforms: linux/amd64,linux/arm64 58 | push: ${{ github.event_name != 'pull_request' }} 59 | tags: ${{ steps.docker_meta.outputs.tags }} 60 | labels: ${{ steps.docker_meta.outputs.labels }} 61 | build-args: ${{ steps.prepare.outputs.build_args }} 62 | cache-from: type=local,src=/tmp/.buildx-cache 63 | cache-to: type=local,dest=/tmp/.buildx-cache 64 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | # This workflow will triage pull requests and apply a label based on the 2 | # paths that are modified in the pull request. 3 | # 4 | # To use this workflow, you will need to set up a .github/labeler.yml 5 | # file with configuration. For more information, see: 6 | # https://github.com/actions/labeler 7 | 8 | name: Label PR 9 | on: [pull_request_target] 10 | 11 | jobs: 12 | label: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/labeler@v2 17 | with: 18 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 19 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint - Python 2 | 3 | on: 4 | push: 5 | paths: 6 | - "elkserver/docker/redelk-base/redelkinstalldata/scripts/**" 7 | - .github/workflows/lint.yml 8 | pull_request: 9 | paths: 10 | - "elkserver/docker/redelk-base/redelkinstalldata/scripts/**" 11 | - .github/workflows/lint.yml 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-20.04 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v3 20 | - name: Set up Python 3.6 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: "3.6.9" 24 | cache: pip 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | pip install black 29 | pip install -r elkserver/docker/redelk-base/redelkinstalldata/scripts/requirements.txt 30 | - name: Analysing the code with black 31 | run: | 32 | black --check --diff --color elkserver/docker/redelk-base/redelkinstalldata/scripts 33 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - main 8 | - master 9 | - maindev 10 | 11 | jobs: 12 | update_release_draft: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: release-drafter/release-drafter@v5 16 | with: 17 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml 18 | config-name: release-drafter.yml 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | #*.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .env.bak* 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # mkdocs documentation 102 | /site 103 | 104 | .vscode/* 105 | !.vscode/extensions.json 106 | 107 | # mypy 108 | .mypy_cache/ 109 | elkserver/scripts/upload_redelkz.sh 110 | 111 | c2servers.tgz 112 | c2servers/VERSION 113 | c2servers/ssh/ 114 | c2servers/filebeat/*.crt 115 | certs/*.key 116 | certs/*.crt 117 | certs/*.csr 118 | certs/*.pem 119 | certs/*.srl 120 | elkserver.tgz 121 | elkserver/VERSION 122 | elkserver/mounts/redelk-ssh/* 123 | elkserver/mounts/redelk-logs/* 124 | elkserver/mounts/certs/* 125 | elkserver/mounts/certbot/* 126 | elkserver/mounts/jupyter-workbooks/redelk_passwords.py 127 | elkserver/redelk_passwords.cfg 128 | elkserver/redelk-install.log 129 | elkserver/docker-compose.yml 130 | redelk-inintialsetup.log 131 | redirs.tgz 132 | redirs/VERSION 133 | redirs/filebeat/*.crt 134 | sshkey/ 135 | elkserver/mounts/logstash-config/certs_inputs/* 136 | certs/config.cnf 137 | elkserver/mounts/redelk-config/etc/cron.d/redelk 138 | elkserver/mounts/redelk-config/etc/redelk/config.json 139 | elkserver/mounts/redelk-config/etc/redelk/domainslist_redteam.conf 140 | elkserver/mounts/redelk-config/etc/redelk/iplist_alarmed.conf 141 | elkserver/mounts/redelk-config/etc/redelk/iplist_blueteam.conf 142 | elkserver/mounts/redelk-config/etc/redelk/iplist_customer.conf 143 | elkserver/mounts/redelk-config/etc/redelk/iplist_redteam.conf 144 | elkserver/mounts/redelk-config/etc/redelk/iplist_unknown.conf 145 | elkserver/mounts/redelk-config/etc/redelk/rogue_useragents.conf 146 | elkserver/mounts/redelk-config/etc/redelk/roguedomains.conf 147 | redirs/filebeat/filebeat.yml 148 | c2servers/filebeat/filebeat_redelk_main.yml 149 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v3.2.0 6 | hooks: 7 | - id: trailing-whitespace 8 | - id: end-of-file-fixer 9 | - id: check-yaml 10 | exclude: ^(c2servers|redirs)/filebeat(/inputs.d)?/.*.yml$ 11 | - id: check-added-large-files 12 | - id: requirements-txt-fixer 13 | - id: fix-encoding-pragma 14 | - repo: https://github.com/psf/black 15 | rev: 22.8.0 16 | hooks: 17 | - id: black 18 | # language_version: python3.9 19 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-python.python", 4 | "ms-toolsai.jupyter", 5 | "redhat.vscode-yaml", 6 | "oderwat.indent-rainbow", 7 | "ms-azuretools.vscode-docker" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Outflank B.V. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v2.0.0-beta.6 2 | -------------------------------------------------------------------------------- /c2servers/cron.d/redelk_cobaltstrike: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # cron.d script for periodic actions related to RedELK and Cobalt Strike 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | SHELL=/bin/sh 9 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 10 | 11 | # Command to sync the logs from cobaltstrike to our scponly user's home directory 12 | # m h dom mon dow user command 13 | * * * * * root /usr/bin/rsync -rvx --append-verify --delete /root/cobaltstrike/server/logs /home/scponly/cobaltstrike/; /bin/chown -R scponly:scponly /home/scponly/cobaltstrike/* 14 | * * * * * root /usr/bin/rsync -rvx --append-verify --delete /root/cobaltstrike/profiles /home/scponly/cobaltstrike/; /bin/chown -R scponly:scponly /home/scponly/cobaltstrike/* 15 | * * * * * root /usr/bin/rsync -rvx --append-verify --delete /root/cobaltstrike/server/data /home/scponly/cobaltstrike/; /bin/chown -R scponly:scponly /home/scponly/cobaltstrike/* 16 | * * * * * root /usr/share/redelk/bin/export_cobaltstrikedata.sh 17 | * * * * * root /usr/share/redelk/bin/copydownloads_cobaltstrike.sh 18 | -------------------------------------------------------------------------------- /c2servers/cron.d/redelk_outflankstage1: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # cron.d script for periodic actions related to RedELK and Outflank Stage1 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | SHELL=/bin/sh 9 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 10 | 11 | # Command to sync the logs from Stage1 to our scponly user's home directory 12 | # m h dom mon dow user command 13 | * * * * * root /usr/bin/rsync -rvx --append-verify --delete /root/stage1c2server/shared/logs /home/scponly/stage1/; /bin/chown -R scponly:scponly /home/scponly/stage1/* 14 | * * * * * root /usr/share/redelk/bin/copydownloads_outflankstage1.sh 15 | -------------------------------------------------------------------------------- /c2servers/cron.d/redelk_sliver: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # cron.d script for periodic actions related to RedELK and Cobalt Strike 4 | # 5 | # Author: hypnoticpattern 6 | # 7 | 8 | SHELL=/bin/sh 9 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 10 | 11 | # Command to sync the logs from sliver to our scponly user's home directory 12 | # m h dom mon dow user command 13 | * * * * * root /usr/bin/rsync -rvx --append-verify --delete /root/.sliver/logs/audit.json /home/scponly/sliver/; /bin/chown -R scponly:scponly /home/scponly/sliver/* 14 | -------------------------------------------------------------------------------- /c2servers/filebeat/filebeat_redelk_main.yml.example: -------------------------------------------------------------------------------- 1 | filebeat.config.inputs: 2 | enabled: true 3 | path: inputs.d/*.yml 4 | reload.enabled: true 5 | reload.period: 10s 6 | 7 | filebeat.config.modules: 8 | path: ${path.config}/modules.d/*.yml 9 | reload.enabled: false 10 | 11 | setup.template.settings: 12 | index.number_of_shards: 3 13 | 14 | name: "@@HOSTNAME@@" 15 | fields_under_root: true 16 | harvester.limit: 1 17 | 18 | output.logstash: 19 | hosts: ["@@HOSTANDPORT@@"] 20 | ssl.certificate_authorities: ["/etc/filebeat/redelkCA.crt"] 21 | -------------------------------------------------------------------------------- /c2servers/filebeat/inputs.d/filebeat_cobaltstrike.yml: -------------------------------------------------------------------------------- 1 | - type: log 2 | scan_frequency: 5s 3 | enabled: true 4 | fields_under_root: true 5 | paths: 6 | - /root/cobaltstrike/server/logs/*/events.log 7 | fields: 8 | infra: 9 | attack_scenario: @@ATTACKSCENARIO@@ 10 | log: 11 | type: rtops 12 | c2: 13 | program: cobaltstrike 14 | log: 15 | type: events 16 | 17 | - type: log 18 | scan_frequency: 5s 19 | enabled: true 20 | fields_under_root: true 21 | paths: 22 | - /root/cobaltstrike/server/logs/*/weblog* 23 | fields: 24 | infra: 25 | attack_scenario: @@ATTACKSCENARIO@@ 26 | log: 27 | type: rtops 28 | c2: 29 | program: cobaltstrike 30 | log: 31 | type: weblog 32 | 33 | - type: log 34 | scan_frequency: 5s 35 | enabled: true 36 | fields_under_root: true 37 | paths: 38 | - /root/cobaltstrike/server/logs/*/downloads.log 39 | fields: 40 | infra: 41 | attack_scenario: @@ATTACKSCENARIO@@ 42 | log: 43 | type: rtops 44 | c2: 45 | program: cobaltstrike 46 | log: 47 | type: downloads 48 | 49 | - type: log 50 | scan_frequency: 5s 51 | enabled: true 52 | fields_under_root: true 53 | paths: 54 | - /root/cobaltstrike/server/data/export_credentials.tsv 55 | fields: 56 | infra: 57 | attack_scenario: @@ATTACKSCENARIO@@ 58 | log: 59 | type: rtops 60 | c2: 61 | program: cobaltstrike 62 | log: 63 | type: credentials 64 | 65 | 66 | - type: log 67 | scan_frequency: 5s 68 | enabled: true 69 | fields_under_root: true 70 | paths: 71 | - /root/cobaltstrike/server/logs/*/*/beacon_*.log 72 | - /root/cobaltstrike/server/logs/*/*/ssh_*.log 73 | # Since Cobalt Strike version 3.14 the time format in the logs is changed. Here we use regex 'or' function (expr1)|(expr2) to match new or old format 74 | multiline.pattern: '(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\sUTC\s\[)|(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\s\[)' # match "06/19 12:32:56 UTC [" or "06/19 12:32:56 [" 75 | multiline.negate: true 76 | multiline.match: after 77 | multiline.max_lines: 100000 78 | fields: 79 | infra: 80 | attack_scenario: @@ATTACKSCENARIO@@ 81 | log: 82 | type: rtops 83 | c2: 84 | program: cobaltstrike 85 | log: 86 | type: beacon 87 | 88 | - type: log 89 | scan_frequency: 5s 90 | enabled: true 91 | fields_under_root: true 92 | paths: 93 | - /root/cobaltstrike/server/logs/*/*/keystrokes/keystrokes_*.txt 94 | # Since Cobalt Strike version 3.14 the time format in the logs is changed. Here we use regex 'or' function (expr1)|(expr2) to match new or old format 95 | multiline.pattern: '(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\sUTC\s\[)|(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\s\[)' # match "06/19 12:32:56 UTC [" or "06/19 12:32:56 [" 96 | multiline.negate: true 97 | multiline.match: after 98 | multiline.max_lines: 100000 99 | fields: 100 | infra: 101 | attack_scenario: @@ATTACKSCENARIO@@ 102 | log: 103 | type: rtops 104 | c2: 105 | program: cobaltstrike 106 | log: 107 | type: keystrokes 108 | 109 | - type: log 110 | scan_frequency: 5s 111 | enabled: true 112 | fields_under_root: true 113 | paths: 114 | - /root/cobaltstrike/server/logs/*/*/screenshots.log 115 | # Since Cobalt Strike version 3.14 the time format in the logs is changed. Here we use regex 'or' function (expr1)|(expr2) to match new or old format 116 | multiline.pattern: '(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\sUTC\s\[)|(^\d\d\/\d\d\s\d\d\:\d\d\:\d\d\s\[)' # match "06/19 12:32:56 UTC [" or "06/19 12:32:56 [" 117 | multiline.negate: true 118 | multiline.match: after 119 | multiline.max_lines: 100000 120 | fields: 121 | infra: 122 | attack_scenario: @@ATTACKSCENARIO@@ 123 | log: 124 | type: rtops 125 | c2: 126 | program: cobaltstrike 127 | log: 128 | type: screenshots 129 | -------------------------------------------------------------------------------- /c2servers/filebeat/inputs.d/filebeat_outflankstage1.yml: -------------------------------------------------------------------------------- 1 | - type: log 2 | scan_frequency: 5s 3 | enabled: true 4 | fields_under_root: true 5 | paths: 6 | - /root/stage1c2server/shared/logs/api/implant_logs/legacy_text/*.log 7 | multiline.pattern: '^\d\d\d\d\-\d\d\-\d\d\s\d\d\:\d\d\:\d\d\sUTC\s' # match "2020-04-26 19:49:03 UTC 8 | multiline.negate: true 9 | multiline.match: after 10 | fields: 11 | infra: 12 | attack_scenario: @@ATTACKSCENARIO@@ 13 | log: 14 | type: rtops 15 | c2: 16 | program: stage1 17 | log: 18 | type: implant 19 | -------------------------------------------------------------------------------- /c2servers/filebeat/inputs.d/filebeat_poshc2.yml: -------------------------------------------------------------------------------- 1 | - type: log 2 | scan_frequency: 5s 3 | enabled: true 4 | fields_under_root: true 5 | paths: 6 | - /opt/*/poshc2_server.log 7 | include_lines: ['(.*)implant\s+connected:\s+','(0[1-9]|[12]\d|3[01])/(0[1-9]|1[0-2])/[12]\d{3}\s+([0-1][0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9]):(.*?)','Download\s+file\s+part\s+(.*?)','Screenshot\s+captured:\s+(.*?)','(.*?)\:(.*?)\s+\|\s+Time:(.*?)\s+\|\s+PID:(.*?)\s+\|\s+Sleep:(.*?)\s+\|\s+(.*?)\s+@\s+(.*?)\s+\((.*?)\)\s+\|\s+URL\:(.*?)'] 8 | fields: 9 | infra: 10 | attack_scenario: @@ATTACKSCENARIO@@ 11 | log: 12 | type: rtops 13 | c2: 14 | program: poshc2 15 | log: 16 | type: events 17 | -------------------------------------------------------------------------------- /c2servers/filebeat/inputs.d/filebeat_sliver.yml: -------------------------------------------------------------------------------- 1 | - type: log 2 | scan_frequency: 5s 3 | enabled: true 4 | fields_under_root: true 5 | json.keys_under_root: true 6 | json.add_error_key: true 7 | paths: 8 | - /root/.sliver/logs/audit.json 9 | fields: 10 | infra: 11 | attack_scenario: @@ATTACKSCENARIO@@ 12 | log: 13 | type: rtops 14 | c2: 15 | program: sliver 16 | log: 17 | type: events 18 | -------------------------------------------------------------------------------- /c2servers/remove-redelkinstall-on-c2servers-USEATOWNRISK.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to remove RedELK on C2 servers 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | echo "" 10 | echo "" 11 | echo " !! USE AT OWN RISK !! " 12 | echo "" 13 | echo " This script will rudimentarily remove" 14 | echo " all kinds of things on your system." 15 | echo "" 16 | echo " Check the code before running. " 17 | echo "" 18 | echo " 5 sec to abort" 19 | echo "" 20 | sleep 5 21 | 22 | echo "[-] Stopping ELK services" 23 | service filebeat stop 24 | 25 | echo "[-] Nuking crontab for redelk user actions" 26 | rm -rf /cp /etc/cron.d/redelk* 27 | 28 | echo "[-] Removing apt-transport-https" 29 | apt-get remove -y apt-transport-https 30 | 31 | echo "[-] Removing FileBeat" 32 | apt-get purge -y filebeat 33 | 34 | echo "[-] Removing FileBeat directories" 35 | rm -rf /etc/filebeat 36 | rm -rf /usr/share/filebeat 37 | rm -rf /var/log/filebeat* 38 | rm -rf /var/lib/filebeat 39 | 40 | echo "[-] Removing scponly user" 41 | userdel -f -r scponly 42 | 43 | echo "[-] Nuking /usr/share/redelk directorie" 44 | rm -rf /usr/share/redelk 45 | 46 | echo "[-] Removing python script dependencies" 47 | apt-get remove -y python3-pil python3-pip 48 | 49 | echo "[-] Nuking RedELK log directory" 50 | rm -rf /var/log/redelk 51 | 52 | echo "[-] Removing other not used packages" 53 | apt -y autoremove 54 | 55 | echo "[-] Removing apt elastic file" 56 | rm -rf /etc/apt/sources.list.d/elastic-*.x.list 57 | 58 | echo "[*] Done. You can manually remove this directory as well if you like." 59 | echo "" 60 | -------------------------------------------------------------------------------- /c2servers/scripts/copydownloads_cobaltstrike.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to copy downloaded files from the CobaltStrike teamserver's downloads folder to the homedir of the scponly user. 5 | # It also adds "_orginal file name" to the file name, e.g. 9ce6fbfb1 becomes 9ce6fbfb1_testdoc.txt 6 | # 7 | # Author: Outflank B.V. / Marc Smeets 8 | # 9 | 10 | LOGFILE="/var/log/redelk/copydownloads.log" 11 | 12 | mkdir -p /home/scponly/cobaltstrike/downloads >> $LOGFILE 2>&1 13 | 14 | echo "`date` # Start CS downloads copy" >> $LOGFILE 2>&1 15 | 16 | for fileid in $(ls /root/cobaltstrike/server/downloads/ | grep -v '\.'); do 17 | orifilename=`grep -rn $fileid /root/cobaltstrike/server/logs/*/downloads.log|awk 'BEGIN {FS="\t"}; {print $6}'` 18 | if [ -z "$orifilename" ]; then orifilename="filenameunknown"; fi 19 | if [ ! -f "/home/scponly/cobaltstrike/downloads/${fileid}_${orifilename}" ]; then 20 | cp /root/cobaltstrike/server/downloads/${fileid} "/home/scponly/cobaltstrike/downloads/${fileid}_${orifilename}" 21 | chown scponly:scponly "/home/scponly/cobaltstrike/downloads/${fileid}_${orifilename}" 22 | fi 23 | done 24 | 25 | echo "`date` # Done CS" >> $LOGFILE 2>&1 26 | -------------------------------------------------------------------------------- /c2servers/scripts/copydownloads_outflankstage1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to copy downloaded files from the Outflank Stage teamserver's downloads folder to the homedir of the scponly user. 5 | # It also adds "_orginal file name" to the file name, e.g. 9ce6fbfb1 becomes 9ce6fbfb1_testdoc.txt 6 | # 7 | # Author: Outflank B.V. / Marc Smeets 8 | # 9 | 10 | LOGFILE="/var/log/redelk/copydownloads.log" 11 | 12 | mkdir -p /home/scponly/stage1/downloads >> $LOGFILE 2>&1 13 | 14 | echo "`date` # Start Stage1 downloads copy" >> $LOGFILE 2>&1 15 | 16 | for fileid in $(ls /root/stage1c2server/shared/downloads/ | grep -v '\.'); do 17 | orifilename=`grep -rn $fileid /root/stage1c2server/shared/logs/api/implant_logs/legacy_text/*|awk 'BEGIN {FS="taskResponse: Downloaded"}; {print $2}'|awk -F"] " '{print $2}'|tr -d ";"|awk '{$1=$1};1'` 18 | if [ -z "$orifilename" ]; then orifilename="filenameunknown"; fi 19 | if [ ! -f "/home/scponly/stage1/downloads/${fileid}_${orifilename}" ]; then 20 | cp /root/stage1c2server/shared/downloads/${fileid} "/home/scponly/stage1/downloads/${fileid}_${orifilename}" 21 | chown scponly:scponly "/home/scponly/stage1/downloads/${fileid}_${orifilename}" 22 | fi 23 | done 24 | 25 | echo "`date` # Done Stage1" >> $LOGFILE 2>&1 26 | -------------------------------------------------------------------------------- /c2servers/scripts/export_cobaltstrikedata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to start the exporting of data of Cobalt Strike data. Haevy lifting is done by exportcsdata.py, 5 | # this shell script only calls the python script and logs its running 6 | # 7 | # Author: Outflank B.V. / Marc Smeets 8 | # 9 | 10 | LOGFILE="/var/log/redelk/exportcobaltstrikesdata.log" 11 | CSDIR="/root/cobaltstrike/server" 12 | 13 | echo "`date` ######## Start CS data export" >> $LOGFILE 2>&1 14 | 15 | # Copy old listeners file for comparison (if exists) 16 | if [ -f "$CSDIR/data/export_listeners.tsv" ]; then 17 | cp $CSDIR/data/export_listeners.tsv $CSDIR/data/export_listeners.old.tsv 18 | fi 19 | 20 | # Export CS credentials and listeners 21 | cd $CSDIR/data && python3 /usr/share/redelk/bin/exportcsdata.py --credentials $CSDIR/data/credentials.bin --listeners $CSDIR/data/listeners.bin >> $LOGFILE 2>&1 22 | 23 | # Output listener changes in log file 24 | if [ -f "$CSDIR/data/export_listeners.old.tsv" ]; then 25 | diff $CSDIR/data/export_listeners.old.tsv $CSDIR/data/export_listeners.tsv --changed-group-format='%>' --unchanged-group-format='' >> $CSDIR/data/export_listeners.log 26 | else 27 | cat $CSDIR/data/export_listeners.tsv >> $CSDIR/data/export_listeners.log 28 | fi 29 | 30 | echo "`date` ######## Done with CS data export" >> $LOGFILE 2>&1 31 | -------------------------------------------------------------------------------- /certs/config.cnf.example: -------------------------------------------------------------------------------- 1 | [req] 2 | distinguished_name = req_distinguished_name 3 | x509_extensions = v3_req 4 | prompt = no 5 | 6 | [req_distinguished_name] 7 | C = MODIFYME, for example NL 8 | ST = MODIFYME, for example Noord-Holland 9 | L = MODIFYME, for example Amsterdam 10 | O = MODIFYME, for example Outflank B.V. 11 | OU = MODIFYME, for example IT-OPS 12 | CN = MODIFYME, for example outflank.nl 13 | emailAddress = MODIFYME, for example totallynotavirus@outflank.nl 14 | 15 | [v3_ca] 16 | subjectKeyIdentifier = hash 17 | authorityKeyIdentifier = keyid:always,issuer:always 18 | basicConstraints = CA:TRUE 19 | 20 | [v3_req] 21 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment 22 | extendedKeyUsage = serverAuth 23 | subjectAltName = @alt_names 24 | 25 | [alt_names] 26 | # Enter the valid IP or DNS where the teamservers and redirectors can reach your ELK server in the fields below. If not done correctly, Logstash on your ELK server will crash with cryptic errors. 27 | DNS.1 = dnsnameofyourredelkserver 28 | DNS.2 = someseconddnsname 29 | IP.1 = 123.123.123.123 30 | -------------------------------------------------------------------------------- /elkserver/.env.tmpl: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Docker file for RedELK 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi (@fastlorenzo) 8 | # 9 | 10 | ## RedELK docker images variables 11 | #REDELKVERSION={{REDELKVERSION}} 12 | REDELKVERSION=master 13 | REDELKREPO=outflanknl 14 | 15 | 16 | ## Docker generic variables 17 | COMPOSE_PROJECT_NAME=redelk 18 | # Defines the maximum log size per container (https://docs.docker.com/compose/compose-file/compose-file-v3/#logging) 19 | LOG_MAX_SIZE=200m 20 | LOG_MAX_FILE=1 21 | 22 | ## Variables for ES, Logstash and Kibana 23 | CERTS_DIR_ES=/usr/share/elasticsearch/config/certificates 24 | CERTS_DIR_KBN=/usr/share/kibana/config/certificates 25 | CERTS_DIR_LOGSTASH=/usr/share/logstash/config/certificates 26 | CERTS_DIR_REDELK=/usr/share/logstash/redelk-main/certs 27 | 28 | 29 | ## Below you can configure the location to the certificates used in logstash 30 | CERTS_LOGSTASH_INPUT_KEY=/usr/share/logstash/redelk-main/certs/elkserver.key 31 | CERTS_LOGSTASH_INPUT_CRT=/usr/share/logstash/redelk-main/certs/elkserver.crt 32 | CERTS_LOGSTASH_OUTPUT_CA=/usr/share/logstash/config/certificates/ca/ca.crt 33 | CREDS_kibana_system={{CREDS_kibana_system}} 34 | CREDS_logstash_system={{CREDS_logstash_system}} 35 | CREDS_redelk_ingest={{CREDS_redelk_ingest}} 36 | CREDS_redelk={{CREDS_redelk}} 37 | ELASTIC_PASSWORD={{ELASTIC_PASSWORD}} 38 | ES_URL=https://redelk-elasticsearch:9200 39 | KBN_XPACK_ENCRYPTEDSAVEDOBJECTS={{KBN_XPACK_ENCRYPTEDSAVEDOBJECTS}} 40 | 41 | 42 | ## Neo4J / Bloodhound specific variables. 43 | NEO4J_AUTH=neo4j/{{NEO4J_PASSWORD}} 44 | # NEO4J_MEMORY is used to instruct Neo4J the amount of memory to use. It is dynamically determined and set by the install-elkserver.sh script. 45 | # You can manually override here, e.g. 1G (upper case) 46 | NEO4J_dbms_memory_heap_initial__size={{NEO4J_MEMORY}} 47 | NEO4J_dbms_memory_heap_max__size={{NEO4J_MEMORY}} 48 | NEO4J_dbms_memory_pagecache_size={{NEO4J_MEMORY}} 49 | # Allow upgrades of neo4j data (useful when importing external data) 50 | NEO4J_ALLOW_UPGRADE=true 51 | 52 | ## Bloodhound Community Edition specific variables 53 | # Select the image tag to use (latest, edge, or version number) 54 | BLOODHOUND_TAG=latest 55 | # Postgres auth configuration 56 | POSTGRES_USER=bloodhound 57 | POSTGRES_PASSWORD={{PGSQL_PASSWORD}} 58 | POSTGRES_DATABASE=bloodhound 59 | # Data directory for neo4j 60 | # Uncomment if you want a filesystem mount for your neo4j data in the current directory 61 | #NEO4J_DATA_MOUNT=./neo4j/data 62 | # Port forwards 63 | # You can also use the form "127.0.0.1:8080" if you aren't running in a virtual environment (like WSL2) 64 | # and only want this accessible on localhost 65 | BLOODHOUND_PORT=127.0.0.1:8080 66 | #POSTGRES_PORT=5432 67 | NEO4J_DB_PORT=7687 68 | NEO4J_WEB_PORT=7474 69 | 70 | # BloodHound Configuration Parameters 71 | # Uncomment if you want to disable cypher quality control 72 | #bhe_disable_cypher_qc=false 73 | 74 | 75 | ## Variables for NGINX certificates mounts 76 | CERTS_DIR_NGINX=/etc/nginx/certs 77 | # Defaults to certbot mount 78 | CERTS_DIR_NGINX_LOCAL={{CERTS_DIR_NGINX_LOCAL}} 79 | CERTS_DIR_NGINX_CA=/etc/nginx/ca_certs 80 | # Defaults to certificates generated by ES script (RedELK CA) 81 | CERTS_DIR_NGINX_CA_LOCAL={{CERTS_DIR_NGINX_CA_LOCAL}} 82 | # The following variables are used in the NGINX configuration file 83 | # By default they use the certificates generated by certbot (self-signed if EXTERNAL_DOMAIN is invalid) 84 | TLS_NGINX_CRT_PATH={{TLS_NGINX_CRT_PATH}} 85 | TLS_NGINX_KEY_PATH={{TLS_NGINX_KEY_PATH}} 86 | # The following variable allows to set a CA in NGINX config for mutual TLS authentication 87 | # Defaults to RedELK CA 88 | TLS_NGINX_CA_PATH={{TLS_NGINX_CA_PATH}} 89 | 90 | 91 | ## Let's Encrypt config 92 | EXTERNAL_DOMAIN={{EXTERNAL_DOMAIN}} 93 | LE_EMAIL={{LE_EMAIL}} 94 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Dockerfile for RedELK base image 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi 8 | # 9 | 10 | FROM phusion/baseimage:18.04-1.0.0 11 | LABEL maintainer="Outflank B.V. / Marc Smeets" 12 | LABEL description="RedELK Base" 13 | 14 | # Install required packages 15 | RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ 16 | DEBIAN_FRONTEND=noninteractive apt-get -y install rsync python3-pil python3-pip python3-setuptools && \ 17 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 18 | 19 | # Copy relevant install data 20 | RUN mkdir -p /root/redelkinstalldata/ 21 | COPY ./redelkinstalldata/ /root/redelkinstalldata/ 22 | 23 | # Init script 24 | RUN mkdir -p /etc/my_init.d && \ 25 | cp /root/redelkinstalldata/42_redelk-base-docker-init.sh /etc/my_init.d/42_redelk-base-docker-init.sh && \ 26 | chmod +x /etc/my_init.d/42_redelk-base-docker-init.sh 27 | 28 | # copy relevant scripts to redelk script working dir 29 | RUN mkdir -p /usr/share/redelk/bin && \ 30 | cp -r /root/redelkinstalldata/scripts/* /usr/share/redelk/bin/ && \ 31 | chmod -R 775 /usr/share/redelk/bin/* 32 | 33 | # Install python requirements 34 | RUN pip3 install -r /usr/share/redelk/bin/requirements.txt 35 | 36 | CMD ["/sbin/my_init"] 37 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/docker/redelk-base/redelkinstalldata/scripts/__init__.py -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | Script to load the config file 7 | 8 | Authors: 9 | - Outflank B.V. / Mark Bergman (@xychix) 10 | - Lorenzo Bernardi (@fastlorenzo) 11 | """ 12 | 13 | import json 14 | import logging 15 | 16 | with open("/etc/redelk/config.json", encoding="utf-8") as json_data: 17 | # pylint: disable=invalid-name 18 | data = json.load(json_data) 19 | 20 | # -- logging 21 | # CRITICAL, 50 22 | # ERROR, 40 23 | # WARNING, 30 24 | # INFO, 20 25 | # DEBUG, 10 26 | # NOTSET, 0 27 | 28 | LOGLEVEL = logging.WARN 29 | if "loglevel" in data: 30 | LOGLEVEL = data["loglevel"] 31 | 32 | # -- directory for cache files (including shelves) 33 | TEMP_DIR = "/tmp" 34 | if "tempDir" in data: 35 | TEMP_DIR = data["tempDir"] 36 | 37 | # -- Notifications 38 | # pylint: disable=invalid-name 39 | notifications = { 40 | "email": { 41 | "enabled": False, 42 | "smtp": {"host": "localhost", "port": 25, "login": "", "pass": ""}, 43 | "from": "", 44 | "to": [], 45 | }, 46 | "msteams": {"enabled": False, "webhook_url": ""}, 47 | "slack": {"enabled": False, "webhook_url": ""}, 48 | } 49 | if "notifications" in data: 50 | for n in data["notifications"]: 51 | notifications[n] = data["notifications"][n] 52 | 53 | # -- Alarms 54 | # pylint: disable=invalid-name 55 | alarms = { 56 | "alarm_filehash": { 57 | "enabled": False, 58 | "interval": 300, 59 | # Virustotal API 60 | "vt_api_key": "", 61 | # IBM X-Force API (can be retreived from a sample call on their swagger test site) 62 | "ibm_basic_auth": "", 63 | # Hybrid Analysis API 64 | "ha_api_key": "", 65 | }, 66 | "alarm_httptraffic": { 67 | "enabled": False, 68 | "interval": 310, 69 | "notify_interval": 86400, # Only notify on the same IP hit every 24h by default 70 | }, 71 | "alarm_useragent": {"enabled": False, "interval": 320}, 72 | "alarm_dummy": {"enabled": False, "interval": 300}, 73 | "alarm_manual": {"enabled": False, "interval": 300}, 74 | "alarm_backendalarm": {"enabled": False, "interval": 320}, 75 | } 76 | if "alarms" in data: 77 | for a in data["alarms"]: 78 | alarms[a] = data["alarms"][a] 79 | 80 | # -- Enrichments modules 81 | # pylint: disable=invalid-name 82 | enrich = { 83 | "enrich_csbeacon": {"enabled": True, "interval": 300}, 84 | "enrich_stage1": {"enabled": True, "interval": 300}, 85 | 'enrich_sliver': {"enabled": True, 'interval': 300}, 86 | "enrich_greynoise": { 87 | "enabled": True, 88 | "interval": 310, 89 | "cache": 86400, # Only query for the same IP hit every 24h by default 90 | # Greynoise Community API Key - Default RedELK key if none provided 91 | "api_key": "cEwJeLyDkNSXzabKNvzJSzZjZW0xEJYSYvf2nfhmmaXQHfCA8bJb49AvI3DF5Tlx", 92 | }, 93 | "enrich_tor": {"enabled": True, "interval": 320, "cache": 3600}, 94 | "enrich_iplists": {"enabled": True, "interval": 330}, 95 | "enrich_synciplists": {"enabled": True, "interval": 360}, 96 | "enrich_syncdomainslists": {"enabled": True, "interval": 355}, 97 | "enrich_domainscategorization": { 98 | "enabled": True, 99 | "interval": 345, 100 | # IBM X-Force API (can be retreived from a sample call on their swagger test site) 101 | "ibm_basic_auth": "", 102 | # Virustotal API 103 | "vt_api_key": "", 104 | }, 105 | } 106 | if "enrich" in data: 107 | for e in data["enrich"]: 108 | enrich[e] = data["enrich"][e] 109 | 110 | # pylint: disable=invalid-name 111 | es_connection = ["http://localhost:9200"] 112 | if "es_connection" in data: 113 | es_connection = data["es_connection"] 114 | 115 | project_name = data["project_name"] if "project_name" in data else "redelk-project" 116 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/getremotelogs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of Red ELK 4 | # Script to get remote C2 logs via rsync 5 | # The output is saved in /var/www/html/c2logs/$hostname/logs/ 6 | # 7 | # Author: Outflank B.V. / Marc Smeets 8 | # 9 | 10 | LOGFILE="/var/log/redelk/getremotelogs.log" 11 | 12 | if [ $# -lt 3 ] ; then 13 | echo "[X] Error - need IP or full DNS name of system to get remote logs from as 1st parameter." 14 | echo "[X] Error - need the remote system's filebeats hostname as 2nd parameter." 15 | echo "[X] Error - need the username to connect with as 3rd parameter." 16 | echo "[X] Optional - need the remote system's ssh port to get logs as 4th parameter. Defaults to '22'" 17 | echo "[X] Optional - remote base path to get the logs as 5th parameter. Defaults to '~' (HOME dir)" 18 | echo "Incorrect amount of parameters" >> $LOGFILE 2>&1 19 | exit 1 20 | fi 21 | mkdir -p /var/www/html/c2logs/"$2" >> $LOGFILE 2>&1 22 | 23 | echo "$(date) ######## Start of rsync to $1" >> $LOGFILE 2>&1 24 | rsync -rxv --append-verify -e 'ssh -p '"${4:-22}"' -o "StrictHostKeyChecking=no" -i /home/redelk/.ssh/id_rsa' "$3"@"$1":${5:-"~"}/ /var/www/html/c2logs/"$2" >> $LOGFILE 2>&1 25 | echo "$(date) ######## Done with rsync" >> $LOGFILE 2>&1 26 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/makethumbnail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of Red ELK 5 | 6 | Script to generate thumbnails of images 7 | The output is saved next to input file as ".thumb.jpg" 8 | 9 | Authors: 10 | - Outflank B.V. / Marc Smeets 11 | - Lorenzo Bernardi (@fastlorenzo) 12 | """ 13 | 14 | import sys 15 | import os 16 | import logging 17 | from PIL import Image 18 | 19 | logger = logging.getLogger("makethumbnail") 20 | 21 | try: 22 | 23 | path = sys.argv[1] 24 | BAS_HEIGHT = 300 25 | for root, dirs, files in os.walk(path): 26 | for file in files: 27 | if file.endswith(".jpg") and not file.endswith("thumb.jpg"): 28 | file_in = os.path.join(root, file) 29 | file_out = f"{file_in}.thumb.jpg" 30 | 31 | if not os.path.exists(file_out): 32 | img = Image.open(file_in) 33 | w_percent = BAS_HEIGHT / float(img.size[1]) 34 | v_size = int((float(img.size[0]) * float(w_percent))) 35 | img = img.resize((v_size, BAS_HEIGHT), Image.ANTIALIAS) 36 | img.save(file_out) 37 | # pylint: disable=broad-except 38 | except Exception as error: 39 | error = sys.exc_info()[1] 40 | logging.log("Error ", str(error)) 41 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/__init__.py -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/alarm_backendalarm/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This check queries for calls to backends that have alarm in their name 7 | 8 | Authors: 9 | - Outflank B.V. / Mark Bergman (@xychix) 10 | - Lorenzo Bernardi (@fastlorenzo) 11 | """ 12 | import logging 13 | 14 | from modules.helpers import get_initial_alarm_result, get_query 15 | 16 | info = { 17 | "version": 0.1, 18 | "name": "backend alarm module", 19 | "alarmmsg": "TRAFFIC TO ANY BACKEND WITH THE WORD ALARM IN THE NAME", 20 | "description": "This check queries for calls to backends that have alarm in their name", 21 | "type": "redelk_alarm", # Could also contain redelk_enrich if it was an enrichment module 22 | "submodule": "alarm_backendalarm", 23 | } 24 | 25 | 26 | class Module: 27 | """backend alarm module 28 | This check queries for calls to backends that have alarm in their name 29 | """ 30 | 31 | def __init__(self): 32 | self.logger = logging.getLogger(info["submodule"]) 33 | 34 | def run(self): 35 | """Run the alarm module""" 36 | ret = get_initial_alarm_result() 37 | ret["info"] = info 38 | ret["fields"] = [ 39 | "@timestamp", 40 | "source.ip", 41 | "http.headers.useragent", 42 | "source.cdn.ip", 43 | "redir.frontend.name", 44 | "redir.backend.name", 45 | "infra.attack_scenario", 46 | ] 47 | ret["groupby"] = ["source.ip", "http.headers.useragent"] 48 | report = self.alarm_check() 49 | ret["hits"]["hits"] = report["hits"] 50 | ret["hits"]["total"] = len(report["hits"]) 51 | self.logger.info( 52 | "finished running module. result: %s hits", ret["hits"]["total"] 53 | ) 54 | return ret 55 | 56 | # pylint: disable=no-self-use 57 | def alarm_check(self): 58 | """This check queries for calls to backends that have *alarm* in their name""" 59 | es_query = f'redir.backend.name:*alarm* AND NOT tags:{info["submodule"]}' 60 | es_results = get_query(es_query, 10000) 61 | report = {"hits": es_results} 62 | return report 63 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/alarm_dummy/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This alarm always triggers. Only use for testing purposes. 7 | 8 | Authors: 9 | - Lorenzo Bernardi (@fastlorenzo) 10 | """ 11 | import logging 12 | from modules.helpers import get_initial_alarm_result, get_query 13 | 14 | info = { 15 | "version": 0.1, 16 | "name": "dummy alarm", 17 | "alarmmsg": "ALARM GENERATED BY DUMMY", 18 | "description": "This alarm always triggers. Only use for testing purposes.", 19 | "type": "redelk_alarm", 20 | "submodule": "alarm_dummy", 21 | } 22 | 23 | 24 | class Module: 25 | """dummy alarm module 26 | This check returns the last IOC in rtops-* that have not been alarmed yet 27 | """ 28 | 29 | def __init__(self): 30 | self.logger = logging.getLogger(info["submodule"]) 31 | 32 | def run(self): 33 | """Run the alarm module""" 34 | ret = get_initial_alarm_result() 35 | ret["info"] = info 36 | ret["fields"] = [ 37 | "agent.hostname", 38 | "@timestamp", 39 | "host.name", 40 | "user.name", 41 | "ioc.type", 42 | "file.name", 43 | "file.hash.md5", 44 | "ioc.domain", 45 | "c2.message", 46 | "alarm.alarm_filehash", 47 | ] 48 | ret["groupby"] = [] 49 | for result in self.alarm_dummy(): 50 | ret["hits"]["hits"].append(result) 51 | ret["mutations"][result["_id"]] = {"test": "extra_data"} 52 | ret["hits"]["total"] += 1 53 | 54 | self.logger.info( 55 | "finished running module. result: %s hits", ret["hits"]["total"] 56 | ) 57 | self.logger.debug(ret) 58 | return ret 59 | 60 | def alarm_dummy(self): 61 | """This check returns the last IOC in rtops-* that have not been alarmed yet""" 62 | es_query = "c2.log.type:ioc AND NOT tags:alarm_*" 63 | es_results = get_query(es_query, 1, index="rtops-*") 64 | self.logger.debug(es_results) 65 | 66 | return es_results 67 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/alarm_httptraffic/readme.md: -------------------------------------------------------------------------------- 1 | # Test1 2 | 3 | each module needs to have 4 | - version() function 5 | info: 6 | { 7 | 'version':0.1, 8 | 'name':'test1 module', 9 | 'descriptoin':'test1 module description', 10 | 'type':'redelk_alarm', # Could also contain redelk_enrich if it was an enrichment module 11 | } 12 | 13 | - run() function, just run what you need to run. 14 | returns: 15 | { 16 | 'info':$info, 17 | 'hits': 18 | { 19 | hits:[] #list of ID fields in ES 20 | total:999 # number of hits 21 | } 22 | 'indices':[] # list of indices that the hits are in 23 | } 24 | 25 | 26 | The list of hits contain per hit: 27 | { 28 | 'id': {Elastic ID} 29 | 'source':{full line} 30 | fields:{fields we want to report} 31 | message:"Alarm on $ip hitting c2_backend and unknown" 32 | } 33 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/alarm_lastline/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This alarm always triggers. It lists the last 2 redirtraffic lines as hit 7 | 8 | Authors: 9 | - Outflank B.V. / Mark Bergman (@xychix) 10 | - Lorenzo Bernardi (@fastlorenzo) 11 | """ 12 | import logging 13 | 14 | from modules.helpers import get_hits_count, get_initial_alarm_result, get_query 15 | 16 | info = { 17 | "version": 0.1, 18 | "name": "lastline alarm module", 19 | "alarmmsg": "ALARM GENERATED BY LASTLINE", 20 | "description": "This alarm always triggers. It lists the last 2 redirtraffic lines as hit", 21 | "type": "redelk_alarm-NOTINUSE", 22 | "submodule": "alarm_lastline", 23 | } 24 | 25 | 26 | class Module: 27 | """lastline alarm module""" 28 | 29 | def __init__(self): 30 | self.logger = logging.getLogger(info["submodule"]) 31 | 32 | def run(self): 33 | """Run the alarm module""" 34 | ret = get_initial_alarm_result() 35 | ret["info"] = info 36 | ret["fields"] = [ 37 | "source.ip", 38 | "source.cdn.ip", 39 | "source.geo.country_name", 40 | "source.as.organization.name", 41 | "redir.frontend.name", 42 | "redir.backend.name", 43 | "infra.attack_scenario", 44 | "tags", 45 | "redir.timestamp", 46 | ] 47 | ret["groupby"] = ["source.ip"] 48 | report = self.alarm_check() 49 | ret["hits"]["hits"] = report["hits"] 50 | ret["hits"]["total"] = len(report["hits"]) 51 | self.logger.info( 52 | "finished running module. result: %s hits", ret["hits"]["total"] 53 | ) 54 | return ret 55 | 56 | # pylint: disable=no-self-use 57 | def alarm_check(self): 58 | """This check queries for IP's that aren't listed in any iplist* but do talk to c2* paths on redirectors""" 59 | es_query = "*" 60 | i = get_hits_count(es_query) 61 | i = min(i, 10000) 62 | es_result = get_query(es_query, i) 63 | report = {} 64 | report["hits"] = [] 65 | report["hits"].append(es_result[0]) 66 | report["hits"].append(es_result[1]) 67 | return report 68 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/alarm_useragent/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This check queries for UA\'s that are listed in any blacklist_useragents.conf and do talk to c2* paths on redirectors 7 | 8 | Authors: 9 | - Outflank B.V. / Mark Bergman (@xychix) 10 | - Lorenzo Bernardi (@fastlorenzo) 11 | """ 12 | import logging 13 | 14 | from modules.helpers import get_initial_alarm_result, get_query 15 | 16 | info = { 17 | "version": 0.1, 18 | "name": "User-agent module", 19 | "alarmmsg": "VISIT FROM BLACKLISTED USERAGENT TO C2_*", 20 | "description": "This check queries for UA's that are listed in any blacklist_useragents.conf and do talk to c2* paths on redirectors", 21 | "type": "redelk_alarm", # Could also contain redelk_enrich if it was an enrichment module 22 | "submodule": "alarm_useragent", 23 | } 24 | 25 | 26 | class Module: 27 | """User-agent module""" 28 | 29 | def __init__(self): 30 | self.logger = logging.getLogger(info["submodule"]) 31 | 32 | def run(self): 33 | """Run the alarm module""" 34 | ret = get_initial_alarm_result() 35 | ret["info"] = info 36 | ret["fields"] = [ 37 | "agent.hostname", 38 | "@timestamp", 39 | "source.ip", 40 | "http.headers.useragent", 41 | "source.cdn.ip", 42 | "redir.frontend.name", 43 | "redir.backend.name", 44 | "infra.attack_scenario", 45 | ] 46 | ret["groupby"] = ["source.ip", "http.headers.useragent"] 47 | report = self.alarm_check() 48 | ret["hits"]["hits"] = report["hits"] 49 | ret["hits"]["total"] = len(report["hits"]) 50 | self.logger.info( 51 | "finished running module. result: %s hits", ret["hits"]["total"] 52 | ) 53 | return ret 54 | 55 | def alarm_check(self): # pylint: disable=no-self-use 56 | """This check queries for UA's that are listed in any blacklist_useragents.conf and do talk to c2* paths on redirectors 57 | We will dig trough ALL data finding specific IP related lines and tag them reading the useragents we trigger on.""" 58 | file_name = "/etc/redelk/rogue_useragents.conf" 59 | with open(file_name, encoding="utf-8") as file: 60 | content = file.readlines() 61 | ua_list = [] 62 | for line in content: 63 | if not line.startswith("#"): 64 | ua_list.append(line.strip()) 65 | keywords = ua_list 66 | es_subquery = "" 67 | # add keywords (UA's) to query 68 | for keyword in keywords: 69 | if es_subquery == "": 70 | es_subquery = f"(http.headers.useragent:{keyword}" 71 | else: 72 | es_subquery = es_subquery + f" OR http.headers.useragent:{keyword}" 73 | es_subquery = es_subquery + ") " 74 | # q = "%s AND redir.backendname:c2* AND tags:enrich_* AND NOT tags:alarm_* "%qSub 75 | es_query = ( 76 | f"{es_subquery} AND redir.backend.name:c2* AND NOT tags:alarm_useragent" 77 | ) 78 | 79 | es_results = get_query(es_query, 10000) 80 | report = {} 81 | report["hits"] = es_results 82 | return report 83 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/email/redelk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/email/redelk.png -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/email/redelk_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/email/redelk_white.png -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/enrich_domainscategorization/cat_bluecoat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This script checks for domain categorization data in Bluecoat 7 | 8 | Adapted from Chameleon's script 9 | 10 | Authors: 11 | - Lorenzo Bernardi (@fastlorenzo) 12 | """ 13 | 14 | import logging 15 | import json 16 | import traceback 17 | import requests 18 | 19 | 20 | class Bluecoat: 21 | """This script checks for domain categorization data in Bluecoat""" 22 | 23 | def __init__(self): 24 | self.logger = logging.getLogger("enrich_domaincategorization.bluecoat") 25 | 26 | def check_domain(self, domain): 27 | """Check the domain categoriation in Bluecoat""" 28 | # Category checking lifted from CatMyFish 29 | # https://github.com/Mr-Un1k0d3r/CatMyFish/blob/master/CatMyFish.py 30 | self.logger.debug("Checking domain %s", domain) 31 | 32 | session = requests.session() 33 | url = "https://sitereview.bluecoat.com/resource/lookup" 34 | cookies = {"XSRF-TOKEN": "028e5984-50bf-4c00-ad38-87d19957201a"} 35 | headers = { 36 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0", 37 | "Accept": "application/json, text/plain, */*", 38 | "Accept-Language": "en_US", 39 | "Accept-Encoding": "gzip, deflate", 40 | "Referer": "https://sitereview.bluecoat.com/", 41 | "X-XSRF-TOKEN": "028e5984-50bf-4c00-ad38-87d19957201a", 42 | "Content-Type": "application/json; charset=utf-8", 43 | "Connection": "close", 44 | } 45 | data = { 46 | "captcha": "", 47 | "key": "", 48 | "phrase": "RXZlbiBpZiB5b3UgYXJlIG5vdCBwYXJ0IG9mIGEgY29tbWVyY2lhbCBvcmdhbml6YXRpb24sIHNjcmlwdGluZyBhZ2FpbnN0IFNpdGUgUmV2aWV3IGlzIHN0aWxsIGFnYWluc3QgdGhlIFRlcm1zIG9mIFNlcnZpY2U=", 49 | "source": "new lookup", 50 | "url": domain, 51 | } 52 | response = session.post(url, headers=headers, cookies=cookies, json=data) 53 | 54 | try: 55 | json_data = json.loads(response.content) 56 | if "errorType" in json_data: 57 | if json_data["errorType"] == "captcha": 58 | self.logger.warning("BlueCoat blocked us :(") 59 | return "Blocked by BlueCoat" 60 | 61 | category = [] 62 | self.logger.debug("BlueCoat response: %s", json_data) 63 | for entry in json_data["categorization"]: 64 | category.append(entry["name"]) 65 | cat = ", ".join(category) 66 | print("\033[1;32m[-] Your site is categorised as: " + cat + "\033[0;0m") 67 | return cat 68 | except Exception: # pylint: disable=broad-except 69 | self.logger.error( 70 | "Error checking domain %s: %s", domain, traceback.print_exc() 71 | ) 72 | 73 | return False 74 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/enrich_domainscategorization/cat_ibmxforce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This script checks for domain categorization data in IBM X-Force Exchange 7 | 8 | Adapted from Chameleon's script 9 | 10 | Authors: 11 | - Lorenzo Bernardi (@fastlorenzo) 12 | """ 13 | 14 | import logging 15 | import traceback 16 | import requests 17 | 18 | from config import enrich 19 | from modules.helpers import get_value 20 | 21 | 22 | class IBMXForce: 23 | """This script checks for domain categorization data in IBM X-Force Exchange""" 24 | 25 | def __init__(self): 26 | self.logger = logging.getLogger("enrich_domaincategorization.ibmxforce") 27 | self.ibm_basic_auth = get_value( 28 | "enrich_domainscategorization.ibm_basic_auth", enrich 29 | ) 30 | 31 | def check_domain(self, domain): 32 | """Check the domain categoriation in IBM X-Force Exchange""" 33 | result = { 34 | "domain": domain, 35 | "categories": [], 36 | "status": "unknown", 37 | "response_code": -1, 38 | "extra_data": {}, 39 | } 40 | 41 | self.logger.debug("Checking domain %s", domain) 42 | 43 | session = requests.session() 44 | url = f"https://api.xforce.ibmcloud.com/api/url/{domain}" 45 | headers = { 46 | "Accept": "application/json", 47 | "Authorization": self.ibm_basic_auth, 48 | } 49 | 50 | response = session.get(url, headers=headers, verify=False) 51 | 52 | self.logger.debug("Response: %s", response.content) 53 | result["response_code"] = response.status_code 54 | 55 | # Domain was not found in IBM X-Force Exchange 56 | if response.status_code == 404: 57 | self.logger.debug( 58 | "IBM x-Force does not have entries for the domain %s!", domain 59 | ) 60 | result["status"] = "not_found" 61 | 62 | # Domain was found in IBM X-Force Exchange 63 | elif response.status_code == 200: 64 | 65 | try: 66 | json_data = response.json() 67 | self.logger.debug("Json Response: %s", json_data) 68 | result["status"] = "found" 69 | for category in get_value("result.cats", json_data, {}): 70 | result["categories"].append(category) 71 | except Exception: # pylint: disable=broad-except 72 | self.logger.error( 73 | "Error checking domain %s: %s", domain, traceback.print_exc() 74 | ) 75 | self.logger.error(traceback.format_exc()) 76 | result["status"] = "error" 77 | 78 | return result 79 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/enrich_domainscategorization/cat_mcafee.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This script checks for domain categorization data in MCAfee 7 | 8 | Adapted from Chameleon's script 9 | 10 | Authors: 11 | - Lorenzo Bernardi (@fastlorenzo) 12 | """ 13 | 14 | import logging 15 | import traceback 16 | import requests 17 | 18 | from bs4 import BeautifulSoup 19 | 20 | 21 | class MCafee: 22 | """This script checks for domain categorization data in MCAfee""" 23 | 24 | def __init__(self): 25 | self.logger = logging.getLogger("enrich_domaincategorization.mcafee") 26 | 27 | def check_domain(self, domain): 28 | """Check the domain categoriation in MCAfee""" 29 | result = { 30 | "domain": domain, 31 | "categories": [], 32 | "status": "unknown", 33 | "response_code": -1, 34 | "extra_data": {}, 35 | } 36 | 37 | self.logger.debug("Checking domain %s", domain) 38 | 39 | session = requests.session() 40 | 41 | try: 42 | # Get anti-automation tokens 43 | headers = { 44 | "User-Agent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)", 45 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 46 | "Accept-Language": "en-GB,en;q=0.5", 47 | } 48 | session.headers.update(headers) 49 | base_url = "https://sitelookup.mcafee.com/" 50 | response = session.get(base_url) 51 | bs_parsed = BeautifulSoup(response.text, "html.parser") 52 | 53 | form = bs_parsed.find("form", {"class": "contactForm"}) 54 | e_token = form.find("input", {"name": "e"}).get("value") 55 | c_token = form.find("input", {"name": "c"}).get("value") 56 | 57 | # Check domain with MCAfee 58 | headers["Referer"] = base_url 59 | session.headers.update(headers) 60 | payload = { 61 | "sid": (None, ""), 62 | "e": (None, e_token), 63 | "c": (None, c_token), 64 | "p": (None, ""), 65 | "action": (None, "checksingle"), 66 | "product": (None, "13-ts-3"), 67 | "url": (None, domain), 68 | } 69 | response = session.post( 70 | "https://sitelookup.mcafee.com/en/feedback/url", 71 | headers=headers, 72 | files=payload, 73 | ) 74 | result["response_code"] = response.status_code 75 | 76 | # Parse response 77 | bs_parsed = BeautifulSoup(response.content, "html.parser") 78 | form = bs_parsed.find("form", {"class": "contactForm"}) 79 | 80 | results_table = bs_parsed.find("table", {"class": "result-table"}) 81 | 82 | td_cat = results_table.find_all("td") 83 | categories = td_cat[len(td_cat) - 2].text 84 | 85 | # Split categories by "- " and remove empty strings 86 | categories = categories.strip().split("- ")[1:] 87 | 88 | self.logger.debug("Categories: %s", categories) 89 | result["categories"] = categories 90 | 91 | if "Uncategorized URL" in categories: 92 | result["status"] = "not_found" 93 | else: 94 | result["status"] = "found" 95 | 96 | except Exception: # pylint: disable=broad-except 97 | # TODO: Add better exception handling 98 | self.logger.error( 99 | "Error checking domain %s: %s", domain, traceback.print_exc() 100 | ) 101 | self.logger.error(traceback.format_exc()) 102 | result["status"] = "error" 103 | 104 | return result 105 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/msteams/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This connector sends RedELK alerts via Microsoft Teams 7 | 8 | Authors: 9 | - Lorenzo Bernardi (@fastlorenzo) 10 | """ 11 | import logging 12 | import pymsteams 13 | 14 | import config 15 | from modules.helpers import get_value, pprint 16 | 17 | info = { 18 | "version": 0.1, 19 | "name": "msteams connector", 20 | "description": "This connector sends RedELK alerts via Microsoft Teams", 21 | "type": "redelk_connector", 22 | "submodule": "msteams", 23 | } 24 | 25 | 26 | class Module: # pylint: disable=too-few-public-methods 27 | """msteams connector module""" 28 | 29 | def __init__(self): 30 | self.logger = logging.getLogger(info["submodule"]) 31 | 32 | def send_alarm(self, alarm): 33 | """Send the alarm notification""" 34 | tmsg = pymsteams.connectorcard(config.notifications["msteams"]["webhook_url"]) 35 | description = alarm["info"]["description"] 36 | if len(alarm["groupby"]) > 0: 37 | description += f'\n *Please note that the items below have been grouped by: {pprint(alarm["groupby"])}*' 38 | tmsg.text(description) 39 | tmsg.color("red") 40 | try: 41 | for hit in alarm["hits"]["hits"]: 42 | tcs = pymsteams.cardsection() 43 | tcs.disableMarkdown() 44 | i = 0 45 | title = hit["_id"] 46 | while i < len(alarm["groupby"]): 47 | val = get_value(f'_source.{alarm["groupby"][i]}', hit) 48 | if i == 0: 49 | title = val 50 | else: 51 | title = f"{title} / {val}" 52 | i += 1 53 | tcs.activityTitle(f"Alarm on item: {title}") 54 | # tcs.activitySubtitle(alarm['info']['description']) 55 | for field in alarm["fields"]: 56 | val = get_value(f"_source.{field}", hit) 57 | tcs.addFact(field, pprint(val)) 58 | tmsg.addSection(tcs) 59 | # pylint: disable=broad-except 60 | except Exception as error: 61 | self.logger.exception(error) 62 | 63 | tmsg.title( 64 | f'[{config.project_name}] Alarm from {alarm["info"]["name"]} [{alarm["hits"]["total"]} hits]' 65 | ) 66 | tmsg.send() 67 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/modules/slack/module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Part of RedELK 5 | 6 | This connector sends RedELK alerts via Slack 7 | 8 | Authors: 9 | - Matthijs Vos (@matthijsy) 10 | """ 11 | import logging 12 | from slack_sdk.webhook import WebhookClient 13 | from modules.helpers import get_value, pprint 14 | import config 15 | 16 | info = { 17 | "version": 0.1, 18 | "name": "slack connector", 19 | "description": "This connector sends RedELK alerts via Slack", 20 | "type": "redelk_connector", 21 | "submodule": "slack", 22 | } 23 | 24 | 25 | class Module: # pylint: disable=too-few-public-methods 26 | """slack connector module""" 27 | 28 | def __init__(self): 29 | self.logger = logging.getLogger(info["submodule"]) 30 | 31 | def send_alarm(self, alarm): 32 | """Send the alarm notification""" 33 | description = alarm["info"]["description"] 34 | if len(alarm["groupby"]) > 0: 35 | description += f'\n _Please note that the items below have been grouped by: {alarm["groupby"]}_' 36 | 37 | blocks = [ 38 | { 39 | "type": "section", 40 | "text": { 41 | "type": "mrkdwn", 42 | "text": f'*[{config.project_name}] Alarm from {alarm["info"]["name"]} [{alarm["hits"]["total"]} hits]*\n{description}', 43 | }, 44 | }, 45 | {"type": "divider"}, 46 | ] 47 | 48 | try: 49 | for hit in alarm["hits"]["hits"]: 50 | i = 0 51 | title = hit["_id"] 52 | while i < len(alarm["groupby"]): 53 | val = get_value(f'_source.{alarm["groupby"][i]}', hit) 54 | if i == 0: 55 | title = val 56 | else: 57 | title = f"{title} / {val}" 58 | i += 1 59 | 60 | text = f"*Alarm on item: {title.strip()}*\n\t" 61 | for field in alarm["fields"]: 62 | val = get_value(f"_source.{field}", hit) 63 | 64 | # Add a tab to every line of values, this makes it easier to read 65 | pretty_val = "".join( 66 | [f"{line}\n\t" for line in pprint(val).split("\n")] 67 | ) 68 | text += f"*{field}*: {pretty_val}" 69 | 70 | blocks.append( 71 | {"type": "section", "text": {"type": "mrkdwn", "text": text}} 72 | ) 73 | blocks.append({"type": "divider"}) 74 | # pylint: disable=broad-except 75 | except Exception as error: 76 | self.logger.exception(error) 77 | 78 | webhook = WebhookClient(config.notifications["slack"]["webhook_url"]) 79 | res = webhook.send(text="", blocks=blocks) 80 | 81 | if not 200 <= res.status_code <= 299: 82 | self.logger.error( 83 | "Informing slack failed: %s %s", res.status_code, res.body 84 | ) 85 | self.logger.error(alarm) 86 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | bs4==0.0.1 2 | elasticsearch==7.17.9 3 | json2html==1.3.0 4 | pymsteams==0.1.14 5 | python-dateutil==2.8.2 6 | slack_sdk==3.13.0 7 | urllib3==1.26.19 8 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/run_daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to start alarm, enrichment and notification processes of data in elasticsearch 5 | # 6 | # Author: 7 | # - Outflank B.V. / Marc Smeets 8 | # - Lorenzo Bernardi (@fastlorenzo) 9 | # 10 | 11 | # INIT-LOGFILE is the first log file created 12 | # Keep it for root cause analysis 13 | LOGFILE="/var/log/redelk/daemon.log" 14 | INIT_LOGFILE="/var/log/redelk/init-daemon.log" 15 | 16 | # du default size listing is 1024B/1KB 17 | # 2 MB = 2048 18 | MAXLOGSIZE=$((1024 * 50)) 19 | 20 | # Check if there isn't an old process running, we dont want to run this in parallel 21 | pgrep -f daemon.py >/dev/null 22 | DAEMON_RUNNING=$? 23 | if [ $DAEMON_RUNNING -eq 1 ]; then 24 | cd /usr/share/redelk/bin 25 | 26 | # Check if file is larger than max log size 27 | # We want to keep the first log file for troubleshooting 28 | CURRENTLOGSIZE=$(/usr/bin/du $LOGFILE | /usr/bin/cut -f1) 29 | if [ $CURRENTLOGSIZE -gt $MAXLOGSIZE ]; then 30 | if [ ! -f "$INIT-LOGFILE" ]; then 31 | /usr/bin/mv $LOGFILE $INIT_LOGFILE 32 | fi 33 | 34 | python3 /usr/share/redelk/bin/daemon.py >$LOGFILE 2>&1 35 | else 36 | python3 /usr/share/redelk/bin/daemon.py >>$LOGFILE 2>&1 37 | fi 38 | printf "$(date +'%b %e %R') Daemon script ran \n" >>$LOGFILE 2>&1 39 | fi 40 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/run_roguedomainsupdate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to update list of known rogue domain names 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | LOGFILE="/var/log/redelk/roguedomains.log" 10 | CONFIGFILE="/etc/redelk/roguedomains.conf" 11 | INTERMEDIATEFILE="/tmp/roguedomains.txt" 12 | 13 | ## DNS-BH malwaredomains.com 14 | TEMPFILE="/tmp/roguedomains_malwaredomains.com.txt" 15 | curl -s http://mirror1.malwaredomains.com/files/domains.txt | grep -v '#'|awk '{print $1}'|grep -P '(?=^.{1,254}$)(^(?>(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)' > $TEMPFILE 16 | LINECOUNT=`wc -l $TEMPFILE|awk '{print $1}'` 17 | if [ $LINECOUNT -ge 10 ]; then 18 | cat $TEMPFILE |awk '{print $1 " # malwaredomains.com"}' >> $INTERMEDIATEFILE 19 | echo "$LINECOUNT lines added from malwaredomains.com">> $LOGFILE 20 | fi 21 | 22 | ## abuse.ch URLhaus Plain-Text URL List (URLs only) 23 | TEMPFILE="/tmp/roguedomains_urlhaus.abuse.ch.txt" 24 | curl -s https://urlhaus.abuse.ch/downloads/text/ | grep -v '#'|awk '{print $1}'|grep '^http' | sed -e "s/\r//g" > $TEMPFILE 25 | LINECOUNT=`wc -l $TEMPFILE|awk '{print $1}'` 26 | if [ $LINECOUNT -ge 10 ]; then 27 | cat $TEMPFILE |awk '{print $1 " # urlhaus.abuse.ch"}' >> $INTERMEDIATEFILE 28 | echo "$LINECOUNT lines added from urlhaus.abuse.ch">> $LOGFILE 29 | fi 30 | 31 | ## host list form malwaredomainlist.com 32 | TEMPFILE="/tmp/roguedomains_malwaredomainlist.com.txt" 33 | curl -s http://www.malwaredomainlist.com/hostslist/hosts.txt | grep -v '#'|awk '{print $2}'|sed -e "s/\r//g"|grep -P '(?=^.{1,254}$)(^(?>(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)' > $TEMPFILE 34 | LINECOUNT=`wc -l $TEMPFILE|awk '{print $1}'` 35 | if [ $LINECOUNT -ge 10 ]; then 36 | cat $TEMPFILE |awk '{print $1 " # malwaredomainlist.com"}' >> $INTERMEDIATEFILE 37 | echo "$LINECOUNT lines added from malwaredomainlist.com">> $LOGFILE 38 | fi 39 | 40 | # Put it all together 41 | LINECOUNT=`wc -l $INTERMEDIATEFILE|awk '{print $1}'` 42 | if [ $LINECOUNT -ge 10 ]; then 43 | echo "# Part of RedELK - Rogue domain names form multiple sources - AUTO UPDATED, DO NOT MAKE MANUAL CHANGES" > $CONFIGFILE 44 | cat $INTERMEDIATEFILE >> $CONFIGFILE 45 | rm $INTERMEDIATEFILE 46 | echo "$LINECOUNT lines added">> $LOGFILE 47 | printf "`date +'%b %e %R'` rogue domain name update script ran \n" >> $LOGFILE 2>&1 48 | fi 49 | 50 | printf "`date +'%b %e %R'` Now running chameleon.py for checking classifications of our domains\n" >> $LOGFILE 2>&1 51 | 52 | # Now run chameleon.py to check if our domains 53 | cd /usr/share/redelk/bin/Chameleon/ 54 | #python3 chameleon.py --redelk --proxy a >> $LOGFILE 2>&1 55 | 56 | ### At this moment, Chameleon doesnt work anymore with IBM and Bluecoat. Setting proxy parameter to only query at McAfee 57 | python3 chameleon.py --redelk --proxy m >> $LOGFILE 2>&1 58 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/scripts/run_torexitnodeupdate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to update list of TOR exit node IP addresses 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | LOGFILE="/var/log/redelk/torupdate.log" 10 | CONFIGFILE="/etc/redelk/torexitnodes.conf" 11 | TEMPFILE="/tmp/torexitnodes.txt" 12 | 13 | 14 | curl -s https://check.torproject.org/exit-addresses | awk '/ExitAddress/ {print $2}' > $TEMPFILE 15 | LINECOUNT=`wc -l /tmp/torexitnodes.txt|awk '{print $1}'` 16 | if [ $LINECOUNT -ge 10 ]; then 17 | echo "# Part of RedELK - list of TOR exit node addresses - AUTO UPDATED, DO NOT MAKE MANUAL CHANGES" > $CONFIGFILE 18 | cat $TEMPFILE >> $CONFIGFILE 19 | rm $TEMPFILE 20 | echo "$LINECOUNT lines added">> $LOGFILE 21 | printf "`date +'%b %e %R'` TOR update script ran \n" >> $LOGFILE 2>&1 22 | fi 23 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/diff/redelk_kibana_index-pattern_redirtraffic.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "attributes": { 4 | "fieldAttrs": "{\"tags\":{\"count\":1},\"destination.as.organization.name\":{\"count\":1}}", 5 | "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"pattern\":\"MMM D Y, HH:mm:ss\"}},\"greynoise.first_seen\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.last_result.first_seen\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.last_result.last_updated\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.query_timestamp\":{\"id\":\"string\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}}}", 6 | "fields": [], 7 | "runtimeFieldMap": "{}", 8 | "timeFieldName": "@timestamp", 9 | "title": "redirtraffic-*", 10 | "typeMeta": "{}" 11 | }, 12 | "coreMigrationVersion": "7.16.3", 13 | "id": "redirtraffic", 14 | "migrationVersion": { 15 | "index-pattern": "7.11.0" 16 | }, 17 | "references": [], 18 | "sort": [ 19 | 1679213602216, 20 | 368678 21 | ], 22 | "type": "index-pattern", 23 | "version": "1" 24 | } 25 | ] -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/diff/redelk_kibana_index-pattern_rtops.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "attributes": { 4 | "fieldAttrs": "{\"c2.program\":{\"count\":1}}", 5 | "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"basePath\":\"\"},\"pattern\":\"MMM D Y, HH:mm:ss\"}},\"event.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Event URL\"}},\"file.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"/\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"File download\"}},\"implant.log_file\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Implant URL\"}},\"keystrokes.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Full keystrokes\"}},\"screenshot.full\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Full screenshot\"}},\"screenshot.thumb\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"type\":\"img\",\"urlTemplate\":\"/../..{{rawValue}}\"}},\"implant.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Implant URL\"}}}", 6 | "fields": [], 7 | "runtimeFieldMap": "{}", 8 | "timeFieldName": "@timestamp", 9 | "title": "rtops-*", 10 | "typeMeta": "{}" 11 | }, 12 | "coreMigrationVersion": "7.16.3", 13 | "id": "rtops", 14 | "migrationVersion": { 15 | "index-pattern": "7.11.0" 16 | }, 17 | "references": [], 18 | "sort": [ 19 | 1675843214132, 20 | 59678 21 | ], 22 | "type": "index-pattern", 23 | "version": "1" 24 | } 25 | ] -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/diff/redelk_kibana_map.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_elasticsearch_ilm.json: -------------------------------------------------------------------------------- 1 | {"policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"100gb","max_age":"365d"},"set_priority":{"priority":1}}}}}} 2 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_elasticsearch_template_iplist.json: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": {}, 3 | "index_patterns": [ 4 | "iplist-*" 5 | ], 6 | "mappings": { 7 | "_routing": { 8 | "required": false 9 | }, 10 | "_source": { 11 | "enabled": true, 12 | "excludes": [], 13 | "includes": [] 14 | }, 15 | "date_detection": true, 16 | "dynamic": true, 17 | "dynamic_date_formats": [ 18 | "strict_date_optional_time", 19 | "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z" 20 | ], 21 | "numeric_detection": false, 22 | "properties": { 23 | "@timestamp": { 24 | "doc_values": true, 25 | "ignore_malformed": false, 26 | "index": true, 27 | "store": false, 28 | "type": "date" 29 | }, 30 | "date_modified": { 31 | "type": "date" 32 | }, 33 | "ip": { 34 | "type": "ip" 35 | }, 36 | "list": { 37 | "type": "keyword" 38 | }, 39 | "source": { 40 | "type": "keyword" 41 | } 42 | } 43 | }, 44 | "order": 0, 45 | "settings": { 46 | "index": { 47 | "mapping": { 48 | "total_fields": { 49 | "limit": "10000" 50 | } 51 | }, 52 | "number_of_replicas": "0", 53 | "number_of_shards": "1", 54 | "query": { 55 | "default_field": "*" 56 | }, 57 | "refresh_interval": "5s" 58 | } 59 | }, 60 | "version": 1 61 | } -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_elasticsearch_template_redelk.json: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": {}, 3 | "index_patterns": [ 4 | "redelk-*" 5 | ], 6 | "mappings": { 7 | "_routing": { 8 | "required": false 9 | }, 10 | "_source": { 11 | "enabled": true, 12 | "excludes": [], 13 | "includes": [] 14 | }, 15 | "date_detection": true, 16 | "dynamic": true, 17 | "dynamic_date_formats": [ 18 | "strict_date_optional_time", 19 | "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z" 20 | ], 21 | "dynamic_templates": [], 22 | "numeric_detection": true, 23 | "properties": { 24 | "@timestamp": { 25 | "type": "date" 26 | }, 27 | "iplist": { 28 | "properties": { 29 | "comments": { 30 | "type": "text" 31 | }, 32 | "ip": { 33 | "coerce": true, 34 | "index": true, 35 | "store": false, 36 | "type": "ip_range" 37 | }, 38 | "name": { 39 | "type": "keyword" 40 | }, 41 | "source": { 42 | "type": "keyword" 43 | } 44 | }, 45 | "type": "object" 46 | }, 47 | "module": { 48 | "properties": { 49 | "last_run": { 50 | "dynamic": true, 51 | "enabled": true, 52 | "properties": { 53 | "message": { 54 | "type": "text" 55 | }, 56 | "status": { 57 | "type": "keyword" 58 | }, 59 | "timestamp": { 60 | "doc_values": true, 61 | "ignore_malformed": false, 62 | "index": true, 63 | "store": false, 64 | "type": "date" 65 | } 66 | }, 67 | "type": "object" 68 | }, 69 | "name": { 70 | "type": "keyword" 71 | }, 72 | "type": { 73 | "type": "keyword" 74 | } 75 | }, 76 | "type": "object" 77 | }, 78 | "type": { 79 | "type": "keyword" 80 | } 81 | } 82 | }, 83 | "order": 0, 84 | "settings": { 85 | "index": { 86 | "mapping": { 87 | "total_fields": { 88 | "limit": "10000" 89 | } 90 | }, 91 | "number_of_replicas": "0", 92 | "number_of_shards": "1", 93 | "query": { 94 | "default_field": "*" 95 | }, 96 | "refresh_interval": "5s" 97 | } 98 | }, 99 | "version": 1 100 | } -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_index-pattern_redelk-domainslist.ndjson: -------------------------------------------------------------------------------- 1 | {"attributes": {"fieldAttrs": "{\"domainslist.categorization.categories\":{\"count\":1},\"domainslist.comment\":{\"count\":1},\"domainslist.domain\":{\"count\":2},\"domainslist.name\":{\"count\":1},\"domainslist.source\":{\"count\":1},\"_id\":{\"count\":1}}", "fields": "[]", "runtimeFieldMap": "{}", "timeFieldName": "@timestamp", "title": "redelk-domainslist-*", "typeMeta": "{}"}, "coreMigrationVersion": "7.16.3", "id": "db409380-4d9d-11ed-9a8f-a126bac589a5", "migrationVersion": {"index-pattern": "7.11.0"}, "references": [], "sort": [1665960516942, 49310], "type": "index-pattern", "version": "1"} 2 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_index-pattern_redelk-iplist.ndjson: -------------------------------------------------------------------------------- 1 | {"attributes": {"fields": "[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"iplist.comments\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"iplist.ip\",\"type\":\"unknown\",\"esTypes\":[\"ip_range\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"iplist.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"iplist.source\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.last_run.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"module.last_run.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.last_run.timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "timeFieldName": "@timestamp", "title": "redelk-iplist-*"}, "coreMigrationVersion": "7.16.3", "id": "789bb360-2ab1-11eb-bc47-53169c986c81", "migrationVersion": {"index-pattern": "7.11.0"}, "references": [], "sort": [1675843207972, 59677], "type": "index-pattern", "version": "1"} -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_index-pattern_redelk.ndjson: -------------------------------------------------------------------------------- 1 | {"attributes": {"fields": "[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"iplist.comments\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"iplist.ip\",\"type\":\"unknown\",\"esTypes\":[\"ip_range\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"iplist.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"iplist.source\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.last_run.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.last_run.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"module.last_run.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.last_run.timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"module.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "title": "redelk-*"}, "coreMigrationVersion": "7.16.3", "id": "b5972620-2b72-11eb-85d7-bbc5b6917d13", "migrationVersion": {"index-pattern": "7.11.0"}, "references": [], "sort": [1675843210059, 59652], "type": "index-pattern", "version": "1"} -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_index-pattern_redirtraffic.ndjson: -------------------------------------------------------------------------------- 1 | {"attributes": {"fieldAttrs": "{\"tags\":{\"count\":1},\"destination.as.organization.name\":{\"count\":1}}", "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"pattern\":\"MMM D Y, HH:mm:ss\"}},\"greynoise.first_seen\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.last_result.first_seen\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.last_result.last_updated\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"greynoise.query_timestamp\":{\"id\":\"string\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:1080\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}}}", "fields": "[]", "runtimeFieldMap": "{}", "timeFieldName": "@timestamp", "title": "redirtraffic-*", "typeMeta": "{}"}, "coreMigrationVersion": "7.16.3", "id": "redirtraffic", "migrationVersion": {"index-pattern": "7.11.0"}, "references": [], "sort": [1679213602216, 368678], "type": "index-pattern", "version": "1"} -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_index-pattern_rtops.ndjson: -------------------------------------------------------------------------------- 1 | {"attributes": {"fieldAttrs": "{\"c2.program\":{\"count\":1}}", "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date\",\"params\":{\"parsedUrl\":{\"basePath\":\"\"},\"pattern\":\"MMM D Y, HH:mm:ss\"}},\"event.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Event URL\"}},\"file.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"/\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"File download\"}},\"implant.log_file\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Implant URL\"}},\"keystrokes.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Full keystrokes\"}},\"screenshot.full\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Full screenshot\"}},\"screenshot.thumb\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"type\":\"img\",\"urlTemplate\":\"/../..{{rawValue}}\"}},\"implant.url\":{\"id\":\"url\",\"params\":{\"parsedUrl\":{\"pathname\":\"/app/kibana\",\"basePath\":\"\"},\"urlTemplate\":\"/../..{{rawValue}}\",\"labelTemplate\":\"Implant URL\"}}}", "fields": "[]", "runtimeFieldMap": "{}", "timeFieldName": "@timestamp", "title": "rtops-*", "typeMeta": "{}"}, "coreMigrationVersion": "7.16.3", "id": "rtops", "migrationVersion": {"index-pattern": "7.11.0"}, "references": [], "sort": [1675843214132, 59678], "type": "index-pattern", "version": "1"} -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_map.ndjson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_map.ndjson -------------------------------------------------------------------------------- /elkserver/docker/redelk-base/redelkinstalldata/templates/redelk_kibana_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": { 3 | "theme:darkMode": true, 4 | "telemetry:optIn": false, 5 | "siem:enableNewsFeed": false, 6 | "siem:defaultIndex": ["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*","rtops-*","redirtraffic-*"], 7 | "defaultIndex": "195a3f00-d04f-11ea-9301-a30a04251ae9", 8 | "defaultRoute": "/app/discover#/view/1c580960-b6a9-11e8-bc1a-cf8fa3255855", 9 | "shortDots:enable": false, 10 | "telemetry:enabled": false, 11 | "timepicker:timeDefaults": "{\"from\": \"now-7d\",\"to\": \"now\"}" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-elasticsearch/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Dockerfile for RedELK elasticsearch image 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi 8 | # 9 | 10 | FROM docker.elastic.co/elasticsearch/elasticsearch:7.17.9 11 | LABEL maintainer="Outflank B.V. / Marc Smeets" 12 | LABEL description="RedELK Elasticsearch" 13 | 14 | RUN apt-get install -y openssl 15 | 16 | COPY --chown=elasticsearch:elasticsearch ./redelkinstalldata/init-elasticsearch.sh /usr/local/bin/init-elasticsearch.sh 17 | COPY --chown=elasticsearch:elasticsearch ./redelkinstalldata/redelk-entrypoint.sh /usr/local/bin/redelk-entrypoint.sh 18 | COPY --chown=elasticsearch:elasticsearch ./redelkinstalldata/instances.yml /usr/share/elasticsearch/config/instances.yml 19 | 20 | RUN chmod 755 /usr/local/bin/init-elasticsearch.sh /usr/local/bin/redelk-entrypoint.sh 21 | 22 | ENTRYPOINT ["/bin/tini", "--", "/usr/local/bin/redelk-entrypoint.sh"] 23 | CMD ["eswrapper"] 24 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-elasticsearch/redelkinstalldata/init-elasticsearch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Part of RedELK 4 | # Init script for RedELK elasticsearch image 5 | # 6 | # Authors: 7 | # - Outflank B.V. / Marc Smeets 8 | # - Lorenzo Bernardi (@fastlorenzo) 9 | # 10 | 11 | if [[ ! -f $CERTS_DIR_ES/bundle.zip ]]; then 12 | echo "[*] Generating RedELK certificates" 13 | bin/elasticsearch-certutil cert --silent --pem --in /usr/share/elasticsearch/config/instances.yml -out $CERTS_DIR_ES/bundle.zip; 14 | unzip $CERTS_DIR_ES/bundle.zip -d $CERTS_DIR_ES; 15 | fi; 16 | if [[ ! -f $CERTS_DIR_ES/redelk-logstash/redelk-logstash.pkcs8.key ]]; then 17 | echo "[*] Converting logstash private key to pkcs8" 18 | openssl pkcs8 -in $CERTS_DIR_ES/redelk-logstash/redelk-logstash.key -topk8 -nocrypt -out $CERTS_DIR_ES/redelk-logstash/redelk-logstash.pkcs8.key 19 | fi 20 | chown -R 1000:0 $CERTS_DIR_ES 21 | chmod u+rwX,g+rX,o-rwx $CERTS_DIR_ES 22 | READY=1 23 | while [[ $READY -ne 0 ]]; do 24 | echo "[*] Waiting for Elasticsearch to be up" 25 | curl $ES_URL/ --cacert $CERTS_DIR_ES/ca/ca.crt -s -u elastic:$ELASTIC_PASSWORD >/dev/null 2>&1 26 | READY=$? 27 | sleep 1 28 | done 29 | 30 | echo "[*] Setting password for user kibana_system" 31 | curl -XPOST $ES_URL/_security/user/kibana_system/_password --cacert $CERTS_DIR_ES/ca/ca.crt -s -uelastic:$ELASTIC_PASSWORD -H 'Content-Type: application/json' --data "{\"password\":\"$CREDS_kibana_system\"}" 32 | ERROR=$? 33 | if [ $ERROR -ne 0 ]; then 34 | echoerror "[X] Error setting password for user kibana_system (Error Code: $ERROR)." 35 | fi 36 | 37 | echo "[*] Setting password for user logstash_system" 38 | curl -XPOST $ES_URL/_security/user/logstash_system/_password --cacert $CERTS_DIR_ES/ca/ca.crt -s -uelastic:$ELASTIC_PASSWORD -H 'Content-Type: application/json' --data "{\"password\":\"$CREDS_logstash_system\"}" 39 | ERROR=$? 40 | if [ $ERROR -ne 0 ]; then 41 | echoerror "[X] Error setting password for user logstash_system (Error Code: $ERROR)." 42 | fi 43 | 44 | echo "[*] Creating redelk_ingest role" 45 | curl -XPOST $ES_URL/_security/role/redelk_ingest --cacert $CERTS_DIR_ES/ca/ca.crt -s -uelastic:$ELASTIC_PASSWORD -H 'Content-Type: application/json' --data-binary @- << EOF 46 | { 47 | "cluster": ["monitor","cluster:admin/xpack/monitoring/bulk","manage_ilm"], 48 | "indices": [ 49 | { 50 | "names": ["rtops*","redirtraffic*","credentials-*","bluecheck-*","email-*","implantsdb","auditbeat*","filebeat*","packetbeat*","apm*","heartbeat*","nagioscheckbeat*","metricbeat*",".monitor*"], 51 | "privileges": ["create","read","write","monitor","index","manage","delete","manage_ilm"] 52 | } 53 | ], 54 | "run_as":[] 55 | } 56 | EOF 57 | ERROR=$? 58 | if [ $ERROR -ne 0 ]; then 59 | echoerror "[X] Error creating redelk_ingest role (Error Code: $ERROR)." 60 | fi 61 | 62 | echo "[*] Creating redelk_ingest user" 63 | curl -XPOST $ES_URL/_security/user/redelk_ingest --cacert $CERTS_DIR_ES/ca/ca.crt -s -uelastic:$ELASTIC_PASSWORD -H 'Content-Type: application/json' --data-binary @- << EOF 64 | { 65 | "password": "$CREDS_redelk_ingest", 66 | "roles": ["redelk_ingest"], 67 | "full_name": "RedELK Ingest" 68 | } 69 | EOF 70 | ERROR=$? 71 | if [ $ERROR -ne 0 ]; then 72 | echoerror "[X] Error creating redelk_ingest user (Error Code: $ERROR)." 73 | fi 74 | 75 | echo "[*] Creating redelk user" 76 | curl -XPOST $ES_URL/_security/user/redelk --cacert $CERTS_DIR_ES/ca/ca.crt -s -uelastic:$ELASTIC_PASSWORD -H 'Content-Type: application/json' --data-binary @- << EOF 77 | { 78 | "password": "$CREDS_redelk", 79 | "roles": ["superuser"], 80 | "full_name": "RedELK Operator" 81 | } 82 | EOF 83 | ERROR=$? 84 | if [ $ERROR -ne 0 ]; then 85 | echoerror "[X] Error creating redelk user (Error Code: $ERROR)." 86 | fi 87 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-elasticsearch/redelkinstalldata/instances.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Instances file for elasticsearch cert generation 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi (@fastlorenzo) 8 | # 9 | 10 | instances: 11 | - name: redelk-elasticsearch 12 | dns: 13 | - redelk-elasticsearch 14 | - localhost 15 | - name: redelk-kibana 16 | dns: 17 | - redelk-kibana 18 | - localhost 19 | - name: redelk-logstash 20 | dns: 21 | - redelk-logstash 22 | - localhost 23 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-elasticsearch/redelkinstalldata/redelk-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Part of RedELK 4 | # Modified entrypoitn script for RedELK Elasticsearch docker image 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # Contributor: Lorenzo Bernardi / @fastlorenzo 8 | # 9 | 10 | 11 | # Run init script in background 12 | echo "[*] Starting RedELK init script for Elasticsearch" 13 | /usr/local/bin/init-elasticsearch.sh & 14 | 15 | # Run original docker entrypoint 16 | echo "[*] Running regular docker entrypoint script" 17 | /usr/local/bin/docker-entrypoint.sh "${@}" 18 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-jupyter/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Dockerfile for RedELK jupyter notebooks image 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | FROM jupyter/scipy-notebook:notebook-6.4.6 9 | LABEL maintainer="Outflank B.V. / Marc Smeets" 10 | LABEL description="RedELK Jupyter Notebooks" 11 | 12 | RUN pip3 install pandas neo4j elasticsearch==7.17.3 13 | 14 | CMD ["/bin/bash", "-o", "pipefail", "-c", "start-notebook.sh --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.allow_remote_access='True' --NotebookApp.allow_origin='*' --NotebookApp.base_url='/jupyter/'"] 15 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-kibana/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Dockerfile for RedELK Kibana image 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi 8 | # 9 | 10 | FROM docker.elastic.co/kibana/kibana:7.17.9 11 | LABEL maintainer="Outflank B.V. / Marc Smeets" 12 | LABEL description="RedELK Kibana" 13 | 14 | #COPY redelk-7.10.0.zip /tmp/redelk-7.10.0.zip 15 | #RUN /usr/share/kibana/bin/kibana-plugin install file:/tmp/redelk-7.10.0.zip 16 | 17 | RUN /usr/share/kibana/bin/kibana-plugin install https://github.com/fastlorenzo/redelk-kibana-app/releases/download/v1.0.0/redelk-7.17.9.zip 18 | -------------------------------------------------------------------------------- /elkserver/docker/redelk-logstash/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Dockerfile for RedELK Logstash image 4 | # 5 | # Authors: 6 | # - Outflank B.V. / Marc Smeets 7 | # - Lorenzo Bernardi 8 | # 9 | 10 | FROM docker.elastic.co/logstash/logstash:7.17.9 11 | LABEL maintainer="Outflank B.V. / Marc Smeets" 12 | LABEL description="RedELK Logstash" 13 | 14 | # Create relevant directories 15 | #RUN mkdir -p /usr/share/logstash/redelk-main/conf.d 16 | #RUN mkdir -p /usr/share/logstash/redelk-main/certs 17 | 18 | # Move files to proper locations 19 | #COPY --chown=logstash:logstash ./redelkinstalldata/config/pipelines.yml /usr/share/logstash/config/pipelines.yml 20 | #COPY --chown=logstash:logstash ./redelkinstalldata/redelk-main/conf.d/. /usr/share/logstash/redelk-main/conf.d/ 21 | #COPY --chown=logstash:logstash ./redelkinstalldata/redelk-main/scripts/. /usr/share/logstash/redelk-main/scripts/ 22 | -------------------------------------------------------------------------------- /elkserver/init-letsencrypt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Part of RedELK 4 | # Script to bootstrap certbot tls certificates for nginx 5 | # 6 | # Authors: 7 | # - Lorenzo Bernardi (@fastlorenzo) 8 | # - Outflank B.V. / Marc Smeets 9 | # 10 | 11 | rsa_key_size=4096 12 | data_path="./mounts/certbot" 13 | email="$(cat ./mounts/redelk-config/etc/redelk/config.json | jq -r .redelkserver_letsencrypt.le_email)" # Adding a valid address is strongly recommended 14 | staging="$(cat ./mounts/redelk-config/etc/redelk/config.json | jq -r .redelkserver_letsencrypt.staging)" # Set to 1 if you're testing your setup to avoid hitting request limits 15 | 16 | if ! [ -x "$(command -v docker-compose)" ]; then 17 | echo 'Error: docker-compose is not installed.' >&2 18 | exit 1 19 | fi 20 | 21 | if [ ${#} -eq 2 ] && [[ -f $1 ]]; then 22 | compose_file=$1 23 | domain=$2 24 | else 25 | echo "[X] Error: 1st parameter should be input file for docker-compose, 2nd the domain name. Exiting." 26 | exit 1 27 | fi 28 | 29 | # if [ -d "$data_path" ]; then 30 | # read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision 31 | # if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then 32 | # exit 33 | # fi 34 | # fi 35 | 36 | if [ -f "$data_path/conf/live/$domain/privkey.pem" ]; then 37 | echo "Existing data found for $domain, skipping" 38 | exit 0 39 | fi 40 | 41 | echo "### Creating dummy certificate for $domain ..." 42 | path="/etc/letsencrypt/live/$domain" 43 | mkdir -p "$data_path/conf/live/$domain" 44 | docker-compose -f $compose_file run --rm --entrypoint "\ 45 | openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 365\ 46 | -keyout '$path/privkey.pem' \ 47 | -out '$path/fullchain.pem' \ 48 | -subj '/CN=${domain}'" certbot 49 | echo 50 | 51 | echo "### Starting nginx ..." 52 | docker-compose -f $compose_file up --force-recreate -d nginx 53 | echo 54 | 55 | echo "### Requesting Let's Encrypt certificate for $domain ..." 56 | 57 | # Select appropriate email arg 58 | case "$email" in 59 | "") email_arg="--register-unsafely-without-email" ;; 60 | *) email_arg="--email $email" ;; 61 | esac 62 | 63 | # Enable staging mode if needed 64 | if [ $staging != "0" ]; then staging_arg="--staging"; fi 65 | 66 | echo "### Removing dummy certificate folder" 67 | rm -Rf "$data_path/conf/live/$domain" 68 | 69 | docker-compose -f $compose_file run --rm --entrypoint "\ 70 | certbot certonly --webroot -w /var/www/certbot \ 71 | $staging_arg \ 72 | $email_arg \ 73 | -d $domain \ 74 | --rsa-key-size $rsa_key_size \ 75 | --agree-tos \ 76 | --force-renewal -n" certbot 77 | echo 78 | 79 | echo "### Reloading nginx ..." 80 | docker-compose -f $compose_file exec nginx nginx -s reload 81 | -------------------------------------------------------------------------------- /elkserver/mounts/bloodhound-config/bloodhound.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "bind_addr": "0.0.0.0:8080", 4 | "metrics_port": ":2112", 5 | "root_url": "http://127.0.0.1:8080/", 6 | "work_dir": "/opt/bloodhound/work", 7 | "log_level": "INFO", 8 | "log_path": "bloodhound.log", 9 | "features": { 10 | "enable_auth": true 11 | }, 12 | "tls": { 13 | "cert_file": "", 14 | "key_file": "" 15 | }, 16 | "database": { 17 | "connection": "user=bloodhound password={{PGSQL_PASSWORD}} dbname=bloodhound host=redelk-bloodhound-postgres" 18 | }, 19 | "neo4j": { 20 | "connection": "neo4j://neo4j:{{NEO4J_PASSWORD}}@redelk-bloodhound-neo4j:7687/" 21 | }, 22 | "collectors_base_path": "/etc/bloodhound/collectors", 23 | "default_admin": { 24 | "principal_name": "admin", 25 | "password": "{{BLOODHOUND_PASSWORD}}", 26 | "first_name": "Bloodhound", 27 | "last_name": "Admin", 28 | "email_address": "{{BLOODHOUND_ADMIN_EMAIL}}" 29 | } 30 | } -------------------------------------------------------------------------------- /elkserver/mounts/elasticsearch-config/jvm.options.d/jvm.options: -------------------------------------------------------------------------------- 1 | ## JVM configuration 2 | 3 | ################################################################ 4 | ## IMPORTANT: JVM heap size 5 | ################################################################ 6 | ## 7 | ## You should always set the min and max JVM heap 8 | ## size to the same value. For example, to set 9 | ## the heap to 4 GB, set: 10 | ## 11 | ## -Xms4g 12 | ## -Xmx4g 13 | ## 14 | ## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html 15 | ## for more information 16 | ## 17 | ################################################################ 18 | 19 | # Xms represents the initial size of total heap space 20 | # Xmx represents the maximum size of total heap space 21 | 22 | -Xms1g 23 | -Xmx1g 24 | 25 | ################################################################ 26 | ## Expert settings 27 | ################################################################ 28 | ## 29 | ## All settings below this section are considered 30 | ## expert settings. Don't tamper with them unless 31 | ## you understand what you are doing 32 | ## 33 | ################################################################ 34 | 35 | ## GC configuration 36 | 8-13:-XX:+UseConcMarkSweepGC 37 | 8-13:-XX:CMSInitiatingOccupancyFraction=75 38 | 8-13:-XX:+UseCMSInitiatingOccupancyOnly 39 | 40 | ## G1GC Configuration 41 | # NOTE: G1 GC is only supported on JDK version 10 or later 42 | # to use G1GC, uncomment the next two lines and update the version on the 43 | # following three lines to your version of the JDK 44 | # 10-13:-XX:-UseConcMarkSweepGC 45 | # 10-13:-XX:-UseCMSInitiatingOccupancyOnly 46 | 14-:-XX:+UseG1GC 47 | 14-:-XX:G1ReservePercent=25 48 | 14-:-XX:InitiatingHeapOccupancyPercent=30 49 | 50 | ## JVM temporary directory 51 | -Djava.io.tmpdir=${ES_TMPDIR} 52 | 53 | ## heap dumps 54 | 55 | # generate a heap dump when an allocation from the Java heap fails 56 | # heap dumps are created in the working directory of the JVM 57 | -XX:+HeapDumpOnOutOfMemoryError 58 | 59 | # specify an alternative path for heap dumps; ensure the directory exists and 60 | # has sufficient space 61 | -XX:HeapDumpPath=data 62 | 63 | # specify an alternative path for JVM fatal error logs 64 | -XX:ErrorFile=logs/hs_err_pid%p.log 65 | 66 | ## JDK 8 GC logging 67 | 8:-XX:+PrintGCDetails 68 | 8:-XX:+PrintGCDateStamps 69 | 8:-XX:+PrintTenuringDistribution 70 | 8:-XX:+PrintGCApplicationStoppedTime 71 | 8:-Xloggc:logs/gc.log 72 | 8:-XX:+UseGCLogFileRotation 73 | 8:-XX:NumberOfGCLogFiles=32 74 | 8:-XX:GCLogFileSize=64m 75 | 76 | # JDK 9+ GC logging 77 | 9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m 78 | -------------------------------------------------------------------------------- /elkserver/mounts/jupyter-workbooks/RedELK_Jupyter_Notebook_startup_test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# This is the RedELK Welcome Jupyter Notebook\n", 10 | "# We will go through a few steps to make sure the connections to Elasticsearch and BloodHound/Neo4J are operational\n", 11 | "\n", 12 | "import urllib3\n", 13 | "import ssl\n", 14 | "from elasticsearch import Elasticsearch\n", 15 | "from elasticsearch.connection import create_ssl_context\n", 16 | "from redelk_passwords import * # this file contains all relevant credentials" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "# define the connection to our ES instance\n", 26 | "\n", 27 | "urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n", 28 | "ssl_context = create_ssl_context()\n", 29 | "ssl_context.check_hostname = False\n", 30 | "ssl_context.verify_mode = ssl.CERT_NONE\n", 31 | "\n", 32 | "es = Elasticsearch(\n", 33 | " ['redelk-elasticsearch'],\n", 34 | " http_auth=(CredESUsername, CredESPassword),\n", 35 | " scheme=\"https\",\n", 36 | " port=9200,\n", 37 | " ssl_context=ssl_context\n", 38 | ")\n" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "# Now test the connection to ES -- this should give output\n", 48 | "\n", 49 | "if es.ping():\n", 50 | " print(\"ES connection successful\")\n", 51 | "else:\n", 52 | " raise ValueError(\"ES Connection failed\")\n" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "# Now check the connection to Neo4j -- this should give output\n", 62 | "\n", 63 | "from neo4j import GraphDatabase\n", 64 | "\n", 65 | "class HelloWorldExample:\n", 66 | "\n", 67 | " def __init__(self, uri, user, password):\n", 68 | " self.driver = GraphDatabase.driver(uri, auth=(user, password))\n", 69 | "\n", 70 | " def close(self):\n", 71 | " self.driver.close()\n", 72 | "\n", 73 | " def print_greeting(self, message):\n", 74 | " with self.driver.session() as session:\n", 75 | " greeting = session.write_transaction(self._create_and_return_greeting, message)\n", 76 | " print(greeting)\n", 77 | "\n", 78 | " @staticmethod\n", 79 | " def _create_and_return_greeting(tx, message):\n", 80 | " result = tx.run(\"CREATE (a:Greeting) \"\n", 81 | " \"SET a.message = $message \"\n", 82 | " \"RETURN a.message + ', from node ' + id(a)\", message=message)\n", 83 | " return result.single()[0]\n", 84 | "\n", 85 | "\n", 86 | "if __name__ == \"__main__\":\n", 87 | " greeter = HelloWorldExample(\"bolt://redelk-bloodhound-neo4j:7687\", CredNeo4jUsername, CredNeo4jPassword)\n", 88 | " greeter.print_greeting(\"hello, world\")\n", 89 | " greeter.close()" 90 | ] 91 | } 92 | ], 93 | "metadata": { 94 | "kernelspec": { 95 | "display_name": "Python 3", 96 | "language": "python", 97 | "name": "python3" 98 | }, 99 | "language_info": { 100 | "codemirror_mode": { 101 | "name": "ipython", 102 | "version": 3 103 | }, 104 | "file_extension": ".py", 105 | "mimetype": "text/x-python", 106 | "name": "python", 107 | "nbconvert_exporter": "python", 108 | "pygments_lexer": "ipython3", 109 | "version": "3.8.5" 110 | } 111 | }, 112 | "nbformat": 4, 113 | "nbformat_minor": 4 114 | } 115 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/config/pipelines.yml: -------------------------------------------------------------------------------- 1 | # This file is where you define your pipelines. You can define multiple. 2 | # For more information on multiple pipelines, see the documentation: 3 | # https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html 4 | 5 | - pipeline.id: redelk-pipeline 6 | path.config: "/usr/share/logstash/redelk-main/conf.d" 7 | pipeline.ecs_compatibility: v1 -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/10-input_filebeat_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the logstash inputs 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | input { 9 | beats { 10 | port => 5044 11 | ssl => true 12 | ssl_certificate => "${CERTS_LOGSTASH_INPUT_CRT}" 13 | ssl_key => "${CERTS_LOGSTASH_INPUT_KEY}" 14 | client_inactivity_timeout => 7200 15 | ssl_handshake_timeout => 30000 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/11-input_localfiles_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the local file inputs 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | input { 9 | file { 10 | path => "/var/log/redelk/redteamdomaincheck.txt" 11 | start_position => "beginning" 12 | type => "bluecheck" 13 | add_field => { "bluechecktype" => "roguedomaincheck" } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/12-input_email_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the logstash input for remote email resources 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | # 8 | # You need to configure this file to. Ive included a few examples for known email providers. 9 | # A few things to note: 10 | # - Make sure to enable IMAP at the email provider's side if required. Note, Gmail also requires 'allow less secure devices' in Gmail security settings. 11 | # - The provider may block you if you check for email too often, are coming from a suspicious email or some other 12 | # 'magic anti-spam measure'. It differs per provider how you should handle this (e.g. Gmail wants you to do a captcha 13 | # from your IP at https://www.google.com/accounts/DisplayUnlockCaptcha) 14 | # - OPSEC issue: unless you are using an outbound proxy on your RedELK host, this config will expose the RedELK's ext IP to the email provider. 15 | # - In our testing the 'Sent' items weren't always imported from the start. A fix that seem to work is toggle all sent emails as 'unread' once 16 | # - Folder names need to be exact, and they aren't the same at every provider. You can check the names manually by doing: 17 | # openssl s_client -connect remote.imapprovider.com:993 -crlf 18 | # a1 login username p4ssw0rd 19 | # a2 LIST "" "*" 20 | # 21 | # 22 | 23 | input { 24 | ## Outlook.com Inbox 25 | #imap { 26 | # host => "outlook.office365.com" 27 | # password => "" 28 | # user => "" 29 | # port => 993 30 | # check_interval => 180 31 | # folder => "Inbox" 32 | # uid_tracking => "true" 33 | # add_field => { "infra.log.type" => "email" } 34 | # add_field => { "infra.attack_scenario" => "test" } 35 | # add_field => { "email_folder" => "inbox" } 36 | # strip_attachments => "true" # we have to strip attachments for now because of a stupid bug in Logstash 37 | #} 38 | ## Outlook.com Sent 39 | #imap { 40 | # host => "outlook.office365.com" 41 | # password => "" 42 | # user => "" 43 | # port => 993 44 | # check_interval => 180 45 | # folder => "Sent" 46 | # uid_tracking => "true" 47 | # add_field => { "infra.log.type" => "email" } 48 | # add_field => { "infra.attack_scenario" => "test" } 49 | # add_field => { "email_folder" => "sent" } 50 | # strip_attachments => "true" # we have to strip attachments for now because of a stupid bug in Logstash 51 | #} 52 | ## Gmail.com Inbox 53 | #imap { 54 | # host => "imap.gmail.com" 55 | # user => "" 56 | # password => "" 57 | # port => 993 58 | # check_interval => 180 59 | # folder => "Inbox" 60 | # uid_tracking => "true" 61 | # add_field => { "infra.log.type" => "email" } 62 | # add_field => { "infra.attack_scenario" => "test" } 63 | # add_field => { "email_folder" => "inbox" } 64 | # strip_attachments => "true" # we have to strip attachments for now because of a stupid bug in Logstash 65 | #} 66 | ## Gmail.com Sent 67 | #imap { 68 | # host => "imap.gmail.com" 69 | # user => "" 70 | # password => "" 71 | # port => 993 72 | # check_interval => 180 73 | # folder => "[Gmail]/Sent Mail" 74 | # uid_tracking => "true" 75 | # add_field => { "infra.log.type" => "email" } 76 | # add_field => { "infra.attack_scenario" => "test" } 77 | # add_field => { "email_folder" => "sent" } 78 | # strip_attachments => "true" # we have to strip attachments for now because of a stupid bug in Logstash 79 | #} 80 | } 81 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/30-filter-email_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the logstash filters for email inputs 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | filter { 9 | if [infralogtype] == "email" { 10 | 11 | # Set the timestamp from the log to @timestamp 12 | # example: Wed, 29 Jul 2020 10:54:29 +0200 13 | date { 14 | match => [ "date", "EEE, dd MMM yyyy HH:mm:ss Z" ] 15 | target => "@timestamp" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/52-filter-c2-poshc2_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the logstash filters for PoshC2 logs 4 | # 5 | # Author: Outflank B.V. / Marc Smeets / @benpturner - Ben Turner 6 | # Contributor: Lorenzo Bernardi 7 | # 8 | 9 | filter { 10 | if [infra][log][type] == "rtops" and [c2][program] == "poshc2" { 11 | 12 | if [c2][log][type] == "events" { 13 | 14 | # Let's first trim the syslog-like info from the log line 15 | grok { 16 | match => { "message" => [ ".*" ] } 17 | } 18 | 19 | # matching lines like: *** initial implant 20 | if "PID:" in [message] and "Sleep:" in [message] { 21 | 22 | mutate { 23 | replace => { "[c2][log][type]" => "implant_newimplant" } 24 | } 25 | 26 | grok { 27 | match => { "message" => "%{IPORHOST:[host][ext_ip]}\:%{IPORHOST:[host][port]}\s+\|\s+Time:%{GREEDYDATA:[c2][timestamp]}\s+\|\s+PID:%{IPORHOST:[process][pid]}\s+\|\s+Sleep:%{GREEDYDATA:[implant][sleep]}\s+\|\s+%{GREEDYDATA:[user][name]}\s+@\s+%{GREEDYDATA:[host][name]}\s+\(%{GREEDYDATA:[implant][arch]}\)\s+\|\s+URL\:%{GREEDYDATA:[implant][url]}" } 28 | } 29 | 30 | if [host][ext_ip] { 31 | # duplicate field so we can replace it with reverse DNS lookup and add the external IP to [host][ip] 32 | mutate { 33 | add_field => { "[host][ext_domain]" => "%{[host][ext_ip]}" } 34 | copy => { "[host][ext_ip]" => "[host][ip]" } 35 | } 36 | # do reverse DNS lookup 37 | dns { 38 | reverse => ["[host][ext_domain]"] 39 | action => "replace" 40 | timeout => "2.0" 41 | } 42 | # add geo ip info from City DB 43 | geoip { 44 | source => "[host][ext_ip]" 45 | target => "[host]" 46 | add_tag => "geoip_host_city" 47 | } 48 | # add geo ip info from ASN DB 49 | geoip { 50 | source => "[host][ext_ip]" 51 | target => "[host]" 52 | default_database_type => "ASN" 53 | add_tag => "geoip_host_asn" 54 | } 55 | } 56 | 57 | date { 58 | match => [ "[c2][timestamp]", "dd/MM/YYYY HH:mm:ss" ] 59 | target => "@timestamp" 60 | timezone => "Etc/UTC" 61 | } 62 | 63 | clone { 64 | clones => [ "implantsdb" ] 65 | remove_field => [ "[c2][log][type]","message","[infra][log_type]" ] 66 | } 67 | 68 | } 69 | 70 | # matching lines like: *** Screenshot captured: 71 | if "Screenshot captured:" in [message] { 72 | 73 | mutate { 74 | replace => { "[c2][log][type]" => "screenshots" } 75 | } 76 | 77 | grok { 78 | # Screenshot.full expects and URL, if the full screenshot is saved then the index needs to be updated to accomodate it 79 | match => { "message" => "Screenshot\s+captured:\s+%{GREEDYDATA:[screenshot][full]}" } 80 | } 81 | 82 | } 83 | 84 | # matching lines like: *** Download: 85 | if "Download file" in [message] { 86 | 87 | mutate { 88 | replace => { "[c2][log][type]" => "downloads" } 89 | } 90 | 91 | grok { 92 | match => { "message" => "Download\s+file\s+part\s+%{GREEDYDATA:[file][path]}" } 93 | } 94 | 95 | } 96 | 97 | # matching lines like: *** Messages: 98 | if "Message from" in [message] or "logged off" in [message] or "logged on" in [message] { 99 | 100 | mutate { 101 | replace => { "[c2][log][type]" => "messages" } 102 | } 103 | 104 | grok { 105 | match => { "message" => "(0[1-9]|[12]\d|3[01])/(0[1-9]|1[0-2])/[12]\d{3}\s+([0-1][0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9]):%{GREEDYDATA:[c2][message]}" } 106 | } 107 | 108 | } 109 | 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/70-filter-pstools_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we parse the output of the PS-Tools suite by Outflank / @Cn33liz 4 | # This may or may not work with the latest public version ! 5 | # 6 | # More info on PS-Tools at https://outflank.nl/blog/2020/03/11/red-team-tactics-advanced-process-monitoring-techniques-in-offensive-operations/ 7 | # and downloads at https://github.com/outflanknl/Ps-Tools 8 | # 9 | # Author: Outflank B.V. / Marc Smeets 10 | # 11 | 12 | filter { 13 | if [infra][log][type] == "rtops" and "PStoolsStart" in [c2][message] { 14 | grok { 15 | match => { "[c2][message]" => "\[PStoolsStart\]\n\n(?<[pstools][full_output]>(.|\r|\n)*)" } 16 | } 17 | 18 | # Determine the type of PSTool 19 | if "Output from Outflank PSX" in [pstools][full_output] { 20 | grok { 21 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{GREEDYDATA:[pstools][tool]}\)\n\n(?<[pstools][psx][processes]>(.|\r|\n)*)\n\n((-)+)\n(?<[pstools][psx][security_products]>(.|\r|\n)*)\n\n((-)+)\n(?<[pstools][psx][summary]>(.|\r|\n)*)\[PStoolsEnd\]" } 22 | } 23 | 24 | if [pstools][psx][security_products] { 25 | grok { 26 | match => { "[pstools][psx][security_products]" => "%{GREEDYDATA}Vendor:\t (?<[pstools][psx][edr_name]>(.|\r|\n)*)" } 27 | } 28 | # clean up the tab and "Product" string 29 | mutate { 30 | gsub => ["[pstools][psx][edr_name]", "\n Product:\t", " -"] 31 | } 32 | # now duplicate this specific log line to record into bluecheck index - remove useless info for that index 33 | # also copy the value from [pstools][psx][security_products] to [message] 34 | clone { 35 | clones => [ "bluecheck" ] 36 | remove_field => [ "[agent][ephemeral_id]","[agent][hostname]","[agent][id]","[agent][name]","[agent][type]","[agent][version]","[c2][log][type]","[c2][message]","[c2][program]","[c2][timestamp]","[event][action]","[event][category]","[event][dataset]","[event][end]","[event][enriched_from]","[event][ingested]","[event][kind]","[event][module]","[event][start]","[host]","[implant][output]","[infra][log][type]","[input][type]","[log][file][path]","[log][flags]","[log][offset]","[message]","[process][name]","[process][pid]","[pstools][full_output]","[pstools][psx][processes]","[pstools][psx][summary]","[user][name]" ] 37 | add_field => { "[message]" => "%{[pstools][psx][security_products]}" } 38 | } 39 | } 40 | 41 | } else if "Output from Outflank PSK" in [pstools][full_output] { 42 | grok { 43 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{WORD:[pstools][tool]} version %{NUMBER:[pstools][version]}\)\\n\\n%{GREEDYDATA:[pstools][header]}\\n\\n%{GREEDYDATA:[pstools][items]}\[F\]%{GREEDYDATA:[pstools][footer]}" } 44 | } 45 | } else if "Output from Outflank PSC" in [pstools][full_output] { 46 | grok { 47 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{WORD:[pstools][tool]} version %{NUMBER:[pstools][version]}\)\\n\\n%{GREEDYDATA:[pstools][items]}\[F\]%{GREEDYDATA:[pstools][footer]}" } 48 | } 49 | } else if "Output from Outflank PSM" in [pstools][full_output] { 50 | grok { 51 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{WORD:[pstools][tool]} version %{NUMBER:[pstools][version]}\)\\n\\n%{GREEDYDATA:[pstools][items]}\[F\]%{GREEDYDATA:[pstools][footer]}" } 52 | } 53 | } else if "Output from Outflank PSH" in [pstools][full_output] { 54 | grok { 55 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{WORD:[pstools][tool]} version %{NUMBER:[pstools][version]}\)\\n\\n%{GREEDYDATA:[pstools][items]}\[F\]%{GREEDYDATA:[pstools][footer]}" } 56 | } 57 | } else if "Output from Outflank PSW" in [pstools][full_output] { 58 | grok { 59 | match => { "[pstools][full_output]" => "\[V\] Output from Outflank %{WORD:[pstools][tool]} version %{NUMBER:[pstools][version]}\)\\n\\n%{GREEDYDATA:[pstools][items]}\[F\]%{GREEDYDATA:[pstools][footer]}" } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/80-filter-bluecheck_domainchecks_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we parse the file with the domain classification cheks 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | filter { 9 | if [type] == "bluecheck" { 10 | 11 | if [bluechecktype] == "roguedomaincheck" { 12 | grok { 13 | match => { "message" => "(?%{YEAR}\/%{MONTHNUM}\/%{MONTHDAY}, %{HOUR}\:%{MINUTE}\:%{SECOND}) Domain\: %{IPORHOST:domain} Source\: %{GREEDYDATA:classifier} Results\: %{GREEDYDATA:results}" } 14 | } 15 | date { 16 | match => [ "bluechecktimestamp", "YYYY/MM/dd, HH:mm:ss" ] 17 | target => "@timestamp" 18 | timezone => "Etc/UTC" 19 | } 20 | mutate { 21 | remove_field => [ "host" ] 22 | } 23 | } 24 | 25 | if [pstools][psx][edr_name] { 26 | mutate { 27 | add_field => { "bluechecktype" => "psx"} 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/conf.d/99-outputs_logstash.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # In this file we configure the logstash outputs 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | output { 9 | if [infra][log][type] == "rtops" { 10 | elasticsearch { 11 | hosts => ["redelk-elasticsearch:9200"] 12 | sniffing => false 13 | manage_template => false 14 | # ilm_enabled => true 15 | # ilm_rollover_alias => "rtops" 16 | # ilm_policy => "redelk" 17 | # template_name => "rtops" 18 | ilm_enabled => false 19 | index => "rtops-%{+YYYY.MM.dd}" 20 | user => ["redelk_ingest"] 21 | password => ["${CREDS_redelk_ingest}"] 22 | ssl => true 23 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 24 | ssl_certificate_verification => true 25 | } 26 | } 27 | 28 | if ([type] == "implantsdb" or "implantsdb" in [tags]) { 29 | elasticsearch { 30 | hosts => ["redelk-elasticsearch:9200"] 31 | sniffing => false 32 | manage_template => false 33 | ilm_enabled => false 34 | index => "implantsdb" 35 | user => ["redelk_ingest"] 36 | password => ["${CREDS_redelk_ingest}"] 37 | ssl => true 38 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 39 | ssl_certificate_verification => true 40 | } 41 | } 42 | 43 | if [infra][log][type] == "redirtraffic" { 44 | elasticsearch { 45 | hosts => ["redelk-elasticsearch:9200"] 46 | sniffing => false 47 | manage_template => false 48 | # ilm_enabled => true 49 | # ilm_rollover_alias => "redirtraffic" 50 | # ilm_policy => "redelk" 51 | # template_name => "redirtraffic" 52 | ilm_enabled => false 53 | index => "redirtraffic-%{+YYYY.MM.dd}" 54 | user => ["redelk_ingest"] 55 | password => ["${CREDS_redelk_ingest}"] 56 | ssl => true 57 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 58 | ssl_certificate_verification => true 59 | } 60 | } 61 | 62 | if [c2][log][type] == "credentials" { 63 | elasticsearch { 64 | hosts => ["redelk-elasticsearch:9200"] 65 | sniffing => false 66 | manage_template => false 67 | index => "credentials-%{+YYYY.MM.dd}" 68 | user => ["redelk_ingest"] 69 | password => ["${CREDS_redelk_ingest}"] 70 | ssl => true 71 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 72 | ssl_certificate_verification => true 73 | } 74 | } 75 | 76 | if ([type] == "bluecheck" or "bluecheck" in [tags]) { 77 | elasticsearch { 78 | hosts => ["redelk-elasticsearch:9200"] 79 | sniffing => false 80 | manage_template => false 81 | index => "bluecheck-%{+YYYY.MM.dd}" 82 | user => ["redelk_ingest"] 83 | password => ["${CREDS_redelk_ingest}"] 84 | ssl => true 85 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 86 | ssl_certificate_verification => true 87 | } 88 | } 89 | 90 | if [infralogtype] == "email" { 91 | elasticsearch { 92 | hosts => ["redelk-elasticsearch:9200"] 93 | sniffing => false 94 | manage_template => false 95 | index => "email-%{+YYYY.MM.dd}" 96 | user => ["redelk_ingest"] 97 | password => ["${CREDS_redelk_ingest}"] 98 | ssl => true 99 | cacert => "${CERTS_LOGSTASH_OUTPUT_CA}" 100 | ssl_certificate_verification => true 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/bluecheck_make_sectools_object.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to make a json object to be stored as nested object of all found security tools 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | def filter(event) 9 | string = event.get("[bluecheck][sectools]") 10 | string2 = string.gsub("ProcessID","{ \"ProcessID\"") 11 | string3 = string2.gsub(" Vendor",", \"Vendor\"") 12 | string4 = string3.gsub(" Product",", \"Product\"") 13 | string5 = string4.gsub(",{","},{") 14 | string6 = string5.gsub(": ",": \"") 15 | string7 = string6.gsub(", ","\", ") 16 | string8 = string7.gsub("},","\"},") 17 | string9 = "["+string8+"\" }]" 18 | json = JSON.parse(string9) 19 | event.tag("_rubyparseok") 20 | event.set("[bluecheck][sectools]", json) 21 | return [event] 22 | end 23 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makebeaconlogpath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to the full TXT file of a Cobalt Strike keystrokes file 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | def filter(event) 9 | host = event.get("[agent][name]") 10 | logpath = event.get("[log][file][path]") 11 | temppath = logpath.split('/cobaltstrike/server') 12 | implantlogpath = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath[1]}" 13 | event.tag("_rubyparseok") 14 | event.set("[implant][log_file]", implantlogpath) 15 | return [event] 16 | end 17 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makedownloadspath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to the Cobalt Strike downloaded file 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | def filter(event) 9 | host = event.get("[agent][name]") 10 | filename = event.get("[file][name]") 11 | file_path = event.get("[file][directory_local]") 12 | file_patharray = file_path.split(/\/([^\/]*)$/) 13 | file_id = file_patharray[-1] 14 | downloadsurl = "/c2logs/" + "#{host}" + "/cobaltstrike/downloads/" + "#{file_id}" + "_" + "#{filename}" 15 | event.tag("_rubyparseok") 16 | event.set("[file][url]", downloadsurl) 17 | return [event] 18 | end 19 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makekeystrokespath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to the full TXT file of a Cobalt Strike keystrokes file 4 | # Cobalt Strike 4.2 and higher 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | def filter(event) 10 | host = event.get("[agent][name]") 11 | logpath = event.get("[log][file][path]") 12 | implant_id = event.get("[implant][id]") 13 | desktop_session = event.get("[keystrokes][desktop_session]") 14 | temppath = logpath.split('/cobaltstrike/server') 15 | temppath2 = temppath[1].split(/\/([^\/]*)$/) 16 | filename = temppath2[1] 17 | keystrokespath = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/" + "#{filename}" 18 | event.tag("_rubyparseok") 19 | event.set("[keystrokes][url]", keystrokespath) 20 | return [event] 21 | end 22 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makekeystrokespath_beforecs4.2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to the full TXT file of a Cobalt Strike keystrokes file 4 | # Before Cobalt Strike 4.2 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | def filter(event) 10 | host = event.get("[agent][name]") 11 | logpath = event.get("[log][file][path]") 12 | implant_id = event.get("[implant][id]") 13 | temppath = logpath.split('/cobaltstrike') 14 | temppath2 = temppath[1].split(/\/([^\/]*)$/) 15 | keystrokespath = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/keystrokes_" + "#{implant_id}" + ".txt" 16 | event.tag("_rubyparseok") 17 | event.set("[keystrokes][url]", keystrokespath) 18 | return [event] 19 | end 20 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makescreenshotpath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert extra fields pointing to the Cobalt Strike screenshots 4 | # Cobalt Strike 4.2 and higher 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | def filter(event) 10 | host = event.get("[agent][name]") 11 | logpath = event.get("[log][file][path]") 12 | filename = event.get("[screenshot][file_name]") 13 | temppath = logpath.split('/cobaltstrike/server') 14 | temppath2 = temppath[1].split(/\/([^\/]*)$/) 15 | screenshoturl = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/screenshots/"+ "#{filename}" 16 | thumburl = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/screenshots/"+ "#{filename}" + ".thumb.jpg" 17 | event.tag("_rubyparseok") 18 | event.set("[screenshot][full]", screenshoturl) 19 | event.set("[screenshot][thumb]", thumburl) 20 | return [event] 21 | end 22 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/cs_makescreenshotpath_beforecs4.2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert extra fields pointing to the Cobalt Strike screenshots 4 | # before Cobalt Strike 4.2 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | def filter(event) 10 | require 'time' 11 | host = event.get("[agent][name]") 12 | logpath = event.get("[log][file][path]") 13 | implant_id = event.get("[implant][id]") 14 | timefromcs = event.get("[c2][timestamp]") + " UTC" 15 | timestring = Time.parse(timefromcs).strftime("%I%M%S") 16 | temppath = logpath.split('/cobaltstrike') 17 | temppath2 = temppath[1].split(/\/([^\/]*)$/) 18 | screenshoturl = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/screenshots/screen_" + "#{timestring}" + "_" + "#{implant_id}" + ".jpg" 19 | thumburl = "/c2logs/" + "#{host}" + "/cobaltstrike" + "#{temppath2[0]}" + "/screenshots/screen_" + "#{timestring}" + "_" + "#{implant_id}" + ".jpg.thumb.jpg" 20 | event.tag("_rubyparseok") 21 | event.set("[screenshot][full]", screenshoturl) 22 | event.set("[screenshot][thumb]", thumburl) 23 | return [event] 24 | end 25 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/outflankstage1_makedownloadspath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to downloaded file via Outflank Stage1 C2 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | 9 | def filter(event) 10 | host = event.get("[agent][name]") 11 | filename = event.get("[file][name]") 12 | file_path = event.get("[file][directory_local]") 13 | downloadsurl = "/c2logs/" + "#{host}" + "/stage1/downloads/" + "#{file_path}" + "_" + "#{filename}" 14 | event.tag("_rubyparseok") 15 | event.set("[file][url]", downloadsurl) 16 | return [event] 17 | end 18 | -------------------------------------------------------------------------------- /elkserver/mounts/logstash-config/redelk-main/scripts/outflankstage1_makelogpath.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # Script to have logstash insert an extra field pointing to the full TXT file of a Outflank Stage 1 C2 implant log file 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | 8 | def filter(event) 9 | host = event.get("[agent][name]") 10 | logpath = event.get("[log][file][path]") 11 | temppath = logpath.split('/logs') 12 | implantlogpath = "/c2logs/" + "#{host}" + "/stage1/logs" + "#{temppath[1]}" 13 | event.tag("_rubyparseok") 14 | event.set("[implant][log_file]", implantlogpath) 15 | return [event] 16 | end 17 | -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/default.conf.template: -------------------------------------------------------------------------------- 1 | # top-level http config for websocket headers 2 | # If Upgrade is defined, Connection = upgrade 3 | # If Upgrade is empty, Connection = close 4 | map $http_upgrade $connection_upgrade { 5 | default upgrade; 6 | '' close; 7 | } 8 | 9 | # Redirect HTTP to HTTPS 10 | server { 11 | listen 80 default_server; 12 | #listen [::]:80 default_server; 13 | 14 | #server_name ${EXTERNAL_DOMAIN}; 15 | server_tokens off; 16 | 17 | # Let's Encrypt 18 | location /.well-known/acme-challenge/ { 19 | root /var/www/certbot; 20 | } 21 | 22 | location / { 23 | return 301 https://$host$request_uri; 24 | } 25 | } 26 | 27 | # TLS config generated 2020-11-01, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration 28 | # https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&guideline=5.6 29 | server { 30 | listen 443 ssl http2; 31 | #listen [::]:443 ssl http2; 32 | 33 | #server_name ${EXTERNAL_DOMAIN}; 34 | server_tokens off; 35 | 36 | root /var/www/html; 37 | auth_basic "Restricted Access"; 38 | auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 39 | index index.html index.htm; 40 | autoindex on; 41 | 42 | ssl_certificate ${TLS_NGINX_CRT_PATH}; 43 | ssl_certificate_key ${TLS_NGINX_KEY_PATH}; 44 | ssl_session_timeout 1d; 45 | ssl_session_cache shared:MozSSL:10m; # about 40000 sessions 46 | ssl_session_tickets off; 47 | 48 | # intermediate configuration 49 | ssl_protocols TLSv1.2 TLSv1.3; 50 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 51 | ssl_prefer_server_ciphers off; 52 | 53 | ssl_dhparam /etc/nginx/conf.d/ssl-dhparams.pem; 54 | 55 | # HSTS (ngx_http_headers_module is required) (63072000 seconds) 56 | add_header Strict-Transport-Security "max-age=63072000" always; 57 | 58 | # OCSP stapling 59 | #ssl_stapling on; 60 | #ssl_stapling_verify on; 61 | 62 | # verify chain of trust of OCSP response using Root CA and Intermediate certs 63 | ssl_trusted_certificate ${TLS_NGINX_CA_PATH}; 64 | 65 | location / { 66 | proxy_pass https://redelk-kibana:5601; 67 | proxy_http_version 1.1; 68 | proxy_set_header X-Real-IP $remote_addr; 69 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 70 | proxy_set_header X-Forwarded-Proto $scheme; 71 | proxy_set_header X-Forwarded-Host $host; 72 | proxy_set_header X-Forwarded-Port $server_port; 73 | proxy_set_header Upgrade $http_upgrade; 74 | proxy_set_header Connection 'upgrade'; 75 | proxy_set_header Host $host; 76 | proxy_ssl_verify off; 77 | proxy_cache_bypass $http_upgrade; 78 | } 79 | 80 | location /c2logs { 81 | try_files $uri $uri/ =404; 82 | autoindex on; 83 | location ~* \.(txt)$ { 84 | add_header Content-Type text/plain; 85 | add_header 'X-Content-Type-Options' 'nosniff'; 86 | } 87 | location ~* \.(log)$ { 88 | add_header Content-Type text/plain; 89 | add_header 'X-Content-Type-Options' 'nosniff'; 90 | } 91 | location ~* \.(jpg)$ { 92 | add_header Content-Type image/jpeg; 93 | } 94 | } 95 | 96 | include conf.d/full.location-conf; 97 | } 98 | 99 | include conf.d/full.bloodhound-conf; 100 | # include conf.d/full.neo4j-conf; 101 | -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/full.bloodhound-conf.template: -------------------------------------------------------------------------------- 1 | upstream bloodhound_app { 2 | server redelk-bloodhound-app:8080; 3 | } 4 | 5 | server { 6 | listen 8443 ssl http2; 7 | 8 | #server_name ${EXTERNAL_DOMAIN}; 9 | server_tokens off; 10 | 11 | root /var/www/html; 12 | #auth_basic "Restricted Access"; 13 | #auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 14 | index index.html index.htm; 15 | autoindex on; 16 | 17 | ssl_certificate ${TLS_NGINX_CRT_PATH}; 18 | ssl_certificate_key ${TLS_NGINX_KEY_PATH}; 19 | ssl_session_timeout 1d; 20 | ssl_session_cache shared:MozSSL:10m; # about 40000 sessions 21 | ssl_session_tickets off; 22 | 23 | # intermediate configuration 24 | ssl_protocols TLSv1.2 TLSv1.3; 25 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 26 | ssl_prefer_server_ciphers off; 27 | 28 | ssl_dhparam /etc/nginx/conf.d/ssl-dhparams.pem; 29 | 30 | # HSTS (ngx_http_headers_module is required) (63072000 seconds) 31 | add_header Strict-Transport-Security "max-age=63072000" always; 32 | 33 | # OCSP stapling 34 | #ssl_stapling on; 35 | #ssl_stapling_verify on; 36 | 37 | # verify chain of trust of OCSP response using Root CA and Intermediate certs 38 | ssl_trusted_certificate ${TLS_NGINX_CA_PATH}; 39 | 40 | # Increase upload limit 41 | client_max_body_size 1500M; 42 | 43 | location / { 44 | #auth_basic "Restricted Access"; 45 | #auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 46 | 47 | 48 | proxy_pass http://bloodhound_app; 49 | proxy_set_header Host $host; 50 | 51 | # Proxy headers 52 | proxy_set_header Upgrade $http_upgrade; 53 | proxy_set_header Connection $connection_upgrade; 54 | proxy_set_header X-Real-IP $remote_addr; 55 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 56 | proxy_set_header X-Forwarded-Proto $scheme; 57 | proxy_set_header X-Forwarded-Host $host; 58 | proxy_set_header X-Forwarded-Port $server_port; 59 | 60 | # Proxy timeouts 61 | proxy_connect_timeout 60s; 62 | proxy_send_timeout 60s; 63 | proxy_read_timeout 60s; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/full.location-conf.template: -------------------------------------------------------------------------------- 1 | location /neo4jbrowser { 2 | return 301 http://$host:7474; 3 | # auth_basic "Restricted Access"; 4 | # auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 5 | # proxy_pass http://redelk-bloodhound-neo4j:7474/browser; 6 | } 7 | 8 | location /jupyter { 9 | auth_basic "Restricted Access"; 10 | auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 11 | 12 | proxy_pass http://redelk-jupyter:8888; 13 | proxy_set_header Host $host; 14 | proxy_set_header X-Real-Scheme $scheme; 15 | proxy_set_header X-Real-IP $remote_addr; 16 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 17 | 18 | # websocket headers 19 | proxy_http_version 1.1; 20 | proxy_set_header Upgrade "websocket"; 21 | proxy_set_header Connection "Upgrade"; 22 | proxy_read_timeout 86400; 23 | } -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/full.neo4j-conf.template: -------------------------------------------------------------------------------- 1 | 2 | upstream neo4j_bolt { 3 | server redelk-bloodhound-neo4j:7687; 4 | } 5 | 6 | server { 7 | listen 7687 ssl http2; 8 | #listen [::]:443 ssl http2; 9 | 10 | #server_name ${EXTERNAL_DOMAIN}; 11 | server_tokens off; 12 | 13 | #root /var/www/html; 14 | # auth_basic "Restricted Access"; 15 | # auth_basic_user_file /etc/nginx/conf.d/htpasswd.users; 16 | #index index.html index.htm; 17 | #autoindex on; 18 | 19 | ssl_certificate ${TLS_NGINX_CRT_PATH}; 20 | ssl_certificate_key ${TLS_NGINX_KEY_PATH}; 21 | ssl_session_timeout 1d; 22 | ssl_session_cache shared:MozSSL:10m; # about 40000 sessions 23 | ssl_session_tickets off; 24 | 25 | # intermediate configuration 26 | ssl_protocols TLSv1.2 TLSv1.3; 27 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 28 | ssl_prefer_server_ciphers off; 29 | 30 | ssl_dhparam /etc/nginx/conf.d/ssl-dhparams.pem; 31 | 32 | # HSTS (ngx_http_headers_module is required) (63072000 seconds) 33 | add_header Strict-Transport-Security "max-age=63072000" always; 34 | 35 | # OCSP stapling 36 | #ssl_stapling on; 37 | #ssl_stapling_verify on; 38 | 39 | # verify chain of trust of OCSP response using Root CA and Intermediate certs 40 | ssl_trusted_certificate ${TLS_NGINX_CA_PATH}; 41 | 42 | location / { 43 | proxy_pass http://neo4j_bolt; 44 | proxy_http_version 1.1; 45 | proxy_set_header X-Real-IP $remote_addr; 46 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 47 | proxy_set_header X-Forwarded-Proto $scheme; 48 | proxy_set_header X-Forwarded-Host $host; 49 | proxy_set_header X-Forwarded-Port $server_port; 50 | proxy_set_header Upgrade $http_upgrade; 51 | proxy_set_header Connection 'upgrade'; 52 | proxy_set_header Host $host; 53 | proxy_ssl_verify off; 54 | proxy_cache_bypass $http_upgrade; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/htpasswd.users.template: -------------------------------------------------------------------------------- 1 | redelk:$apr1$P73d6aE2$o3BRWz7QZhDh8gMykjDSd1 2 | elastic:$apr1$P73d6aE2$o3BRWz7QZhDh8gMykjDSd1 3 | -------------------------------------------------------------------------------- /elkserver/mounts/nginx-config/ssl-dhparams.pem.template: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz 3 | +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a 4 | 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 5 | YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi 6 | 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD 7 | ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== 8 | -----END DH PARAMETERS----- 9 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/cron.d/redelk.example: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # cron.d script for periodic actions related to RedELK 3 | # 4 | # Authors: 5 | # - Outflank B.V. / Marc Smeets 6 | # - Lorenzo Bernardi 7 | # 8 | 9 | SHELL=/bin/sh 10 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 11 | 12 | # RedELK rsync comands for getting remote log files from teamservers via rsync - replace $IP with the remote host's DNS/IP, $HOSTNAME with the remote hostname as configured in filebeat on that system amd $USER with the username to login with. 13 | # Repeat line for multiple teamservers. 14 | # m h dom mon dow user command 15 | #*/2 * * * * redelk /usr/share/redelk/bin/getremotelogs.sh $IP $HOSTNAME scponly 16 | # 17 | 18 | # Run update script for SSLBL Botnet C2 IP addresses every 30min 19 | # m h dom mon dow user command 20 | */30 * * * * redelk /usr/share/redelk/bin/run_abusechbotnetc2ipupdate.sh 21 | 22 | # Run update script for SSLBL SSL Certificate Blacklis 23 | # m h dom mon dow user command 24 | */30 * * * * redelk /usr/share/redelk/bin/run_abusechsslcertupdate.sh 25 | 26 | # Run update script for rogue domain list 27 | # And run Chameleon.py for remote checking of domain classification 28 | # m h dom mon dow user command 29 | 00 00,12 * * * redelk /usr/share/redelk/bin/run_roguedomainsupdate.sh 30 | 31 | # Start script to create thumbnails of received screenshots 32 | # m h dom mon dow user command 33 | */1 * * * * redelk /usr/share/redelk/bin/makethumbnail.py /var/www/html/c2logs/ 34 | 35 | # Run the daemon that will process alarms, enrichments and notifications 36 | * * * * * redelk /usr/share/redelk/bin/run_daemon.sh 37 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/config.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "loglevel": "WARNING", 3 | "interval": 3600, 4 | "tempDir": "/tmp", 5 | "redelkserver_letsencrypt": { 6 | "enable_letsencrypt": false, 7 | "external_domain": "", 8 | "le_email": "", 9 | "staging": "0" 10 | }, 11 | "project_name": "redelk-project", 12 | "es_connection": [ 13 | "https://elastic:{{ELASTIC_PASSWORD}}@redelk-elasticsearch:9200" 14 | ], 15 | "notifications": { 16 | "email": { 17 | "enabled": false, 18 | "smtp": { 19 | "host": "localhost", 20 | "port": 25, 21 | "login": "redelk@example.com", 22 | "pass": "redelk" 23 | }, 24 | "from": "redelk@example.com", 25 | "to": [ 26 | "redelk@example.com" 27 | ] 28 | }, 29 | "msteams": { 30 | "enabled": false, 31 | "webhook_url": "INSERT_MSTEAMS_WEBHOOK_URL_HERE" 32 | }, 33 | "slack": { 34 | "enabled": false, 35 | "webhook_url": "INSERT_SLACK_WEBHOOK_URL_HERE" 36 | } 37 | }, 38 | "alarms": { 39 | "alarm_dummy": { 40 | "enabled": false 41 | }, 42 | "alarm_filehash": { 43 | "enabled": true, 44 | "interval": 300, 45 | "vt_api_key": "", 46 | "ibm_basic_auth": "Basic ", 47 | "ha_api_key": "" 48 | }, 49 | "alarm_httptraffic": { 50 | "enabled": true, 51 | "interval": 310 52 | }, 53 | "alarm_useragent": { 54 | "enabled": true, 55 | "interval": 320 56 | }, 57 | "alarm_backendalarm": { 58 | "enabled": true, 59 | "interval": 320 60 | }, 61 | "alarm_manual": { 62 | "enabled": false, 63 | "interval": 300 64 | } 65 | }, 66 | "enrich": { 67 | "enrich_csbeacon": { 68 | "enabled": true, 69 | "interval": 300 70 | }, 71 | "enrich_stage1": { 72 | "enabled": true, 73 | "interval": 300 74 | }, 75 | "enrich_sliver": { 76 | "enabled": true, 77 | "interval": 300 78 | }, 79 | "enrich_greynoise": { 80 | "enabled": true, 81 | "interval": 310, 82 | "cache": 86400, 83 | "api_key": "" 84 | }, 85 | "enrich_tor": { 86 | "enabled": true, 87 | "interval": 360, 88 | "cache": 360 89 | }, 90 | "enrich_iplists": { 91 | "enabled": true, 92 | "interval": 30 93 | }, 94 | "enrich_synciplists": { 95 | "enabled": true, 96 | "interval": 360 97 | }, 98 | "enrich_syncdomainslists": { 99 | "enabled": true, 100 | "interval": 30 101 | }, 102 | "enrich_domainscategorization": { 103 | "enabled": true, 104 | "interval": 1, 105 | "ibm_basic_auth": "Basic ", 106 | "vt_api_key": "" 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/domainslist_redteam.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define domain names part of your red team infrastructure. Once on this list they will be periodically checked against appearance on lists of known bad domains. 5 | # One domain name per line 6 | # 7 | # Author: Outflank B.V. / Marc Smeets 8 | # 9 | # outflank.nl # test domain (valid) 10 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/iplist_alarmed.conf.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/redelk-config/etc/redelk/iplist_alarmed.conf.example -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/iplist_blueteam.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define the public IP addresses of the blue team. 5 | # 6 | # Authors: 7 | # - Outflank B.V. / Marc Smeets 8 | # - Lorenzo Bernardi 9 | # 10 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/iplist_customer.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define the public IP addresses of your target. This will mute alarms of sessions from these IP addresses. One IP per line. 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/iplist_redteam.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define the public IP addresses of the red team. This will mute alarms of sessions from these IP addresses. One IP per line. 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/iplist_unknown.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define the public IP addresses of systems you havent identified yet, but dont want to be alarmed about. One IP per line. 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/rogue_useragents.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Part of RedELK 3 | # 4 | # In this file you can define the User Agents that are known rogue and should never hit your C2 backend. 5 | # - One per line 6 | # - You need to insert query wildcards yourself, e.g. "curl" will match only "curl", "*curl*" will match anything containing "curl" 7 | # 8 | # Author: Outflank B.V. / Marc Smeets 9 | # 10 | curl* 11 | python-requests* 12 | Python-urllib* 13 | Slackbot* 14 | Facebot 15 | Twitterbot* 16 | facebookexternalhit* 17 | WhatsApp* 18 | *SkypeUriPreview* 19 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-config/etc/redelk/roguedomains.conf.example: -------------------------------------------------------------------------------- 1 | # Part of RedELK - Rogue domain names form multiple sources - AUTO UPDATED, DO NOT MAKE MANUAL CHANGES 2 | -------------------------------------------------------------------------------- /elkserver/mounts/redelk-logs/redteamdomaincheck.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/redelk-logs/redteamdomaincheck.txt -------------------------------------------------------------------------------- /elkserver/mounts/redelk-www/c2logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/redelk-www/c2logs/.gitkeep -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/apache2.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/apache2.log -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/beacon_1233239984.log: -------------------------------------------------------------------------------- 1 | 03/29 15:18:46 UTC [metadata] 13.80.254.1 <- 10.99.1.4; computer: LabMaster; user: outflank *; process: testbeacon.exe; pid: 2004; os: Windows; version: 6.2; beacon arch: x64 (x64) 2 | 03/29 15:19:00 UTC [input] upload 3 | 03/29 15:19:15 UTC [input] pwd 4 | 03/29 15:19:15 UTC [task] <> Tasked beacon to print working directory 5 | 03/29 15:19:19 UTC [checkin] host called home, sent: 8 bytes 6 | 03/29 15:19:20 UTC [output] 7 | Current directory is C:\Users\outflank\Desktop 8 | 9 | 03/29 15:19:39 UTC [input] cd \windows\temp 10 | 03/29 15:19:39 UTC [task] <> cd \windows\temp 11 | 03/29 15:19:39 UTC [checkin] host called home, sent: 21 bytes 12 | 03/29 15:19:40 UTC [input] pwd 13 | 03/29 15:19:40 UTC [task] <> Tasked beacon to print working directory 14 | 03/29 15:19:43 UTC [checkin] host called home, sent: 8 bytes 15 | 03/29 15:19:43 UTC [output] 16 | Current directory is C:\windows\temp 17 | 18 | 03/29 15:19:49 UTC [input] upload 19 | 03/29 15:19:56 UTC [task] <> Tasked beacon to upload C:\Users\outflank\Desktop\OfferNr2020F6592_salary.doc as OfferNr2020F6592_salary.doc 20 | 03/29 15:19:56 UTC [indicator] file: f06d1ae4cbde03cde3898f05b841850f 150016 bytes OfferNr2020F6592_salary.doc 21 | 03/29 15:19:58 UTC [checkin] host called home, sent: 150055 bytes 22 | 03/29 15:20:21 UTC [input] ls 23 | 03/29 15:20:21 UTC [task] <> Tasked beacon to list files in . 24 | 03/29 15:20:21 UTC [checkin] host called home, sent: 19 bytes 25 | 03/29 15:20:21 UTC [output] 26 | C:\windows\temp\* 27 | D 0 03/29/2020 15:20:01 . 28 | D 0 03/29/2020 15:20:01 .. 29 | D 0 03/29/2020 11:18:45 C4663637-44E3-43AA-9240-B6235C0B5998-Sigs 30 | F 33311 03/29/2020 09:50:19 chrome_installer.log 31 | D 0 03/29/2020 09:37:54 Crashpad 32 | F 0 03/29/2020 09:27:39 DMI6A08.tmp 33 | D 0 03/29/2020 09:43:18 hsperfdata_LabMaster$ 34 | F 0 03/29/2020 11:24:19 LabMaster-20200329-1124.log 35 | F 8670 03/29/2020 11:25:55 LabMaster-20200329-1125.log 36 | F 14480 03/29/2020 11:25:59 LabMaster-20200329-1125a.log 37 | F 11410 03/29/2020 11:25:59 LabMaster-20200329-1125b.log 38 | F 32790 03/29/2020 11:26:29 LabMaster-20200329-1126.log 39 | F 10400 03/29/2020 11:18:45 MpCmdRun.log 40 | F 18736 03/29/2020 11:18:45 MpSigStub.log 41 | F 150016 03/29/2020 15:19:58 OfferNr2020F6592_salary.doc 42 | F 0 03/29/2020 11:24:19 officeclicktorun.exe_streamserver(202003291124191078).log 43 | F 102 03/29/2020 09:17:42 silconfig.log 44 | D 0 03/29/2020 09:18:28 winrmdone 45 | D 0 03/29/2020 09:18:24 winrmrunning 46 | 47 | 48 | 03/29 15:29:24 UTC [input] exit 49 | 03/29 15:29:24 UTC [task] <> Tasked beacon to exit 50 | 03/29 15:29:28 UTC [checkin] host called home, sent: 8 bytes 51 | 03/29 15:29:28 UTC [output] 52 | beacon exit. 53 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/beacon_496538698.log: -------------------------------------------------------------------------------- 1 | 03/29 13:16:36 UTC [metadata] 13.80.254.1 <- 10.99.1.4; computer: LabMaster; user: outflank *; process: testbeacon.exe; pid: 3324; os: Windows; version: 6.2; beacon arch: x64 (x64) 2 | 03/29 13:26:57 UTC [input] screenshot 3 | 03/29 13:26:57 UTC [task] Tasked beacon to take screenshot 4 | 03/29 13:27:01 UTC [checkin] host called home, sent: 197186 bytes 5 | 03/29 13:27:02 UTC [output] 6 | received screenshot (166469 bytes) 7 | 8 | 03/29 13:54:31 UTC [input] keylogger 9 | 03/29 13:54:31 UTC [task] Tasked beacon to log keystrokes 10 | 03/29 13:54:35 UTC [checkin] host called home, sent: 81474 bytes 11 | 03/29 13:55:09 UTC [output] 12 | received keystrokes 13 | 14 | 03/29 13:55:18 UTC [output] 15 | received keystrokes 16 | 17 | 03/29 13:55:34 UTC [input] jobkill 18 | 03/29 13:55:34 UTC [error] jobkill error: not enough arguments 19 | 03/29 13:55:36 UTC [input] jobs 20 | 03/29 13:55:36 UTC [task] <> Tasked beacon to list jobs 21 | 03/29 13:55:37 UTC [checkin] host called home, sent: 8 bytes 22 | 03/29 13:55:37 UTC [output] 23 | 1 0 keystroke logger 24 | 25 | 26 | 03/29 13:55:42 UTC [input] jobkill 1 27 | 03/29 13:55:42 UTC [task] <> Tasked beacon to kill job 1 28 | 03/29 13:55:42 UTC [checkin] host called home, sent: 10 bytes 29 | 03/29 15:01:06 UTC [input] exit 30 | 03/29 15:01:06 UTC [task] <> Tasked beacon to exit 31 | 03/29 15:01:08 UTC [checkin] host called home, sent: 8 bytes 32 | 03/29 15:01:08 UTC [output] 33 | beacon exit. 34 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/keystrokes/keystrokes_496538698.txt: -------------------------------------------------------------------------------- 1 | 03/29 13:55:09 UTC Received keystrokes 2 | 3 | 4 | 5 | CCobalt Strike 6 | E======= 7 | r2[command] 8 | 9 | CRun 10 | E======= 11 | notepad 12 | 13 | C 14 | E======= 15 | 16 | 17 | 18 | CUntitled - Notepad 19 | E======= 20 | test for keylogger 21 | 03/29 13:55:18 UTC Received keystrokes 22 | 23 | - hello :-) 24 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/screenshots/screen_012702_496538698.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/screenshots/screen_012702_496538698.jpg -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/screenshots/screen_030037_2019412980.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/10.99.1.4/screenshots/screen_030037_2019412980.jpg -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200329/events.log: -------------------------------------------------------------------------------- 1 | 03/29 12:29:29 UTC *** MarcS joined 2 | 03/29 13:16:31 UTC *** initial beacon from outflank *@10.99.1.4 (LabMaster) 3 | 03/29 13:54:14 UTC *** neo joined 4 | 03/29 14:13:46 UTC *** neo quit 5 | 03/29 14:37:25 UTC *** neo joined 6 | 03/29 14:48:36 UTC *** MarcS hosted file /root/cobaltstrike/uploads/OfferNr2020F6592_salary.doc @ http://redira1.totallynotavirus.nl:80/downloaddoc.php?f=56893 7 | 03/29 14:54:21 UTC *** MarcS hosted file /root/cobaltstrike/uploads/OfferNr2020F6592_salary.doc @ http://redira1.totallynotavirus.nl:80/download/doc56893 8 | 03/29 14:54:49 UTC *** initial beacon from outflank *@10.99.1.4 (LabMaster) 9 | 03/29 15:12:10 UTC *** MarcS quit 10 | 03/29 15:12:28 UTC *** neo quit 11 | 03/29 15:12:49 UTC *** neo joined 12 | 03/29 15:14:07 UTC *** MarcS joined 13 | 03/29 15:18:37 UTC *** initial beacon from outflank *@10.99.1.4 (LabMaster) 14 | 03/29 16:04:01 UTC *** MarcS quit 15 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.2.10/beacon_455228.log: -------------------------------------------------------------------------------- 1 | 03/30 09:10:57 UTC [metadata] beacon_22170412 -> 10.1.2.10; computer: S-WIN21; user: ADMIN-W.Trommel *; process: wsmprovhost.exe; pid: 2476; os: Windows; version: 6.3; beacon arch: x64 (x64) 2 | 03/30 09:10:51 UTC [output] 3 | established link to parent beacon: 10.1.4.10 4 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/keystrokes/keystrokes_936715360.txt: -------------------------------------------------------------------------------- 1 | 03/30 07:58:09 UTC Received keystrokes 2 | 3 | 4 | 5 | CSave As 6 | E======= 7 | RecipeTeammeeting_ 8 | 03/30 07:58:19 UTC Received keystrokes 9 | 10 | Apr1_newrecipes 11 | 03/30 07:58:30 UTC Received keystrokes 12 | 13 | 14 | 15 | 03/30 07:58:49 UTC Received keystrokes 16 | 17 | 18 | 19 | CRecipeTeammeeting_Apr1_newrecipes - PowerPoint 20 | E======= 21 | 2021 22 | 03/30 07:58:59 UTC Received keystrokes 23 | 24 | 2020 & Holidat season 20202[left]2[left]2[left]2[left]2[left] 25 | 03/30 07:59:09 UTC Received keystrokes 26 | 27 | 2[left]2[left]2[left]2[left]2[left]2[left]2[left]2[left]y2[end] 28 | 2021 introduces 29 | 03/30 07:59:18 UTC Received keystrokes 30 | 31 | new 'special' flavour' 2[left]2[left]2[left]2[left]2[left]2[left] 32 | 03/30 07:59:27 UTC Received keystrokes 33 | 34 | 2[end] 35 | 03/30 07:59:37 UTC Received keystrokes 36 | 37 | 38 | We need to act now to j2[backspace]eep ahe 39 | 03/30 07:59:51 UTC Received keystrokes 40 | 41 | ad of competitors2[right]k 42 | 03/30 08:00:00 UTC Received keystrokes 43 | 44 | 45 | 2[tab] 46 | 03/30 08:00:10 UTC Received keystrokes 47 | 48 | Decided: 49 | 03/30 08:02:47 UTC Received keystrokes 50 | 51 | Ani 52 | 03/30 08:03:01 UTC Received keystrokes 53 | 54 | se snowflakes 55 | 2[tab]Decided 56 | 03/30 08:03:10 UTC Received keystrokes 57 | 58 | : Peanut 59 | 03/30 08:03:20 UTC Received keystrokes 60 | 61 | butter OR 62 | 03/30 08:03:30 UTC Received keystrokes 63 | 64 | Nutella 65 | 03/30 08:09:48 UTC Received keystrokes 66 | 67 | 68 | 69 | C 70 | E======= 71 | 2[command] 72 | 03/30 08:09:58 UTC Received keystrokes 73 | 74 | 75 | 76 | CSearch 77 | E======= 78 | start 79 | 03/30 08:10:07 UTC Received keystrokes 80 | 81 | up2[down]2[down]2[right] 82 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_075707_936715360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_075707_936715360.jpg -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_075830_936715360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_075830_936715360.jpg -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_080335_936715360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/10.1.3.10/screenshots/screen_080335_936715360.jpg -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/downloads.log: -------------------------------------------------------------------------------- 1 | 03/30 09:30:59 UTC 10.1.3.10 358093816 114 /root/cobaltstrike/downloads/fa59012fc passwords.txt.txt H:\ 2 | 03/30 09:31:04 UTC 10.1.3.10 358093816 1056424 /root/cobaltstrike/downloads/c006e2856 RecipeTeammeeting_Apr1_newrecipes.pptx H:\ 3 | 03/30 09:34:26 UTC 10.1.3.10 358093816 113354 /root/cobaltstrike/downloads/518edf74d sysmonconfig-export.xml \\s-win43\Software\ 4 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/events.log: -------------------------------------------------------------------------------- 1 | 03/30 07:07:24 UTC *** MarcS joined 2 | 03/30 07:55:39 UTC *** initial beacon from w.tax@10.1.3.10 (L-WIN223) 3 | 03/30 08:13:47 UTC *** initial beacon from w.tax@10.1.3.10 (L-WIN223) 4 | 03/30 08:41:18 UTC *** initial beacon from w.tax@10.1.3.10 (L-WIN223) 5 | 03/30 08:44:13 UTC *** initial beacon from W.Tax *@10.1.3.11 (L-WIN224) 6 | 03/30 09:04:07 UTC *** initial beacon from SYSTEM *@10.1.4.10 (L-WIN227) 7 | 03/30 09:06:33 UTC *** initial beacon from ADMIN-w.trommel@10.1.4.10 (L-WIN227) 8 | 03/30 09:10:51 UTC *** initial beacon from ADMIN-W.Trommel *@10.1.2.10 (S-WIN21) 9 | 03/30 15:37:41 UTC *** MarcS quit 10 | 03/30 20:03:00 UTC *** neo quit 11 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/weblog_80.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200330/weblog_80.log -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200402/weblog_80.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200402/weblog_80.log -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/logs/200403/weblog_80.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/logs/200403/weblog_80.log -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/profiles/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/profiles/.DS_Store -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/profiles/MallableConfig-DomainFronting.profile: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # This is a basic example mallable configuration file for CobaltStrike that works with RedELK 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | # Important 1 - change the value of $NameOfYourDomainFrontingEndpoint in the config below to the name of your DomainFronting endpoint name, e.g. somefancyname.azureedgee.net 8 | # Important 2 - configure the listeners in CobaltStrike accordingly: set the HTTP Host Header to the name of your DomainFronting endpoint name, and set the HTTP Hosts to a frontable domain. 9 | # 10 | 11 | set sleeptime "5000"; 12 | set jitter "10"; 13 | set useragent "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"; 14 | 15 | http-config { 16 | set headers "Date, Server, Content-Length, Keep-Alive, Connection, Content-Type"; 17 | header "Server" "Apache"; 18 | header "Keep-Alive" "timeout=5, max=100"; 19 | header "Connection" "Keep-Alive"; 20 | set trust_x_forwarded_for "true"; 21 | } 22 | 23 | http-get { 24 | set uri "/TRAINING-BEACON"; 25 | 26 | client { 27 | header "Accept" "*/*"; 28 | header "Pragma" "no-cache"; 29 | header "Connection" "Keep-Alive"; 30 | header "Host" "redelkdemo.azureedge.net"; 31 | metadata { 32 | base64; 33 | header "Cookie"; 34 | } 35 | } 36 | 37 | server { 38 | header "Content-Type" "application/octet-stream"; 39 | 40 | output { 41 | print; 42 | } 43 | } 44 | } 45 | 46 | http-post { 47 | set uri "/TRAINING-BEACON/submit.php"; 48 | client { 49 | header "Content-Type" "application/octet-stream"; 50 | header "Host" "redelkdemo.azureedge.net"; 51 | 52 | id { 53 | #netbios; 54 | parameter "id"; 55 | } 56 | 57 | output { 58 | print; 59 | } 60 | } 61 | 62 | server { 63 | header "Content-Type" "text/html"; 64 | 65 | output { 66 | print; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/cobaltstrike/uploads/OfferNr2020F6592_salary.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/cobaltstrike/uploads/OfferNr2020F6592_salary.doc -------------------------------------------------------------------------------- /elkserver/mounts/sample-data/logs/nginx.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/elkserver/mounts/sample-data/logs/nginx.log -------------------------------------------------------------------------------- /elkserver/remove-redelkinstall-on-elkserver-USEATOWNRISK.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to remove RedELK on elkserver 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | 10 | echo "" 11 | echo "" 12 | echo " !! USE AT OWN RISK !! " 13 | echo "" 14 | echo " This script will rudimentarily remove" 15 | echo " all kinds of things on your system." 16 | echo "" 17 | echo " Check the code before running. " 18 | echo "" 19 | echo " 5 sec to abort" 20 | echo "" 21 | sleep 5 22 | 23 | echo "[-] Stopping all RedELK docker containers" 24 | for i in $(docker ps -a|grep redelk|awk '{print $1}'); do docker stop $i; done 25 | 26 | echo "[-] removing all RedELK docker containers" 27 | for i in $(docker ps -a |grep redelk|awk '{print $1}'); do docker rm -f $i; done 28 | 29 | echo "[-] Removing all RedELK docker images" 30 | for i in $(docker image ls |grep redelk|awk '{print $3}'); do docker rmi -f $i; done 31 | 32 | echo "[-] Removing all RedELK docker volumes" 33 | for i in $(docker volume ls |grep redelk|awk '{print $2}'); do docker volume rm -f $i; done 34 | 35 | echo "[-] Removing all not used docker networks" 36 | docker network prune -f 37 | 38 | echo "[*] Done. You can manually remove this directory as well if you like." 39 | echo "" 40 | -------------------------------------------------------------------------------- /example-data-and-configs/Apache/redelk-redir-apache.conf: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # This is an example configuration file for Apache that works with RedELK 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # With help from: Jason Lang / @curi0usJack 7 | # 8 | # Put this file in /etc/apache2/sites-available and: 9 | # - Modify $$HOSTNAME_OF_THIS_REDIRECTOR and $$IP_OF_YOUR_C2SERVER 10 | # - run a2enmod rewrite proxy proxy_http proxy_connect ssl proxy_html deflate headers 11 | # - run a2ensite redelk-redir-apache.conf 12 | # - run service apache2 restart 13 | # 14 | # It will log to file /var/log/access-redelk.log - if you used the RedELK installer than Filebeat will pick this up and send it to your RedELK server. 15 | # 16 | 17 | Listen 80 18 | Listen 8070 19 | 20 | 21 | 22 | DocumentRoot /var/www/html 23 | 24 | # exact LogFormat setup is important for RedELK! 25 | LogFormat "%t %{hostname}e apache[%P]: frontend:%{frontend_name}e/%A:%{local}p backend:%{backend_name}e client:%h:%{remote}p xforwardedfor:%{X-Forwarded-For}i headers:{%{User-Agent}i|%{Host}i|%{X-Forwarded-For}i|%{X-Forwarded-Proto}i|%{X-Host}i|%{Forwarded}i|%{Via}i|} statuscode:%s request:%r" redelklogformat 26 | CustomLog ${APACHE_LOG_DIR}/access-redelk.log redelklogformat 27 | 28 | # Set the defaults. Assume all incoming requests are decoys unless changed by RewriteRule below. 29 | # backend name should start with decoy or with c2 30 | SetEnv backend_name decoy 31 | SetEnv hostname $$HOSTNAME_OF_THIS_REDIRECTOR 32 | # frontend name can be whatever you like 33 | SetEnv frontend_name www-http 34 | 35 | # Enable RewriteEngine 36 | RewriteEngine On 37 | 38 | # Send request to C2 backend when it matches specific traffic rules, and set environment variables with E= 39 | # We want to match specific traffic - correlates with the example Cobalt Strike profile shipped with RedELK : 40 | # /dpixel* 41 | # /submit.php* 42 | # /XXXX generic stager URI 43 | RewriteCond %{REQUEST_URI} /dpixel [OR] 44 | RewriteCond %{REQUEST_URI} /submit.php [OR] 45 | RewriteCond %{REQUEST_URI} /TRAINING-BEACON [OR] 46 | RewriteCond %{REQUEST_URI} /[0-z][0-z][0-z][0-z]$ 47 | RewriteRule ^.*$ http://$$IP_OF_YOUR_C2SERVER%{REQUEST_URI} [E=backend_name:c2,P] 48 | ProxyPassReverse "/" "http://$$IP_OF_YOUR_C2SERVER" 49 | 50 | # if requets didn't match previous rules, this rule will forward the request to a decoy website with 302 redirect 51 | RewriteRule ^ https://www.amazon.com [E=backend_name:decoy-amazon,L,R=302] 52 | 53 | 54 | 55 | 56 | 57 | ServerAdmin webmaster@localhost 58 | DocumentRoot /var/www/html 59 | Options -Indexes 60 | ErrorLog ${APACHE_LOG_DIR}/error.log 61 | CustomLog ${APACHE_LOG_DIR}/access.log combined 62 | ErrorDocument 404 /error_pages/404.txt 63 | ErrorDocument 403 /error_pages/404.txt 64 | 65 | 66 | -------------------------------------------------------------------------------- /example-data-and-configs/CobaltStrike/MallableConfig-DomainFronting.profile: -------------------------------------------------------------------------------- 1 | # Part of RedELK 2 | # 3 | # This is a basic example mallable configuration file for CobaltStrike that works with RedELK 4 | # 5 | # Author: Outflank B.V. / Marc Smeets 6 | # 7 | # Important 1 - change the value of $NameOfYourDomainFrontingEndpoint in the config below to the name of your DomainFronting endpoint name, e.g. somefancyname.azureedgee.net 8 | # Important 2 - configure the listeners in CobaltStrike accordingly: set the HTTP Host Header to the name of your DomainFronting endpoint name, and set the HTTP Hosts to a frontable domain. 9 | # 10 | 11 | set sleeptime "5000"; 12 | set jitter "10"; 13 | set useragent "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"; 14 | 15 | http-config { 16 | set headers "Date, Server, Content-Length, Keep-Alive, Connection, Content-Type"; 17 | header "Server" "Apache"; 18 | header "Keep-Alive" "timeout=5, max=100"; 19 | header "Connection" "Keep-Alive"; 20 | set trust_x_forwarded_for "true"; 21 | } 22 | 23 | http-get { 24 | set uri "/TRAINING-BEACON"; 25 | 26 | client { 27 | header "Accept" "*/*"; 28 | header "Pragma" "no-cache"; 29 | header "Connection" "Keep-Alive"; 30 | header "Host" "$NameOfYourDomainFrontingEndpoint"; 31 | metadata { 32 | base64; 33 | header "Cookie"; 34 | } 35 | } 36 | 37 | server { 38 | header "Content-Type" "application/octet-stream"; 39 | 40 | output { 41 | print; 42 | } 43 | } 44 | } 45 | 46 | http-post { 47 | set uri "/TRAINING-BEACON/submit.php"; 48 | client { 49 | header "Content-Type" "application/octet-stream"; 50 | header "Host" "$NameOfYourDomainFrontingEndpoint"; 51 | 52 | id { 53 | #netbios; 54 | parameter "id"; 55 | } 56 | 57 | output { 58 | print; 59 | } 60 | } 61 | 62 | server { 63 | header "Content-Type" "text/html"; 64 | 65 | output { 66 | print; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /example-data-and-configs/ExampleData/Readme.md: -------------------------------------------------------------------------------- 1 | # Example data # 2 | The files in this directory are the logs from the lab used in the blog post [RedELK Part 3](https://outflank.nl/blog/2020/04/07/redelk-part-3-achieving-operational-oversight/). 3 | 4 | You can use the files in this directory to play along with the blog post, and to have some example data in your RedELK installation. 5 | 6 | There are two ways of importing the data. Both ways require that you have got a RedELK server up and running (you successfully ran the install-redelk.sh installer). 7 | 8 | WARNING - both methods are not fully tested. Create an issue when this goes wrong and you aren't able to troubleshoot yourself. 9 | 10 | ## Method 1 - import ES data 11 | You need the files `redelk_elasticsearch-backup.tgz` and `cslogs.tgz`. 12 | 13 | On the RedELK server run: 14 | * Extract the cslogs.tgz to /var/www/html 15 | * Extract the redelk_elasticsearch-backup.tgz to / 16 | * echo "path.repo: [\"/elasticsearch-backup\"]" >> /etc/elasticsearch/elasticsearch.yml 17 | * service elasticsearch restart 18 | * Register the new repository in ES - answer should be {"acknowledged":true} 19 | 20 | `curl -X PUT "localhost:9200/_snapshot/redelkdemo" -H 'Content-Type: application/json' -d' 21 | { 22 | "type": "fs", 23 | "settings": { 24 | "compress" : true, 25 | "location": "/elasticsearch-backup" 26 | } 27 | }'` 28 | * Start restore - can take some time but answer should be {"acknowledged":true} 29 | `curl -X POST "localhost:9200/_snapshot/redelkdemo/snapshot-number-one/_restore" -H 'Content-Type: application/json' -d' 30 | { 31 | "indices": "rtops-*,redirtraffic-*,beacondb", 32 | "ignore_unavailable": true, 33 | "include_global_state": true 34 | }'` 35 | 36 | 37 | ## Method 2 - using filebeat 38 | In this method you will need the files `c2server1_cobaltstrike.zip`, `c2server2_cobaltstrike.zip`, `redira1_access-redelk.log` and `redirb1_haproxy.log`. 39 | You will also need to have the same offensive systems created - or be more experienced with filebeat and know how to import data using the right tags. 40 | 41 | Place files on systems as following: 42 | * On redira1: `redira1_access-redelk.log` as `/var/log/apache2/access-redelk.log` 43 | * On redirb1: `redirb1_haproxy.log` as `/var/log/haproxy.log` 44 | * On c2server1: extract `c2server1_cobaltstrike.zip` to `/root/cobaltstrike` 45 | * On c2server2: extract `c2server2_cobaltstrike.zip` to `/root/cobaltstrike` 46 | * Run each RedELK installer script as would normally do 47 | -------------------------------------------------------------------------------- /example-data-and-configs/ExampleData/c2server1_cobaltstrike.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/example-data-and-configs/ExampleData/c2server1_cobaltstrike.zip -------------------------------------------------------------------------------- /example-data-and-configs/ExampleData/c2server2_cobaltstrike.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/example-data-and-configs/ExampleData/c2server2_cobaltstrike.zip -------------------------------------------------------------------------------- /example-data-and-configs/ExampleData/cslogs.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/example-data-and-configs/ExampleData/cslogs.tgz -------------------------------------------------------------------------------- /example-data-and-configs/ExampleData/redelk_elasticsearch-backup.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/example-data-and-configs/ExampleData/redelk_elasticsearch-backup.tgz -------------------------------------------------------------------------------- /helper-scripts/get_fields_mappings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Part of RedELK 3 | # Helper script to read out Kibana settings and dump the field names, EStype and Kibana type in a Markup table 4 | 5 | function QueryES() { 6 | curl --user ${KIBANACREDS} -k -s -X GET "https://${KIBANAIP}:5601/api/saved_objects/index-pattern/${type}" -H 'kbn-xsrf: true' | jq -r '(.attributes.fields | fromjson)[] | select(.name | startswith("_")|not)| select(.name | startswith("@")|not)|"| " + .name + " | " + (.esTypes|tostring) + " | " + .type + " | |"'| tr -d '["]' >> $outfile 7 | } 8 | 9 | echo "[*] Trying to auto determine the IP address of the redelk-kibana docker container." 10 | KIBANAIP=`docker inspect redelk-kibana|grep \"IPAddress\"\:|grep -v '\"\"'|tr -d " ",|awk -F\: '{print $2}'|tr -d \"` 11 | echo "[*] Found IP address: $KIBANAIP" 12 | echo "[*] Trying to auto determine the credentials for accessing Kibana." 13 | KIBANACREDS="redelk:`grep CREDS_redelk= ../elkserver/.env|awk -F\= '{print $2}'`" 14 | echo "[*] Found credentials: $KIBANACREDS" 15 | 16 | # index redirtraffic 17 | type=redirtraffic 18 | outfile=redelk_fieldnames_${type}.md 19 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 20 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 21 | QueryES 22 | 23 | # index rtops 24 | type=rtops 25 | outfile=redelk_fieldnames_${type}.md 26 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 27 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 28 | QueryES 29 | 30 | # index bluecheck 31 | type=bluecheck 32 | outfile=redelk_fieldnames_${type}.md 33 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 34 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 35 | QueryES 36 | 37 | # index credentials 38 | type=credentials 39 | outfile=redelk_fieldnames_${type}.md 40 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 41 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 42 | QueryES 43 | 44 | # index bluecheck 45 | type=bluecheck 46 | outfile=redelk_fieldnames_${type}.md 47 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 48 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 49 | QueryES 50 | 51 | # index email 52 | type=email 53 | outfile=redelk_fieldnames_${type}.md 54 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 55 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 56 | QueryES 57 | 58 | # index implantsdb 59 | type=implantsdb 60 | outfile=redelk_fieldnames_${type}.md 61 | echo "| Fieldname | ES type | Kibana type | Comment | " > $outfile 62 | echo "| ----------------------------- | ------------ | -------------- | --------------------------------------------- | " >> $outfile 63 | QueryES 64 | -------------------------------------------------------------------------------- /helper-scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | ndjson~=0.3.1 2 | -------------------------------------------------------------------------------- /helper-scripts/reset_ES_readwrite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Got ya, YOLO removing read only" 3 | 4 | source /root/elkserver/.env 5 | docker exec -it redelk-elasticsearch curl --user redelk:${CREDS_redelk} -k -X PUT "https://localhost:9200/_all/_settings" -H 'Content-Type: application/json' -d'{ "index.blocks.read_only_allow_delete" : false } }' 6 | -------------------------------------------------------------------------------- /images/dashboard-add-ioc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-add-ioc.png -------------------------------------------------------------------------------- /images/dashboard-alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-alarm.png -------------------------------------------------------------------------------- /images/dashboard-downloads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-downloads.png -------------------------------------------------------------------------------- /images/dashboard-health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-health.png -------------------------------------------------------------------------------- /images/dashboard-implants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-implants.png -------------------------------------------------------------------------------- /images/dashboard-ioc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-ioc.png -------------------------------------------------------------------------------- /images/dashboard-mitre-attack-navigator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-mitre-attack-navigator.png -------------------------------------------------------------------------------- /images/dashboard-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-overview.png -------------------------------------------------------------------------------- /images/dashboard-rtops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-rtops.png -------------------------------------------------------------------------------- /images/dashboard-summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-summary.png -------------------------------------------------------------------------------- /images/dashboard-tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-tasks.png -------------------------------------------------------------------------------- /images/dashboard-traffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/dashboard-traffic.png -------------------------------------------------------------------------------- /images/redelk_IOC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_IOC.jpg -------------------------------------------------------------------------------- /images/redelk_dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_dashboard.jpg -------------------------------------------------------------------------------- /images/redelk_dashboard2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_dashboard2.jpg -------------------------------------------------------------------------------- /images/redelk_dashboard3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_dashboard3.jpg -------------------------------------------------------------------------------- /images/redelk_downloads.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_downloads.jpg -------------------------------------------------------------------------------- /images/redelk_keystrokes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_keystrokes.jpg -------------------------------------------------------------------------------- /images/redelk_opening.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_opening.jpg -------------------------------------------------------------------------------- /images/redelk_overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_overview.jpg -------------------------------------------------------------------------------- /images/redelk_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_overview.png -------------------------------------------------------------------------------- /images/redelk_redirtraffic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_redirtraffic.jpg -------------------------------------------------------------------------------- /images/redelk_screenshots.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_screenshots.jpg -------------------------------------------------------------------------------- /images/redelk_timeline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_timeline.jpg -------------------------------------------------------------------------------- /images/redelk_timeline_details.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outflanknl/RedELK/3c54953cad65383b099cdc315eab6579f37d8902/images/redelk_timeline_details.jpg -------------------------------------------------------------------------------- /redirs/filebeat/filebeat.yml.example: -------------------------------------------------------------------------------- 1 | filebeat.inputs: 2 | - type: log 3 | enabled: true 4 | fields_under_root: true 5 | paths: 6 | - /var/log/haproxy.log 7 | fields: 8 | infra: 9 | log: 10 | type: redirtraffic 11 | redir: 12 | program: haproxy 13 | - type: log 14 | enabled: true 15 | fields_under_root: true 16 | paths: 17 | - /var/log/apache2/access-redelk.log 18 | fields: 19 | infra: 20 | log: 21 | type: redirtraffic 22 | redir: 23 | program: apache 24 | - type: log 25 | enabled: true 26 | fields_under_root: true 27 | paths: 28 | - /var/log/nginx/access-redelk.log 29 | fields: 30 | infra: 31 | log: 32 | type: redirtraffic 33 | redir: 34 | program: nginx 35 | 36 | filebeat.config.modules: 37 | path: ${path.config}/modules.d/*.yml 38 | reload.enabled: false 39 | 40 | setup.template.settings: 41 | index.number_of_shards: 3 42 | 43 | name: "@@HOSTNAME@@" 44 | fields_under_root: true 45 | fields: 46 | infra: 47 | attack_scenario: @@ATTACKSCENARIO@@ 48 | 49 | output.logstash: 50 | hosts: ["@@HOSTANDPORT@@"] 51 | ssl.certificate_authorities: ["/etc/filebeat/redelkCA.crt"] 52 | -------------------------------------------------------------------------------- /redirs/remove-redelkinstall-on-redirs-USEATOWNRISK.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Part of RedELK 4 | # Script to remove RedELK on redirectors 5 | # 6 | # Author: Outflank B.V. / Marc Smeets 7 | # 8 | 9 | 10 | echo "" 11 | echo "" 12 | echo " !! USE AT OWN RISK !! " 13 | echo "" 14 | echo " This script will rudimentarily remove" 15 | echo " all kinds of things on your system." 16 | echo "" 17 | echo " Check the code before running. " 18 | echo "" 19 | echo " 5 sec to abort" 20 | echo "" 21 | sleep 5 22 | 23 | echo "[-] Stopping ELK services" 24 | service filebeat stop 25 | 26 | echo "[-] Nuking crontab for redelk user actions" 27 | rm -rf /cp /etc/cron.d/redelk* 28 | 29 | echo "[-] Removing apt-transport-https" 30 | apt-get remove -y apt-transport-https 31 | 32 | echo "[-] Removing FileBeat" 33 | apt-get purge -y filebeat 34 | 35 | echo "[-] Removing FileBeat directories" 36 | rm -rf /etc/filebeat 37 | rm -rf /usr/share/filebeat 38 | rm -rf /var/log/filebeat* 39 | rm -rf /var/lib/filebeat 40 | 41 | echo "[-] Removing other not used packages" 42 | apt -y autoremove 43 | 44 | echo "[-] Removing apt elastic file" 45 | rm -rf /etc/apt/sources.list.d/elastic-*.x.list 46 | 47 | echo "[*] Done. You can manually remove this directory as well if you like." 48 | echo "" 49 | --------------------------------------------------------------------------------