Merge branch 'develop' into dev_sec_ops_package

This commit is contained in:
P4T12ICK
2021-08-27 14:32:11 +02:00
26 changed files with 2209 additions and 10 deletions
+275
View File
@@ -0,0 +1,275 @@
#This file makes use of a number of useful, external Github Actions.
#Check the links below for additional documentation on each of these:
#https://github.com/actions/setup-python
#https://github.com/actions/setup-node
#https://github.com/actions/checkout
#https://github.com/actions/upload-artifact
#The mechanism for persisting data between jobs in a workflow is the same as for persisting it
#permanently:
#https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts
#In CircleCI, this was different (store_artifacts vs persist_to_workspace)
name: build-and-validate
on: [push, pull_request]
jobs:
validate-tag-if-present:
runs-on: ubuntu-latest
steps:
- name: TAGGED, Validate that the tag is in the correct format
run: |
echo "The GITHUB_REF: $GITHUB_REF"
#First check to see if the release is a tag
if [[ $GITHUB_REF =~ refs/tags/* ]]; then
#Yes, this is a tag, so we need to test to make sure that the tag
#is in the correct format (like v1.10.20)
if [[ $GITHUB_REF =~ refs/tags/v[0-9]+.[0-9]+.[0-9]+ ]]; then
echo "PASS: Tagged release with good format"
exit 0
else
echo "FAIL: Tagged release with bad format"
exit 1
fi
else
echo "PASS: Not a tagged release"
exit 0
fi
validate-content:
#Note that the CircleCI job used a Container. The way to do this with Github Actions
#is to first start up a Virtual Machine, then we can by following:
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idcontainer
runs-on: ubuntu-latest
needs: [validate-tag-if-present]
steps:
#Previous config chose which branch/tag to operate on.
#I think Github is smart enough to choose based on whether it's a pull request or push + other info?
- name: Check out the repository code
uses: actions/checkout@v2
#with:
# repository: splunk/security-content #check out https://github.com/mitre/cti.git, defaults to HEAD
# path: "security-content"
- uses: actions/setup-python@v2
with:
python-version: '3.9' #Available versions here - https://github.com/actions/python-versions/releases easy to change/make a matrix/use pypy
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
#TODO: CircleCI restore_cache equivalent
#don't need to install python3 or python3-dev since it was handled by the action above?
#Also, no support for YAML anchors/aliases in Github Actions...
- name: Install System Packages
run: |
sudo apt update -qq
sudo apt install jq -qq
#TODO: CircleCI save_cache equivalent
- name: Install Python Dependencies
run: |
#Get the virtualenv set up
rm -rf venv
python3 -m venv --clear venv
source venv/bin/activate
python3 -m pip install -q -r requirements.txt
- name: run validate
run: |
source venv/bin/activate
python3 contentctl.py --path . --verbose validate
- name: Get CTI Repo for Mitre context
uses: actions/checkout@v2
with:
repository: mitre/cti #check out https://github.com/mitre/cti.git, defaults to HEAD
path: "cti/"
#Now generate the documentation (uses Node)
- uses: actions/setup-node@v2
with:
node-version: '14' #can easily be changed to a different version
- name: Generate documentation
run: |
ls -lah
#Enter the virtualenv and run the docgen
source venv/bin/activate
python3 bin/doc_gen.py --path . --output docs -v
#Now generate the spec docs
npm install -g @adobe/jsonschema2md
jsonschema2md -d spec -o docs/spec -f yaml -e spec.json -x -
#Clean up extra properties on docs
rm -rf docs/spec/*-*.md
echo "****** BRANCH INFORMATION ******"
git branch
git branch --show-current
build-sources:
runs-on: ubuntu-latest
needs: validate-content
steps:
- name: Checkout Repo
uses: actions/checkout@v2
- name: Install System Packages
run: |
sudo apt update -qq
sudo apt install jq -qq
- name: Install Python Dependencies
run: |
#Get the virtualenv set up
rm -rf venv
python3 -m venv --clear venv
source venv/bin/activate
python3 -m pip install -q -r requirements.txt
- name: Run Generate
run: |
source venv/bin/activate
python3 contentctl.py --path . --verbose generate --product ESCU --output dist/escu
python3 contentctl.py --path . --verbose generate --product SAAWS --output dist/saaws
#make a copy of use_case_lib in order to have ES work :-(
cp dist/escu/default/use_case_library.conf dist/escu/default/analyticstories.conf
cp dist/saaws/default/use_case_library.conf dist/saaws/default/analyticstories.conf
- name: Copy lookups .csv files
run: |
# clean up current lookups
rm -rf dist/escu/lookups
rm -rf dist/saaws/lookups
mkdir dist/escu/lookups
mkdir dist/saaws/lookups
#copy over lookups
cd lookups
cp -rv *.csv ../dist/escu/lookups
cp -rv *.csv ../dist/saaws/lookups
#Tag is '' for non-tagged push and the tag name for a tagged release
- name: Set tag
id: vars
run: |
if [ echo ${GITHUB_REF} | grep "^refs/tags/*" ]; then
#failed to find the refs/tags/ beginning, grab and set the tag
echo "::set-output name=tag::${GITHUB_REF#refs/tags/}"
else
#Not a tagged relese
echo "::set-output name=tag::"
fi
- name: Update Version and Build number
run : |
# check if tag is set, get build number from the tag if set
if [ -z "${{ steps.vars.outputs.tag }}" ]; then
CONTENT_VERSION=$(grep -oP "(\d+.\d+.\d+$)" dist/escu/default/content-version.conf)
echo "detected content version: $CONTENT_VERSION"
else
CONTENT_VERSION=$(echo ${{ steps.vars.outputs.tag }} | grep -oP "\d+.\d+.\d+")
echo "content version: $CONTENT_VERSION, set by tag: ${{ steps.vars.outputs.tag }}"
fi
# update build number and version for ESCU
sed -i "s/build = .*$/build = ${{ github.run_number }}/g" dist/escu/default/app.conf
sed -i "s/^version = .*$/version = $CONTENT_VERSION/g" dist/escu/default/app.conf
sed -i "s/\"version\": .*$/\"version\": \"$CONTENT_VERSION\"/g" dist/escu/app.manifest
sed -i "s/version = .*$/version = $CONTENT_VERSION/g" dist/escu/default/content-version.conf
tar -czf content-pack-build-escu.tar.gz dist/escu/*
# update build number and version for saaws
sed -i "s/build = .*$/build = ${{ github.run_number }}/g" dist/saaws/default/app.conf
sed -i "s/^version = .*$/version = $CONTENT_VERSION/g" dist/saaws/default/app.conf
sed -i "s/\"version\": .*$/\"version\": \"$CONTENT_VERSION\"/g" dist/saaws/app.manifest
sed -i "s/version = .*$/version = $CONTENT_VERSION/g" dist/saaws/default/content-version.conf
tar -czf content-pack-build-saaws.tar.gz dist/saaws/*
- name: Persist to Workspace
uses: actions/upload-artifact@v2
with:
name: content-pack-build
path: |
content-pack-build-escu.tar.gz
content-pack-build-saaws.tar.gz
build-package:
runs-on: ubuntu-latest
needs: [validate-content, build-sources]
steps:
- uses: actions/download-artifact@v2
with:
name: content-pack-build
path: build/
#This explicitly uses a different version of python (2.7)
- uses: actions/setup-python@v2
with:
python-version: '2.7' #Available versions here - https://github.com/actions/python-versions/releases easy to change/make a matrix/use pypy
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Get virtualenv for Python 2.7
run: |
sudo apt install virtualenv
- name: Grab Splunk Packaging Toolkit
run : |
curl -Ls https://download.splunk.com/misc/packaging-toolkit/splunk-packaging-toolkit-0.9.0.tar.gz -o splunk-packaging-toolkit-latest.tar.gz
mkdir slim-latest
tar -zxf splunk-packaging-toolkit-latest.tar.gz -C slim-latest --strip-components=1
- name: Install Splunk Packaging Toolkit (slim)
run: |
cd slim-latest
virtualenv --python=/usr/bin/python2.7 --clear venv
source venv/bin/activate
python -m pip install semantic_version
python -m pip install .
- name: Create a .spl for this Build Using Slim
run: |
source slim-latest/venv/bin/activate
cd build
tar -zxf content-pack-build-escu.tar.gz
tar -zxf content-pack-build-saaws.tar.gz
mv dist/escu DA-ESS-ContentUpdate
mv dist/saaws DA-ESS_AmazonWebServices_Content
slim package -o upload DA-ESS-ContentUpdate
slim package -o upload DA-ESS_AmazonWebServices_Content
cp upload/DA-ESS-ContentUpdate-*.tar.gz DA-ESS-ContentUpdate-latest.tar.gz
sha256sum DA-ESS-ContentUpdate-latest.tar.gz > checksum.txt
cp upload/DA-ESS_AmazonWebServices_Content-*tar.gz DA-ESS_AmazonWebServices_Content-latest.tar.gz
sha256sum DA-ESS_AmazonWebServices_Content-latest.tar.gz >> checksum.txt
touch tag-canary.txt
- name: store_artifacts
uses: actions/upload-artifact@v2
with:
name: package
path: |
build/upload
- name: store_artifacts_two
uses: actions/upload-artifact@v2
with:
name: content-latest
path: |
build/DA-ESS-ContentUpdate-latest.tar.gz
build/DA-ESS_AmazonWebServices_Content-latest.tar.gz
build/checksum.txt
#Store the tag to indicate that this was a tagged build
- name: store_artifacts_three
uses: actions/upload-artifact@v2
with:
name: tag-canary
path: |
build/tag-canary.txt
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
environment: Detection-Testing-Approval
needs: [validate-tag-if-present]
#Only run when tagged
if: startsWith(github.ref, 'refs/tags/v')
if: startsWith(github.ref, 'refs/heads/')
steps:
- name: Checkout Repo
+398
View File
@@ -0,0 +1,398 @@
name: release-checks
on:
workflow_run:
workflows: ["validate-and-build"]
types:
- completed
jobs:
#Check that the validate-and-build workflow succeeded
check-validate-and-build-success:
runs-on: ubuntu-latest
steps:
- if: github.event.workflow_run.conclusion != 'success'
name: Abort if failed
run: |
echo "FAIL: validate-and-build.yml DID NOT run successfully. Terminating..."
exit 1
- name: Print Success
run: |
echo "SUCCESS: validate-and-build.yml ran successfully. Continue"
exit 0
#Enusre that we are running on a tag. There is no good way to see if this was
#triggered from a tag/release, so we use the creation of an aritifact in the
#validate-and-build workflow to represent it
verify-tag:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success]
steps:
- name: Try to get the canary
uses: dawidd6/action-download-artifact@v2
with:
github_token: "${{ secrets.GITHUB_TOKEN }}"
workflow: ${{ github.event.workflow_run.workflow_id }}
#workflow: validate-and-build.yml
#run_id: ${{ github.event.workflow_run.id }}
name: tag-canary
path: canary
- name: Check for existence of canary
run: |
#If this file does not exist, then cat will return a nonzero status (failure)
#and the entire workflow will fail
cat canary/tag-canary.txt
run-appinspect:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag]
#Only run when tagged
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
ref: 'develop'
#Download the artifacts we want to check
- name: Restore Content-Pack Artifacts for AppInspect testing
uses: dawidd6/action-download-artifact@v2
with:
workflow: validate-and-build.yml
workflow_conclusion: success
run_id: ${{ github.event.workflow_run.id }}
name: content-latest
path: build/
- name: Install System Packages
run: |
sudo apt update -qq
sudo apt install jq -qq
- name: Submit ESCU Package to AppInspect API
env:
APPINSPECT_USERNAME: ${{ secrets.AppInspectUsername }}
APPINSPECT_PASSWORD: ${{ secrets.AppInspectPassword }}
run: |
cd bin
#Enclose in quotes in case there are any special characters in the username/password
#Better not to pass these arguments on the command line, if possible
./appinspect.sh ../ DA-ESS-ContentUpdate-latest.tar.gz "$APPINSPECT_USERNAME" "$APPINSPECT_PASSWORD"
- name: Submit SAAWS Package to AppInspect API
env:
APPINSPECT_USERNAME: ${{ secrets.AppInspectUsername }}
APPINSPECT_PASSWORD: ${{ secrets.AppInspectPassword }}
run: |
cd bin
./appinspect.sh ../ DA-ESS_AmazonWebServices_Content-latest.tar.gz "$APPINSPECT_USERNAME" "$APPINSPECT_PASSWORD"
- name: Create report artifact
if: always()
run: |
#Always create this, regardless of whether success or failure above
tar -cvzf report.tar.gz report/
- name: store_artifacts
uses: actions/upload-artifact@v2
with:
name: appinspect_reports
path: |
report.tar.gz
#Still store the report, even if we have failed (otherwise we don't know why/how we failed)
- name: store_artifacts_on_failure
uses: actions/upload-artifact@v2
if: failure()
with:
name: appinspect_reports_failure
path: |
report.tar.gz
create-report:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag, run-appinspect]
#Only run when tagged
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
ref: 'develop'
- name: Install System Packages
run: |
sudo apt update -qq
sudo apt install jq -qq
- uses: actions/setup-python@v2
with:
python-version: '3.9' #Available versions here - https://github.com/actions/python-versions/releases easy to change/make a matrix/use pypy
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Install Python Dependencies
run: |
#Get the virtualenv set up
rm -rf venv
python3 -m venv --clear venv
source venv/bin/activate
python3 -m pip install -q -r requirements.txt
- name: run reporting
run: |
source venv/bin/activate
python3 bin/reporting.py
#Official, Verified Amazon-AWS Github Account Provided Action
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }} # if you have/need it
aws-region: us-west-1 #assume we will always use this, could make this an environment variable...
- name: Upload Reporting
run: |
aws s3 cp bin/reporting s3://security-content-testing/reporting --recursive --exclude "*" --include "*.svg"
update-sources-github:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag, run-appinspect, create-report]
#Only run when tagged
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
ref: 'develop'
- uses: actions/setup-python@v2
with:
python-version: '3.9' #Available versions here - https://github.com/actions/python-versions/releases easy to change/make a matrix/use pypy
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- uses: dawidd6/action-download-artifact@v2
with:
workflow: validate-and-build.yml
workflow_conclusion: success
run_id: ${{ github.event.workflow_run.id }}
path: .
name: content-latest
- name: Stage artifacts in proper directories
run: |
mkdir latest-escu
tar -zxf DA-ESS-ContentUpdate-latest.tar.gz -C latest-escu --strip-components=1
mkdir latest-saaws
tar -zxf DA-ESS_AmazonWebServices_Content-latest.tar.gz -C latest-saaws --strip-components=1
- name: Install Python Dependencies
run: |
#Get the virtualenv set up
rm -rf venv
python3 -m venv --clear venv
source venv/bin/activate
python3 -m pip install -q -r requirements.txt
- name: Get CTI Repo for Mitre context
uses: actions/checkout@v2
with:
repository: mitre/cti #check out https://github.com/mitre/cti.git, defaults to HEAD
path: "cti/"
- name: Get branch and PR required for detection testing main.py
id: vars
run: |
echo "::set-output name=branch::${GITHUB_REF#refs/heads/}"
- name: Run doc-gen
run: |
source venv/bin/activate
python3 bin/doc_gen.py --path . --output docs -v
- name: Make YAMLs Pretty
run: |
source venv/bin/activate
python3 bin/pretty_yaml.py --path . -v
- name: Run generate-actors-map
run: |
source venv/bin/activate
python3 bin/generate-actors-map.py --projects_path . --output docs/mitre-map/
- name: Run generate-coverage-map
run: |
source venv/bin/activate
python3 bin/generate-coverage-map.py --projects_path . --output docs/mitre-map
- name: Update github with new docs and package bits
run: |
rm -rf dist
mkdir dist
echo "Directory layout 3"
pwd
ls -lah
mv latest-escu dist/escu
mv latest-saaws dist/saaws
# configure git to prep for commit
#git config credential.helper 'cache --timeout=120'
git config user.email "research@splunk.com"
git config user.name "research bot"
git config --global push.default simple
git add dist/*
git add docs/*
git add detections/*
git commit --allow-empty -m "updating docs and package bits [ci skip]"
# Push quietly to prevent showing the token in log
#No need to provide any credentials
git push
publish-github-release:
#Github-maintained release action is in archived state: https://github.com/actions/create-release
#They recommend several and we use the following with the most stars: https://github.com/softprops/action-gh-release
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag, run-appinspect, create-report, update-sources-github]
#Only run when tagged
steps:
#Get the artifacts that we need
- uses: dawidd6/action-download-artifact@v2
with:
workflow: validate-and-build.yml
workflow_conclusion: success
run_id: ${{ github.event.workflow_run.id }}
path: .
name: content-latest
- uses: dawidd6/action-download-artifact@v2
with:
workflow: validate-and-build.yml
workflow_conclusion: success
run_id: ${{ github.event.workflow_run.id }}
path: .
name: appinspect_reports
#Rename those artifacts appropriately
- name: Set tag
id: vars
run: echo "::set-output name=tag::${GITHUB_REF#refs/*/}"
- name: Rename the content-update appropriately
run: |
cp DA-ESS-ContentUpdate-latest.tar.gz DA-ESS-ContentUpdate-${{ steps.vars.outputs.tag }}.tar.gz
cp DA-ESS_AmazonWebServices_Content-latest.tar.gz DA-ESS_AmazonWebServices_Content-${{ steps.vars.outputs.tag }}.tar.gz
#No checksum on the reports
cp report.tar.gz report-${{ steps.vars.outputs.tag }}.tar.gz
cp checksum.txt checksum-${{ steps.vars.outputs.tag }}.txt
#Upload all of the artifacts that we have created using the third party
#action recommended bu Github
- name: Upload Release Artifacts
uses: softprops/action-gh-release@v1
with:
files: |
DA-ESS-ContentUpdate-${{ steps.vars.outputs.tag }}.tar.gz
DA-ESS_AmazonWebServices_Content-${{ steps.vars.outputs.tag }}.tar.gz
report-${{ steps.vars.outputs.tag }}.tar.gz
checksum-${{ steps.vars.outputs.tag }}.txt
attack-range-update:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag, run-appinspect, create-report, update-sources-github, publish-github-release]
#Only run when tagged
steps:
- uses: dawidd6/action-download-artifact@v2
with:
workflow: validate-and-build.yml
workflow_conclusion: success
run_id: ${{ github.event.workflow_run.id }}
path: .
name: content-latest
#Official, Verified Amazon-AWS Github Account Provided Action
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }} # if you have/need it
aws-region: us-west-1 #assume we will always use this, could make this an environment variable...
- name: Sync latest ESCU to the Attack Range S3 bucket for apps
run: |
aws s3 cp DA-ESS-ContentUpdate-latest.tar.gz s3://attack-range-appbinaries-testing/
# make the file public since it is not by default
aws s3api put-object-acl --bucket attack-range-appbinaries-testing --key DA-ESS-ContentUpdate-latest.tar.gz --acl public-read
master-api-update:
runs-on: ubuntu-latest
needs: [check-validate-and-build-success, verify-tag, run-appinspect, create-report, update-sources-github, publish-github-release, attack-range-update]
#Only run when tagged
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
ref: 'develop'
- uses: actions/setup-python@v2
with:
python-version: '3.9' #Available versions here - https://github.com/actions/python-versions/releases easy to change/make a matrix/use pypy
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Install Python Dependencies
run: |
#Get the virtualenv set up
rm -rf venv
python3 -m venv --clear venv
source venv/bin/activate
python3 -m pip install -q -r requirements.txt
- name: Create Baseline Folder
run: |
source venv/bin/activate
python3 bin/create_baseline_folder.py
#Official, Verified Amazon-AWS Github Account Provided Action
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }} # if you have/need it
aws-region: us-west-1 #assume we will always use this, could make this an environment variable...
- name: Update API sources
run: |
aws s3 rm s3://security-content-testing --recursive --exclude "*" --include "*.yml"
aws s3 cp stories s3://security-content-testing/stories --recursive --exclude "*" --include "*.yml"
aws s3 cp baselines s3://security-content-testing/baselines --recursive --exclude "*" --include "*.yml"
aws s3 cp detections s3://security-content-testing/detections --recursive --exclude "*" --include "*.yml"
aws s3 cp response_tasks s3://security-content-testing/response_tasks --recursive --exclude "*" --include "*.yml"
aws s3 cp responses s3://security-content-testing/responses --recursive --exclude "*" --include "*.yml"
aws s3 cp lookups s3://security-content-testing/lookups --recursive --exclude "*" --include "*.yml"
aws s3 cp lookups s3://security-content-testing/lookups --recursive --exclude "*" --include "*.csv"
aws s3 cp macros s3://security-content-testing/macros --recursive --exclude "*" --include "*.yml"
aws s3 cp deployments s3://security-content-testing/deployments --recursive --exclude "*" --include "*.yml"
- name: Security Content API Smoke Test
run: |
API_URL='https://content.splunkresearch.com/detections'
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" $API_URL)
echo "Security Content API Status: $API_STATUS"
if [ "$API_STATUS" != "200" ]; then
echo "Error [Security Content API status: $API_STATUS]"
exit 1
fi
+6 -7
View File
@@ -41,16 +41,15 @@ jobs:
# Scan code using project's configuration on https://semgrep.dev/manage
- uses: returntocorp/semgrep-action@v1
with:
#The following line is commented out for now pending a fix to the semgrep repo
#generateSarif: "1"
generateSarif: "1"
config: >- # more at semgrep.dev/explore
p/security-audit
p/secrets
# Upload SARIF file generated in previous step
#The following lines are commented out right now pending a fix to the semgrep repo
# - name: Upload SARIF file
# uses: github/codeql-action/upload-sarif@v1
# with:
# sarif_file: semgrep.sarif
# if: always()
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: semgrep.sarif
if: always()
@@ -148,7 +148,7 @@ def main(args):
detection_obj['tags']['dataset'] = datasets
with open(file_path, 'w') as f:
yaml.dump(detection_obj, f, sort_keys=False)
yaml.dump(detection_obj, f, sort_keys=False, allow_unicode=True)
changed_file_path = 'detections/' + test['detection_result']['detection_file']
security_content_repo_obj.index.add([changed_file_path])
@@ -177,7 +177,7 @@ def main(args):
def load_file(file_path):
with open(file_path, 'r') as stream:
with open(file_path, 'r', encoding="utf-8") as stream:
try:
file = list(yaml.safe_load_all(stream))[0]
except yaml.YAMLError as exc:
@@ -19,6 +19,7 @@ certifi==2021.5.30
cffi==1.14.5
cfgv==3.3.0
chardet==4.0.0
colorama==0.4.4
configparser==5.0.2
contextlib2==0.6.0.post1
Deprecated==1.2.12
@@ -55,6 +56,7 @@ PyInquirer==1.0.3
PyJWT==2.1.0
PyNaCl==1.4.0
pyparsing==2.4.7
pyperclip==1.8.2
pytest==6.2.4
python-daemon==2.3.0
python-dateutil==2.8.1
@@ -0,0 +1,50 @@
name: Github Commit Changes In Master
id: c9d2bfe2-019f-11ec-a8eb-acde48001122
version: 1
date: '2021-08-20'
author: Teoderick Contreras, Splunk
type: Anomaly
datamodel: []
description: This search is to detect a pushed or commit to master or main branch.
This is to avoid unwanted modification to master without a review to the changes. Ideally in terms of devsecops the changes made in a branch and do a
PR for review. of course in some cases admin of the project may did a changes directly to master branch
search: '`github` branches{}.name = main OR branches{}.name = master
| stats count min(_time) as firstTime max(_time) as lastTime by commit.author.html_url commit.commit.author.email commit.author.login commit.commit.message repository.pushed_at commit.commit.committer.date
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `github_commit_changes_in_master_filter`'
how_to_implement: To successfully implement this search, you need to be ingesting
logs related to github logs having the fork, commit, push metadata that can be use
to monitor the changes in a github project.
known_false_positives: admin can do changes directly to master branch
references:
- https://www.redhat.com/en/topics/devops/what-is-devsecops
tags:
analytic_story:
- DevSecOps
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1199/github_push_master/github_push_master.log
kill_chain_phases:
- Exploitation
mitre_attack_id:
- T1199
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- _time
security_domain: endpoint
impact: 30
confidence: 30
risk_score: 9
context:
- Source:Endpoint
- Stage:Reconnaissance
message: suspicious commit by $commit.commit.author.email$ to main branch
observable:
- name: commit.commit.author.email
type: User
role:
- attacker
automated_detection_testing: passed
@@ -0,0 +1,68 @@
name: Gsuite Email Suspicious Subject With Attachment
id: 8ef3971e-00f2-11ec-b54f-acde48001122
version: 1
date: '2021-08-19'
author: Teoderick Contreras, Splunk
type: Anomaly
datamodel: []
description: This search is to detect a gsuite email contains suspicious subject having
known file type used in spear phishing. This technique is a common and effective
entry vector of attacker to compromise a network by luring the user to click or
execute the suspicious attachment send from external email account because of the
effective social engineering of subject related to delivery, bank and so on. On
the other hand this detection may catch a normal email traffic related to legitimate
transaction so better to check the email sender, spelling and etc. avoid click link
or opening the attachment if you are not expecting this type of e-mail.
search: '`gsuite_gmail` num_message_attachments > 0 subject IN ("*dhl*", "* ups *",
"*delivery*", "*parcel*", "*label*", "*invoice*", "*postal*", "* fedex *", "* usps
*", "* express *", "*shipment*", "*Banking/Tax*","*shipment*", "*new order*") attachment{}.file_extension_type
IN ("doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf", "zip", "rar", "html","htm","hta")
| rex field=source.from_header_address "[^@]+@(?<source_domain>[^@]+)" | rex field=destination{}.address
"[^@]+@(?<dest_domain>[^@]+)" | where not source_domain="internal_test_email.com"
and dest_domain="internal_test_email.com" | stats count min(_time) as firstTime
max(_time) as lastTime values(attachment{}.file_extension_type) as email_attachments,
values(attachment{}.sha256) as attachment_sha256, values(payload_size) as payload_size
by destination{}.service num_message_attachments subject destination{}.address
source.address | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
| `gsuite_email_suspicious_subject_with_attachment_filter`'
how_to_implement: To successfully implement this search, you need to be ingesting
logs related to gsuite having the file attachment metadata like file type, file
extension, source email, destination email, num of attachment and etc.
known_false_positives: normal user or normal transaction may contain the subject and
file type attachment that this detection try to search.
references:
- https://www.redhat.com/en/topics/devops/what-is-devsecops
- https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/rpt-top-spear-phishing-words.pdf
tags:
analytic_story:
- DevSecOps
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gsuite_susp_subj/gsuite_susp_subj_attach.log
kill_chain_phases:
- Exploitation
mitre_attack_id:
- T1566.001
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- _time
security_domain: endpoint
impact: 50
confidence: 50
risk_score: 25
context:
- Source:Endpoint
- Stage:Reconnaissance
message: suspicious email from $source.address$ to $destination{}.address$
observable:
- name: source.address
type: User
role:
- attacker
- name: destination{}.address
type: User
role:
- Victim
automated_detection_testing: passed
@@ -0,0 +1,58 @@
name: Gsuite Email With Known Abuse Web Service Link
id: 8630aa22-042b-11ec-af39-acde48001122
version: 1
date: '2021-08-23'
author: Teoderick Contreras, Splunk
type: Anomaly
datamodel: []
description: This analytics is to detect a gmail containing a link that are known
to be abused by malware or attacker like pastebin, telegram and discord to deliver
malicious payload. This event can encounter some normal email traffic within organization
and external email that normally using this application and services.
search: '`gsuite_gmail` "link_domain{}" IN ("*pastebin.com*", "*discord*", "*telegram*","t.me")
| rex field=source.from_header_address "[^@]+@(?<source_domain>[^@]+)" | rex field=destination{}.address
"[^@]+@(?<dest_domain>[^@]+)" | where not source_domain="internal_test_email.com"
and dest_domain="internal_test_email.com" |stats values(link_domain{}) as link_domains
min(_time) as firstTime max(_time) as lastTime count by is_spam source.address source.from_header_address
subject destination{}.address | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
| `gsuite_email_with_known_abuse_web_service_link_filter`'
how_to_implement: To successfully implement this search, you need to be ingesting
logs related to gsuite having the file attachment metadata like file type, file
extension, source email, destination email, num of attachment and etc.
known_false_positives: normal email contains this link that are known application
within the organization or network can be catched by this detection.
references:
- https://news.sophos.com/en-us/2021/07/22/malware-increasingly-targets-discord-for-abuse/
tags:
analytic_story:
- DevSecOps
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gsuite_susp_url/gsuite_susp_url.log
kill_chain_phases:
- Exploitation
mitre_attack_id:
- T1566.001
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- _time
security_domain: endpoint
impact: 50
confidence: 50
risk_score: 25
context:
- Source:Endpoint
- Stage:Reconnaissance
message: suspicious email from $source.address$ to $destination{}.address$
observable:
- name: source.address
type: User
role:
- attacker
- name: destination{}.address
type: User
role:
- Victim
automated_detection_testing: passed
@@ -0,0 +1,71 @@
name: Gsuite Suspicious Shared File Name
id: 07eed200-03f5-11ec-98fb-acde48001122
version: 1
date: '2021-08-23'
author: Teoderick Contreras, Splunk
type: Anomaly
datamodel: []
description: This search is to detect a shared file in google drive with suspicious
file name that are commonly used by spear phishing campaign. This technique is very
popular to lure the user by running a malicious document or click a malicious link
within the shared file that will redirected to malicious website. This detection
can also catch some normal email communication between organization and its external
customer.
search: '`gsuite_drive` parameters.owner_is_team_drive=false "parameters.doc_title"
IN ("*dhl*", "* ups *", "*delivery*", "*parcel*", "*label*", "*invoice*", "*postal*",
"*fedex*", "* usps *", "* express *", "*shipment*", "*Banking/Tax*","*shipment*",
"*new order*") parameters.doc_type IN ("document","pdf", "msexcel", "msword", "spreadsheet",
"presentation") | rex field=parameters.owner "[^@]+@(?<source_domain>[^@]+)" | rex
field=parameters.target_user "[^@]+@(?<dest_domain>[^@]+)" | where not source_domain="internal_test_email.com"
and dest_domain="internal_test_email.com" | stats count min(_time) as firstTime
max(_time) as lastTime by email parameters.owner parameters.target_user parameters.doc_title
parameters.doc_type | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
| `gsuite_suspicious_shared_file_name_filter`'
how_to_implement: To successfully implement this search, you need to be ingesting
logs related to gsuite having the file attachment metadata like file type, file
extension, source email, destination email, num of attachment and etc.
known_false_positives: normal user or normal transaction may contain the subject and
file type attachment that this detection try to search
references:
- https://www.redhat.com/en/topics/devops/what-is-devsecops
- https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/rpt-top-spear-phishing-words.pdf
tags:
analytic_story:
- DevSecOps
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gdrive_susp_file_share/gdrive_susp_attach.log
kill_chain_phases:
- Exploitation
mitre_attack_id:
- T1566.001
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- _time
- parameters.doc_title
- src_domain
- dest_domain
- email
- parameters.visibility
- parameters.owner
- parameters.doc_type
security_domain: endpoint
impact: 30
confidence: 30
risk_score: 9
context:
- Source:Endpoint
- Stage:Reconnaissance
message: suspicious share gdrive from $parameters.owner$ to $email$ namely as $parameters.doc_title$
observable:
- name: parameters.owner
type: User
role:
- attacker
- name: email
type: User
role:
- Victim
automated_detection_testing: passed
@@ -0,0 +1,55 @@
name: Kubernetes Nginx Ingress LFI
id: 0f83244b-425b-4528-83db-7a88c5f66e48
version: 1
date: '2021-08-20'
author: Patrick Bareiss, Splunk
type: TTP
datamodel: []
description: This search uses the Kubernetes logs from a nginx ingress controller
to detect local file inclusion attacks.
search: '`kubernetes_container_controller` | rex field=_raw "^(?<remote_addr>\S+)\s+-\s+-\s+\[(?<time_local>[^\]]*)\]\s\"(?<request>[^\"]*)\"\s(?<status>\S*)\s(?<body_bytes_sent>\S*)\s\"(?<http_referer>[^\"]*)\"\s\"(?<http_user_agent>[^\"]*)\"\s(?<request_length>\S*)\s(?<request_time>\S*)\s\[(?<proxy_upstream_name>[^\]]*)\]\s\[(?<proxy_alternative_upstream_name>[^\]]*)\]\s(?<upstream_addr>\S*)\s(?<upstream_response_length>\S*)\s(?<upstream_response_time>\S*)\s(?<upstream_status>\S*)\s(?<req_id>\S*)"
| lookup local_file_inclusion_paths local_file_inclusion_paths AS request OUTPUT
lfi_path | search lfi_path=yes | rename remote_addr AS src_ip, upstream_status as
status, proxy_upstream_name as proxy | rex field=request "^(?<http_method>\S+)\s(?<url>\S+)\s"
| stats count min(_time) as firstTime max(_time) as lastTime by src_ip, status,
url, http_method, host, http_user_agent, proxy | `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)` | `kubernetes_nginx_ingress_lfi_filter`'
how_to_implement: You must ingest Kubernetes logs through Splunk Connect for Kubernetes.
known_false_positives: unknown
references:
- https://github.com/splunk/splunk-connect-for-kubernetes
- https://www.offensive-security.com/metasploit-unleashed/file-inclusion-vulnerabilities/
tags:
analytic_story:
- Dev Sec Ops
asset_type: Kubernetes
cis20:
- CIS 13
confidence: 70
impact: 70
kill_chain_phases:
- Actions on Objectives
message: Local File Inclusion Attack detected on $host$
mitre_attack_id:
- T1212
nist:
- PR.DS
- PR.AC
- DE.CM
observable:
- name: src_ip
type: IP Address
role:
- Attacker
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- raw
risk_score: 49
security_domain: network
automated_detection_testing: passed
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1212/kubernetes_nginx_lfi_attack/kubernetes_nginx_lfi_attack.log
@@ -0,0 +1,54 @@
name: Kubernetes Nginx Ingress RFI
id: fc5531ae-62fd-4de6-9c36-b4afdae8ca95
version: 1
date: '2021-08-23'
author: Patrick Bareiss, Splunk
type: TTP
datamodel: []
description: This search uses the Kubernetes logs from a nginx ingress controller
to detect remote file inclusion attacks.
search: '`kubernetes_container_controller` | rex field=_raw "^(?<remote_addr>\S+)\s+-\s+-\s+\[(?<time_local>[^\]]*)\]\s\"(?<request>[^\"]*)\"\s(?<status>\S*)\s(?<body_bytes_sent>\S*)\s\"(?<http_referer>[^\"]*)\"\s\"(?<http_user_agent>[^\"]*)\"\s(?<request_length>\S*)\s(?<request_time>\S*)\s\[(?<proxy_upstream_name>[^\]]*)\]\s\[(?<proxy_alternative_upstream_name>[^\]]*)\]\s(?<upstream_addr>\S*)\s(?<upstream_response_length>\S*)\s(?<upstream_response_time>\S*)\s(?<upstream_status>\S*)\s(?<req_id>\S*)"
| rex field=request "^(?<http_method>\S+)?\s(?<url>\S+)\s" | rex field=url "(?<dest_ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
| search dest_ip=* | rename remote_addr AS src_ip, upstream_status as status, proxy_upstream_name
as proxy | stats count min(_time) as firstTime max(_time) as lastTime by src_ip,
dest_ip status, url, http_method, host, http_user_agent, proxy | `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)` | `kubernetes_nginx_ingress_rfi_filter`'
how_to_implement: You must ingest Kubernetes logs through Splunk Connect for Kubernetes.
known_false_positives: unknown
references:
- https://github.com/splunk/splunk-connect-for-kubernetes
- https://www.netsparker.com/blog/web-security/remote-file-inclusion-vulnerability/
tags:
analytic_story:
- Dev Sec Ops
asset_type: Kubernetes
cis20:
- CIS 13
confidence: 70
impact: 70
kill_chain_phases:
- Actions on Objectives
message: Remote File Inclusion Attack detected on $host$
mitre_attack_id:
- T1212
nist:
- PR.DS
- PR.AC
- DE.CM
observable:
- name: src_ip
type: IP Address
role:
- Attacker
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- raw
risk_score: 49
security_domain: network
automated_detection_testing: passed
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1212/kuberntest_nginx_rfi_attack/kubernetes_nginx_rfi_attack.log
@@ -0,0 +1,57 @@
name: Kubernetes Scanner Image Pulling
id: 4890cd6b-0112-4974-a272-c5c153aee551
version: 1
date: '2021-08-24'
author: Patrick Bareiss, Splunk
type: TTP
datamodel: []
description: This search uses the Kubernetes logs from Splunk Connect from Kubernetes
to detect Kubernetes Security Scanner.
search: '`kube_objects_events` object.message IN ("Pulling image *kube-hunter*", "Pulling
image *kube-bench*", "Pulling image *kube-recon*", "Pulling image *kube-recon*")
| rename object.* AS * | rename involvedObject.* AS * | rename source.host AS host
| stats min(_time) as firstTime max(_time) as lastTime count by host, name, namespace,
kind, reason, message | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
| `kubernetes_scanner_image_pulling_filter`'
how_to_implement: You must ingest Kubernetes logs through Splunk Connect for Kubernetes.
known_false_positives: unknown
references:
- https://github.com/splunk/splunk-connect-for-kubernetes
tags:
analytic_story:
- Dev Sec Ops
asset_type: Kubernetes
cis20:
- CIS 13
confidence: 70
impact: 70
kill_chain_phases:
- Actions on Objectives
message: Kubernetes Scanner image pulled on host $host$
mitre_attack_id:
- T1526
nist:
- PR.DS
- PR.AC
- DE.CM
observable:
- name: host
type: Entity
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
required_fields:
- object.message
- source.host
- object.involvedObject.name
- object.involvedObject.namespace
- object.involvedObject.kind
- object.message
- object.reason
risk_score: 49
security_domain: network
automated_detection_testing: passed
dataset:
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1526/kubernetes_kube_hunter/kubernetes_kube_hunter.json
@@ -80,3 +80,4 @@ tags:
- Processes.parent_process_id
risk_score: 90
security_domain: endpoint
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
description: A list of interesting files in a local file inclusion attack
filename: local_file_inclusion_paths.csv
name: local_file_inclusion_paths
default_match: 'false'
match_type: WILDCARD(local_file_inclusion_paths)
min_matches: 1
case_sensitive_match: 'false'
+4
View File
@@ -0,0 +1,4 @@
definition: sourcetype=aws:firehose:json
description: customer specific splunk configurations(eg- index, source, sourcetype).
Replace the macro definition with configurations for your Splunk Environmnent.
name: github
+4
View File
@@ -0,0 +1,4 @@
definition: sourcetype=kube:objects:events
description: customer specific splunk configurations(eg- index, source, sourcetype).
Replace the macro definition with configurations for your Splunk Environmnent.
name: kube_objects_events
@@ -0,0 +1,3 @@
definition: sourcetype=kube:container:controller
description: customer specific splunk configurations(eg- index, source, sourcetype) for Kubernetes data. Replace the macro definition with configurations for your Splunk Environmnent.
name: kubernetes_container_controller
@@ -0,0 +1,12 @@
name: Github Commit Changes In Master Unit Test
tests:
- name: Github Commit Changes In Master
file: cloud/github_commit_changes_in_master.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-30d'
latest_time: 'now'
attack_data:
- file_name: github_push_master.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1199/github_push_master/github_push_master.log
source: github
sourcetype: aws:firehose:json
@@ -0,0 +1,12 @@
name: Gsuite Email Suspicious Subject With Attachment Unit Test
tests:
- name: Gsuite Email Suspicious Subject With Attachment
file: cloud/gsuite_email_suspicious_subject_with_attachment.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-24h'
latest_time: 'now'
attack_data:
- file_name: gsuite_susp_subj_attach.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gsuite_susp_subj/gsuite_susp_subj_attach.log
source: http:gsuite
sourcetype: gsuite:gmail:bigquery
@@ -0,0 +1,12 @@
name: Gsuite Email With Known Abuse Web Service Link Unit Test
tests:
- name: Gsuite Email With Known Abuse Web Service Link
file: cloud/gsuite_email_with_known_abuse_web_service_link.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-24h'
latest_time: 'now'
attack_data:
- file_name: gsuite_susp_url.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gsuite_susp_url/gsuite_susp_url.log
source: http:gsuite
sourcetype: gsuite:gmail:bigquery
@@ -0,0 +1,12 @@
name: Gsuite Suspicious Shared File Name Unit Test
tests:
- name: Gsuite Suspicious Shared File Name
file: cloud/gsuite_suspicious_shared_file_name.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-24h'
latest_time: 'now'
attack_data:
- file_name: gdrive_susp_attach.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/gdrive_susp_file_share/gdrive_susp_attach.log
source: http:gsuite
sourcetype: gsuite:drive:json
@@ -0,0 +1,12 @@
name: Kubernetes Nginx Ingress LFI Unit Test
tests:
- name: Kubernetes Nginx Ingress LFI
file: cloud/kubernetes_nginx_ingress_lfi.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-365d'
latest_time: 'now'
attack_data:
- file_name: kubernetes_nginx_lfi_attack.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1212/kubernetes_nginx_lfi_attack/kubernetes_nginx_lfi_attack.log
sourcetype: kube:container:controller
source: kubernetes
@@ -0,0 +1,12 @@
name: Kubernetes Nginx Ingress RFI Unit Test
tests:
- name: Kubernetes Nginx Ingress RFI
file: cloud/kubernetes_nginx_ingress_rfi.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-365d'
latest_time: 'now'
attack_data:
- file_name: kubernetes_nginx_rfi_attack.log
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1212/kuberntest_nginx_rfi_attack/kubernetes_nginx_rfi_attack.log
sourcetype: kube:container:controller
source: kubernetes
@@ -0,0 +1,12 @@
name: Kubernetes Scanner Image Pulling Unit Test
tests:
- name: Kubernetes Scanner Image Pulling
file: cloud/kubernetes_scanner_image_pulling.yml
pass_condition: '| stats count | where count > 0'
earliest_time: '-7d'
latest_time: 'now'
attack_data:
- file_name: kubernetes_kube_hunter.json
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1526/kubernetes_kube_hunter/kubernetes_kube_hunter.json
sourcetype: kube:objects:events
source: kubernetes