mirror of
https://github.com/splunk/security_content
synced 2026-06-08 17:32:49 +00:00
Merge branch 'develop' of github.com:splunk/security-content into tf23
This commit is contained in:
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
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
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
#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
|
||||
exit 0
|
||||
else
|
||||
echo "FAIL: Tagged release with bad format"
|
||||
exit 1
|
||||
@@ -49,14 +49,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-tag-if-present]
|
||||
steps:
|
||||
#Previous config chose which branch/tag to operate on.
|
||||
#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
|
||||
- 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:
|
||||
@@ -66,14 +66,14 @@ jobs:
|
||||
|
||||
#TODO: CircleCI restore_cache equivalent
|
||||
|
||||
#don't need to install python3 or python3-dev since it was handled by the action above?
|
||||
#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: |
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install jq -qq
|
||||
#TODO: CircleCI save_cache equivalent
|
||||
|
||||
sudo apt install jq -qq
|
||||
#TODO: CircleCI save_cache equivalent
|
||||
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
#Get the virtualenv set up
|
||||
@@ -83,19 +83,19 @@ jobs:
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install wheel
|
||||
python3 -m pip install -q -r requirements.txt
|
||||
|
||||
|
||||
- name: run validate
|
||||
run: |
|
||||
|
||||
- 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
|
||||
- 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
|
||||
@@ -108,18 +108,18 @@ jobs:
|
||||
#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
|
||||
@@ -128,10 +128,10 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install System Packages
|
||||
run: |
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install jq -qq
|
||||
|
||||
sudo apt install jq -qq
|
||||
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
#Get the virtualenv set up
|
||||
@@ -143,18 +143,15 @@ jobs:
|
||||
python3 -m pip install -q -r requirements.txt
|
||||
|
||||
- name: Run Generate
|
||||
run: |
|
||||
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
|
||||
python3 contentctl.py --path . --verbose generate --product DevSecOps --output dist/devsecops
|
||||
# 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
|
||||
# cp dist/devsecops/default/use_case_library.conf dist/devsecops/default/analyticstories.conf
|
||||
python3 contentctl.py --path . --verbose generate --product SSA --output dist/ssa
|
||||
|
||||
- name: Copy lookups .csv files
|
||||
run: |
|
||||
run: |
|
||||
# clean up current lookups
|
||||
rm -rf dist/escu/lookups
|
||||
rm -rf dist/saaws/lookups
|
||||
@@ -167,7 +164,7 @@ jobs:
|
||||
cp -rv *.csv ../dist/escu/lookups
|
||||
cp -rv *.csv ../dist/saaws/lookups
|
||||
cp -rv *.csv ../dist/devsecops/lookups
|
||||
|
||||
|
||||
#Tag is '' for non-tagged push and the tag name for a tagged release
|
||||
- name: Set tag
|
||||
id: vars
|
||||
@@ -198,7 +195,7 @@ jobs:
|
||||
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
|
||||
@@ -209,6 +206,9 @@ jobs:
|
||||
# update build number and version for devsecops
|
||||
tar -czf content-pack-build-devsecops.tar.gz dist/devsecops/*
|
||||
|
||||
# update build number and version for ssa
|
||||
tar -czf content-pack-build-ssa.tar.gz dist/ssa/*
|
||||
|
||||
- name: Persist to Workspace
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
@@ -217,12 +217,13 @@ jobs:
|
||||
content-pack-build-escu.tar.gz
|
||||
content-pack-build-saaws.tar.gz
|
||||
content-pack-build-devsecops.tar.gz
|
||||
|
||||
content-pack-build-ssa.tar.gz
|
||||
|
||||
|
||||
build-package:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-content, build-sources]
|
||||
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -234,12 +235,12 @@ jobs:
|
||||
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
|
||||
sudo apt install virtualenv
|
||||
|
||||
- name: Grab Splunk Packaging Toolkit
|
||||
- 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
|
||||
@@ -264,6 +265,7 @@ jobs:
|
||||
mv dist/escu DA-ESS-ContentUpdate
|
||||
mv dist/saaws DA-ESS_AmazonWebServices_Content
|
||||
mv dist/devsecops dev_sec_ops_analytics
|
||||
|
||||
slim package -o upload DA-ESS-ContentUpdate
|
||||
slim package -o upload DA-ESS_AmazonWebServices_Content
|
||||
slim package -o upload dev_sec_ops_analytics
|
||||
@@ -276,6 +278,9 @@ jobs:
|
||||
|
||||
cp upload/dev_sec_ops_analytics-*tar.gz dev_sec_ops_analytics-latest.tar.gz
|
||||
|
||||
cp content-pack-build-ssa.tar.gz upload/SSA_Content-latest.tar.gz
|
||||
sha256sum upload/SSA_Content-latest.tar.gz >> checksum.txt
|
||||
|
||||
touch tag-canary.txt
|
||||
|
||||
- name: store_artifacts
|
||||
@@ -292,8 +297,9 @@ jobs:
|
||||
build/DA-ESS-ContentUpdate-latest.tar.gz
|
||||
build/DA-ESS_AmazonWebServices_Content-latest.tar.gz
|
||||
build/dev_sec_ops_analytics-latest.tar.gz
|
||||
build/SSA_Content-latest.tar.gz
|
||||
build/checksum.txt
|
||||
|
||||
|
||||
|
||||
#Everything below this line should ONLY run on a tag and nothing else
|
||||
#We still want all of the above checks to run and pass before running these
|
||||
@@ -301,7 +307,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-content, build-sources, build-package]
|
||||
#Only run when tagged
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
|
||||
- name: Checkout Repo
|
||||
@@ -319,10 +325,10 @@ jobs:
|
||||
|
||||
|
||||
- name: Install System Packages
|
||||
run: |
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt install jq -qq
|
||||
|
||||
|
||||
|
||||
|
||||
- name: Submit ESCU Package to AppInspect API
|
||||
@@ -333,8 +339,8 @@ jobs:
|
||||
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"
|
||||
|
||||
./appinspect.sh ../ DA-ESS-ContentUpdate-latest.tar.gz "$APPINSPECT_USERNAME" "$APPINSPECT_PASSWORD"
|
||||
|
||||
- name: Submit SAAWS Package to AppInspect API
|
||||
env:
|
||||
APPINSPECT_USERNAME: ${{ secrets.AppInspectUsername }}
|
||||
@@ -342,20 +348,20 @@ jobs:
|
||||
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
|
||||
- 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
|
||||
@@ -364,7 +370,7 @@ jobs:
|
||||
name: appinspect_reports_failure
|
||||
path: |
|
||||
report.tar.gz
|
||||
|
||||
|
||||
create-report:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-content, build-sources, build-package, run-appinspect]
|
||||
@@ -375,13 +381,13 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: 'develop'
|
||||
|
||||
|
||||
|
||||
|
||||
- name: Install System Packages
|
||||
run: |
|
||||
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
|
||||
@@ -396,12 +402,12 @@ jobs:
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install wheel
|
||||
python3 -m pip install -q -r requirements.txt
|
||||
|
||||
|
||||
- name: run reporting
|
||||
run: |
|
||||
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:
|
||||
@@ -410,23 +416,23 @@ jobs:
|
||||
# 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
|
||||
- name: Upload Reporting
|
||||
run: |
|
||||
aws s3 cp bin/reporting s3://security-content/reporting --recursive --exclude "*" --include "*.svg"
|
||||
|
||||
|
||||
update-sources-github:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-content, build-sources, build-package, run-appinspect, create-report]
|
||||
#Only run when tagged
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
steps:
|
||||
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.PROTECTED_BRANCH_PUSH_TOKEN }}
|
||||
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
|
||||
@@ -443,6 +449,8 @@ jobs:
|
||||
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
|
||||
mkdir latest-ssa
|
||||
tar -zxf SSA_Content-latest.tar.gz -C latest-ssa --strip-components=1
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
#Get the virtualenv set up
|
||||
@@ -452,9 +460,9 @@ jobs:
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install wheel
|
||||
python3 -m pip install -q -r requirements.txt
|
||||
|
||||
- name: Get CTI Repo for Mitre context
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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/"
|
||||
@@ -463,33 +471,30 @@ jobs:
|
||||
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
|
||||
|
||||
- name: Run doc-gen
|
||||
run: |
|
||||
source venv/bin/activate
|
||||
python3 bin/pretty_yaml.py --path . -v
|
||||
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-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
|
||||
mv latest-ssa dist/ssa
|
||||
# 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
|
||||
@@ -500,7 +505,7 @@ jobs:
|
||||
# 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
|
||||
@@ -510,7 +515,7 @@ jobs:
|
||||
#Only run when tagged
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
|
||||
|
||||
#Get the artifacts that we need
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -520,23 +525,24 @@ jobs:
|
||||
with:
|
||||
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
|
||||
- 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
|
||||
|
||||
cp SSA_Content-latest.tar.gz SSA_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
|
||||
@@ -545,18 +551,19 @@ jobs:
|
||||
files: |
|
||||
DA-ESS-ContentUpdate-${{ steps.vars.outputs.tag }}.tar.gz
|
||||
DA-ESS_AmazonWebServices_Content-${{ steps.vars.outputs.tag }}.tar.gz
|
||||
SSA_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: [validate-content, build-sources, build-package, run-appinspect, create-report, update-sources-github, publish-github-release]
|
||||
#Only run when tagged
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
|
||||
steps:
|
||||
|
||||
#Get the artifacts that we need
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -569,20 +576,20 @@ jobs:
|
||||
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...
|
||||
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/
|
||||
# make the file public since it is not by default
|
||||
aws s3api put-object-acl --bucket attack-range-appbinaries --key DA-ESS-ContentUpdate-latest.tar.gz --acl public-read
|
||||
|
||||
|
||||
master-api-update:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-content, build-sources, build-package, run-appinspect, create-report, update-sources-github, publish-github-release, attack-range-update]
|
||||
#Only run when tagged
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -607,7 +614,7 @@ jobs:
|
||||
- name: Create Baseline Folder
|
||||
run: |
|
||||
source venv/bin/activate
|
||||
python3 bin/create_baseline_folder.py
|
||||
python3 bin/create_baseline_folder.py
|
||||
|
||||
#Official, Verified Amazon-AWS Github Account Provided Action
|
||||
- uses: aws-actions/configure-aws-credentials@v1
|
||||
@@ -615,7 +622,7 @@ jobs:
|
||||
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...
|
||||
aws-region: us-west-1 #assume we will always use this, could make this an environment variable...
|
||||
|
||||
- name: Update API sources
|
||||
run: |
|
||||
@@ -623,8 +630,7 @@ jobs:
|
||||
aws s3 cp stories s3://security-content/stories --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp baselines s3://security-content/baselines --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp detections s3://security-content/detections --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp response_tasks s3://security-content/response_tasks --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp responses s3://security-content/responses --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp playbooks s3://security-content/playbooks --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp lookups s3://security-content/lookups --recursive --exclude "*" --include "*.yml"
|
||||
aws s3 cp lookups s3://security-content/lookups --recursive --exclude "*" --include "*.csv"
|
||||
aws s3 cp macros s3://security-content/macros --recursive --exclude "*" --include "*.yml"
|
||||
@@ -638,5 +644,3 @@ jobs:
|
||||
echo "Error [Security Content API status: $API_STATUS]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
#Get the virtualenv set up
|
||||
cd automated_detection_testing/ci/python_ci_code
|
||||
cd bin/automated_detection_testing/ci/python_ci_code
|
||||
rm -rf venv
|
||||
python3 -m venv --clear venv
|
||||
source venv/bin/activate
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
- name: Run Detection testing
|
||||
timeout-minutes: 120
|
||||
run: |
|
||||
cd automated_detection_testing/ci/python_ci_code
|
||||
cd bin/automated_detection_testing/ci/python_ci_code
|
||||
source venv/bin/activate
|
||||
|
||||
echo "github.event.issue.pull_request : [${{ github.event.issue.pull_request }}]"
|
||||
|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
+14
-14
@@ -1,4 +1,4 @@
|
||||
ansible==3.4.0
|
||||
ansible==4.7.0
|
||||
ansible-runner==2.0.2
|
||||
apipkg==1.5
|
||||
aspy.yaml==1.3.0
|
||||
@@ -7,31 +7,31 @@ attackcti==0.3.4.3
|
||||
attrs==21.2.0
|
||||
azure-common==1.1.27
|
||||
azure-core==1.18.0
|
||||
azure-mgmt-compute==23.0.0
|
||||
azure-identity==1.6.1
|
||||
azure-mgmt-compute==20.0.0
|
||||
azure-mgmt-core==1.2.1
|
||||
azure-mgmt-network==19.0.0
|
||||
azure-mgmt-resource==17.0.0
|
||||
bcrypt==3.2.0
|
||||
boto3==1.18.38
|
||||
botocore==1.20.105
|
||||
botocore==1.22.5
|
||||
certifi==2021.5.30
|
||||
cffi==1.14.5
|
||||
cffi==1.15.0
|
||||
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
|
||||
Deprecated==1.2.13
|
||||
dnspython==2.1.0
|
||||
docutils==0.17.1
|
||||
docutils==0.18
|
||||
execnet==1.9.0
|
||||
gitdb==4.0.5
|
||||
GitPython==3.1.18
|
||||
GitPython==3.1.24
|
||||
identify==2.2.10
|
||||
idna==2.8
|
||||
idna==3.3
|
||||
importlib-metadata==4.0.1
|
||||
Jinja2==3.0.0
|
||||
Jinja2==3.0.2
|
||||
jmespath==0.10.0
|
||||
lockfile==0.12.2
|
||||
MarkupSafe==2.0.1
|
||||
@@ -57,15 +57,15 @@ PyJWT==2.1.0
|
||||
PyNaCl==1.4.0
|
||||
pyparsing==2.4.7
|
||||
pyperclip==1.8.2
|
||||
pytest==6.2.4
|
||||
pytest==6.2.5
|
||||
python-daemon==2.3.0
|
||||
python-dateutil==2.8.1
|
||||
python-terraform==0.10.1
|
||||
pywinrm==0.4.2
|
||||
PyYAML==5.4.1
|
||||
PyYAML==6.0
|
||||
requests==2.25.1
|
||||
requests-ntlm==1.1.0
|
||||
s3transfer==0.4.2
|
||||
s3transfer==0.5.0
|
||||
six==1.16.0
|
||||
smmap==3.0.5
|
||||
splunk-sdk==1.6.16
|
||||
@@ -73,10 +73,10 @@ tabulate==0.8.9
|
||||
termcolor==1.1.0
|
||||
toml==0.10.2
|
||||
urllib3<1.26.8
|
||||
virtualenv==20.4.6
|
||||
virtualenv==20.9.0
|
||||
wcwidth==0.2.5
|
||||
wget==3.2
|
||||
wrapt==1.12.1
|
||||
wrapt==1.13.1
|
||||
xmltodict==0.12.0
|
||||
zipp==3.4.1
|
||||
|
||||
+24
-46
@@ -3,7 +3,7 @@ import yaml
|
||||
import argparse
|
||||
import sys
|
||||
import re
|
||||
from os import path, walk
|
||||
from os import path, walk, remove
|
||||
import json
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
import datetime
|
||||
@@ -172,7 +172,7 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
if t not in tactics:
|
||||
tactics.append(t)
|
||||
|
||||
template = j2_env.get_template('doc_navigation_markdown.j2')
|
||||
template = j2_env.get_template('doc_navigation.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/_data/navigation.yml')
|
||||
output = template.render(tactics=sorted(tactics), datamodels=sorted(datamodels), categories=sorted(category_names))
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
@@ -181,7 +181,7 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
|
||||
# write navigation _pages
|
||||
# for datamodels
|
||||
template = j2_env.get_template('doc_navigation_pages_markdown.j2')
|
||||
template = j2_env.get_template('doc_navigation_pages.j2')
|
||||
for datamodel in sorted(datamodels):
|
||||
output_path = path.join(OUTPUT_DIR + '/_pages/' + datamodel.lower().replace(" ", "_") + ".md")
|
||||
output = template.render(tag=datamodel)
|
||||
@@ -197,7 +197,7 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
messages.append("doc_gen.py wrote _page for: {1} structure to: {0}".format(output_path, tactic))
|
||||
|
||||
# for story categories
|
||||
template = j2_env.get_template('doc_navigation_story_pages_markdown.j2')
|
||||
template = j2_env.get_template('doc_navigation_story_pages.j2')
|
||||
for category in categories:
|
||||
output_path = path.join(OUTPUT_DIR + '/_pages/' + category['name'].lower().replace(" ", "_") + ".md")
|
||||
output = template.render(category=category)
|
||||
@@ -206,7 +206,7 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
messages.append("doc_gen.py wrote _page for: {0} structure to: {1}".format(category['name'], output_path))
|
||||
|
||||
# write stories listing markdown
|
||||
template = j2_env.get_template('doc_story_page_markdown.j2')
|
||||
template = j2_env.get_template('doc_story_page.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/_pages/stories.md')
|
||||
output = template.render(stories=sorted_stories)
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
@@ -214,7 +214,7 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
messages.append("doc_gen.py wrote _pages for story to: {0}".format(output_path))
|
||||
|
||||
# write stories markdown
|
||||
template = j2_env.get_template('doc_stories_markdown.j2')
|
||||
template = j2_env.get_template('doc_stories.j2')
|
||||
for story in sorted_stories:
|
||||
file_name = story['name'].lower().replace(" ","_") + '.md'
|
||||
output_path = path.join(OUTPUT_DIR + '/_stories/' + file_name)
|
||||
@@ -223,14 +223,6 @@ def generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, sorted_de
|
||||
f.write(output)
|
||||
messages.append("doc_gen.py wrote {0} story documentation in markdown to: {1}".format(len(sorted_stories),OUTPUT_DIR + '/_stories/'))
|
||||
|
||||
# write wikimarkup
|
||||
template = j2_env.get_template('doc_stories_wiki.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/stories.wiki')
|
||||
output = template.render(categories=categories, time=datetime.datetime.now())
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
f.write(output)
|
||||
messages.append("doc_gen.py wrote {0} stories documentation in mediawiki to: {1}".format(len(stories),output_path))
|
||||
|
||||
return sorted_stories, messages
|
||||
|
||||
|
||||
@@ -293,7 +285,7 @@ def generate_doc_detections(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, messag
|
||||
trim_blocks=False, autoescape=True)
|
||||
|
||||
# write markdown
|
||||
template = j2_env.get_template('doc_detections_markdown.j2')
|
||||
template = j2_env.get_template('doc_detections.j2')
|
||||
for detection in sorted_detections:
|
||||
file_name = detection['date'] + "-" + detection['name'].lower().replace(" ","_") + '.md'
|
||||
output_path = path.join(OUTPUT_DIR + '/_posts/' + file_name)
|
||||
@@ -303,38 +295,13 @@ def generate_doc_detections(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, attack, messag
|
||||
messages.append("doc_gen.py wrote {0} detections documentation in markdown to: {1}".format(len(sorted_detections),OUTPUT_DIR + '/_posts/'))
|
||||
|
||||
# write markdown detection page
|
||||
template = j2_env.get_template('doc_detection_page_markdown.j2')
|
||||
template = j2_env.get_template('doc_detection_page.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/_pages/detections.md')
|
||||
output = template.render(detections=sorted_detections, time=datetime.datetime.now())
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
f.write(output)
|
||||
messages.append("doc_gen.py wrote detections.md page to: {0}".format(output_path))
|
||||
|
||||
#sort detections by kind into categories
|
||||
kinds = []
|
||||
kind_names = set()
|
||||
for detection in sorted_detections:
|
||||
kind_names.add(detection['kind'])
|
||||
|
||||
for kind_name in sorted(kind_names):
|
||||
new_kind = {}
|
||||
new_kind['name'] = kind_name
|
||||
new_kind['detections'] = []
|
||||
kinds.append(new_kind)
|
||||
|
||||
for detection in sorted_detections:
|
||||
for kind in kinds:
|
||||
if kind['name'] == detection['kind']:
|
||||
kind['detections'].append(detection)
|
||||
|
||||
# write wikimarkup
|
||||
template = j2_env.get_template('doc_detections_wiki.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/detections.wiki')
|
||||
output = template.render(kinds=kinds, time=datetime.datetime.now())
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
f.write(output)
|
||||
messages.append("doc_gen.py wrote {0} detections documentation in mediawiki to: {1}".format(len(detections),output_path))
|
||||
|
||||
return sorted_detections, messages
|
||||
|
||||
def generate_doc_playbooks(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, sorted_detections, messages, VERBOSE):
|
||||
@@ -366,7 +333,7 @@ def generate_doc_playbooks(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, sorted_detectio
|
||||
trim_blocks=False, autoescape=True)
|
||||
|
||||
# write markdown
|
||||
template = j2_env.get_template('doc_playbooks_markdown.j2')
|
||||
template = j2_env.get_template('doc_playbooks.j2')
|
||||
for playbook in sorted_playbooks:
|
||||
file_name = playbook['name'].lower().replace(" ","_") + '.md'
|
||||
output_path = path.join(OUTPUT_DIR + '/_playbooks/' + file_name)
|
||||
@@ -376,7 +343,7 @@ def generate_doc_playbooks(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, sorted_detectio
|
||||
messages.append("doc_gen.py wrote {0} playbook documentation in markdown to: {1}".format(len(sorted_playbooks),OUTPUT_DIR + '/_playbooks/'))
|
||||
|
||||
# write markdown detection page
|
||||
template = j2_env.get_template('doc_playbooks_page_markdown.j2')
|
||||
template = j2_env.get_template('doc_playbooks_page.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/_pages/playbooks.md')
|
||||
output = template.render(playbooks=sorted_playbooks, detections=sorted_detections, time=datetime.datetime.now())
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
@@ -392,7 +359,7 @@ def generate_doc_index(OUTPUT_DIR, TEMPLATE_PATH, sorted_detections, sorted_stor
|
||||
trim_blocks=False, autoescape=True)
|
||||
|
||||
# write index updated metrics
|
||||
template = j2_env.get_template('doc_index_markdown.j2')
|
||||
template = j2_env.get_template('doc_index.j2')
|
||||
output_path = path.join(OUTPUT_DIR + '/index.markdown')
|
||||
output = template.render(detection_count=len(sorted_detections), story_count=len(sorted_stories), playbook_count=len(sorted_playbooks))
|
||||
with open(output_path, 'w', encoding="utf-8") as f:
|
||||
@@ -405,7 +372,7 @@ if __name__ == "__main__":
|
||||
|
||||
# grab arguments
|
||||
parser = argparse.ArgumentParser(description="Generates documentation from Splunk Security Content", epilog="""
|
||||
This tool converts all Splunk Security Content detections, stories, workbooks and spec files into documentation. It builds both wiki markup (Splunk Docs) an markdown documentation.""")
|
||||
This generates documention in the form of jekyll site research.splunk.com from Splunk Security Content yamls. """)
|
||||
parser.add_argument("-p", "--path", required=True, help="path to security_content repo")
|
||||
parser.add_argument("-o", "--output", required=True, help="path to the output directory for the docs")
|
||||
parser.add_argument("-v", "--verbose", required=False, default=False, action='store_true', help="prints verbose output")
|
||||
@@ -417,13 +384,24 @@ if __name__ == "__main__":
|
||||
OUTPUT_DIR = args.output
|
||||
VERBOSE = args.verbose
|
||||
|
||||
|
||||
TEMPLATE_PATH = path.join(REPO_PATH, 'bin/jinja2_templates')
|
||||
|
||||
if VERBOSE:
|
||||
print("getting mitre enrichment data from cti")
|
||||
techniques = get_all_techniques(REPO_PATH)
|
||||
|
||||
if VERBOSE:
|
||||
print("wiping the {0}/_posts/* folder".format(OUTPUT_DIR))
|
||||
|
||||
try:
|
||||
for root, dirs, files in walk(OUTPUT_DIR + '/_posts/'):
|
||||
for file in files:
|
||||
if file.endswith(".md"):
|
||||
remove(OUTPUT_DIR + '/_posts/' + file)
|
||||
except OSError as e:
|
||||
print("error: %s : %s" % (file, e.strerror))
|
||||
sys.exit(1)
|
||||
|
||||
messages = []
|
||||
sorted_detections, messages = generate_doc_detections(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, techniques, messages, VERBOSE)
|
||||
sorted_stories, messages = generate_doc_stories(REPO_PATH, OUTPUT_DIR, TEMPLATE_PATH, techniques, sorted_detections, messages, VERBOSE)
|
||||
|
||||
+60
-46
@@ -92,6 +92,29 @@ def generate_collections_conf(lookups, TEMPLATE_PATH, OUTPUT_PATH):
|
||||
|
||||
return output_path
|
||||
|
||||
def generate_ssa_yaml(detections, TEMPLATE_PATH, OUTPUT_PATH):
|
||||
'''
|
||||
@param detections: input list of individual YAML detections in detections/ directory
|
||||
@return: the enhanced yaml file located in /detections directory
|
||||
'''
|
||||
|
||||
# disable yaml pointers https://stackoverflow.com/questions/51272814/python-yaml-dumping-pointer-references
|
||||
yaml.Dumper.ignore_aliases = lambda *args : True
|
||||
|
||||
for d in detections:
|
||||
manifest_file = OUTPUT_PATH + '/detections/' + d['name'].lower().replace(" ", "_") + '.yml'
|
||||
|
||||
# remove unused fields
|
||||
del d['risk']
|
||||
del d['deployment']
|
||||
del d['mappings']
|
||||
del d['savedsearch_annotations']
|
||||
|
||||
with open(manifest_file, 'w') as file:
|
||||
documents = yaml.dump(d, file, sort_keys=True)
|
||||
|
||||
return OUTPUT_PATH + '/detections/'
|
||||
|
||||
def generate_savedsearches_conf(detections, deployments, TEMPLATE_PATH, OUTPUT_PATH):
|
||||
'''
|
||||
@param detections: input list of individual YAML detections in detections/ directory
|
||||
@@ -113,19 +136,6 @@ def generate_savedsearches_conf(detections, deployments, TEMPLATE_PATH, OUTPUT_P
|
||||
|
||||
return output_path
|
||||
|
||||
# def generate_analytic_story_conf(stories, detections, TEMPLATE_PATH, OUTPUT_PATH):
|
||||
# utc_time = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
|
||||
|
||||
# j2_env = Environment(loader=FileSystemLoader(TEMPLATE_PATH), # nosemgrep
|
||||
# trim_blocks=True)
|
||||
# template = j2_env.get_template('analytic_stories.j2')
|
||||
# output_path = path.join(OUTPUT_PATH, 'default/analytic_stories.conf')
|
||||
# output = template.render(stories=stories, time=utc_time)
|
||||
# with open(output_path, 'w', encoding="utf-8") as f:
|
||||
# f.write(output)
|
||||
|
||||
# return output_path
|
||||
|
||||
def generate_use_case_library_conf(stories, detections, TEMPLATE_PATH, OUTPUT_PATH):
|
||||
utc_time = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
|
||||
|
||||
@@ -245,7 +255,6 @@ def get_deployments(object, deployments):
|
||||
|
||||
for tag_value_deployment in tag_array_deployment:
|
||||
if tag_value == tag_value_deployment:
|
||||
# print("tag value: {}, matched deployment tag: {} on deployment: {}".format(tag_value,tag_value_deployment, deployment))
|
||||
matched_deployments.append(deployment)
|
||||
continue
|
||||
|
||||
@@ -257,9 +266,7 @@ def get_deployments(object, deployments):
|
||||
last_deployment = deployment
|
||||
else:
|
||||
last_deployment = matched_deployments[-1]
|
||||
# last_deployment = replace_vars_in_deployment(last_deployment, object) # Not needed because of custom_jinja2_enrichment_filter
|
||||
|
||||
# print(last_deployment)
|
||||
return last_deployment
|
||||
|
||||
def get_nes_fields(search, deployment):
|
||||
@@ -336,18 +343,18 @@ def add_annotations(detection):
|
||||
savedsearch_annotations[key] = detection['tags'][key]
|
||||
detection['savedsearch_annotations'] = savedsearch_annotations
|
||||
|
||||
# add SSA risk_severity
|
||||
if 'risk_score' in detection['tags']:
|
||||
if detection['tags']['risk_score'] >= 80:
|
||||
detection['tags']['risk_severity'] = 'high'
|
||||
elif(50>= detection['tags']['risk_score'] <=79):
|
||||
detection['tags']['risk_severity'] = 'medium'
|
||||
else:
|
||||
detection['tags']['risk_severity'] = 'low'
|
||||
return detection
|
||||
|
||||
def add_rba(detection):
|
||||
|
||||
# removed since this is causing a duplicate bug in ES 6.4+
|
||||
# if 'risk_object' in detection['tags']:
|
||||
# detection['risk_object'] = detection['tags']['risk_object']
|
||||
# if 'risk_object_type' in detection['tags']:
|
||||
# detection['risk_object_type'] = detection['tags']['risk_object_type']
|
||||
# if 'risk_score' in detection['tags']:
|
||||
# detection['risk_score'] = detection['tags']['risk_score']
|
||||
|
||||
# grab risk message
|
||||
if 'message' in detection['tags']:
|
||||
detection['risk_message'] = detection['tags']['message']
|
||||
@@ -433,7 +440,6 @@ def prepare_detections(detections, deployments, playbooks, OUTPUT_PATH):
|
||||
elif detection['type'] == 'Correlation':
|
||||
detection['search'] = detection['search'] + ' | collect index=alerts'
|
||||
|
||||
|
||||
# parse out data_models
|
||||
data_model = parse_data_models_from_search(detection['search'])
|
||||
if data_model:
|
||||
@@ -465,7 +471,7 @@ def prepare_detections(detections, deployments, playbooks, OUTPUT_PATH):
|
||||
if 'product' in detection['tags']:
|
||||
detection['product'] = detection['tags']['product']
|
||||
|
||||
# turn all SAAWS detections
|
||||
# enable all SAAWS detections
|
||||
if (OUTPUT_PATH) == 'dist/saaws':
|
||||
detection['disabled'] = 'false'
|
||||
|
||||
@@ -626,14 +632,17 @@ def compute_objects(objects, PRODUCT, OUTPUT_PATH):
|
||||
objects["detections"] = [object for object in objects["detections"] if 'Dev Sec Ops Analytics' in object['tags']['product']]
|
||||
objects["stories"] = [object for object in objects["stories"] if 'Dev Sec Ops Analytics' in object['tags']['product']]
|
||||
|
||||
if PRODUCT == "ESCU":
|
||||
# only use ESCU detections to the configurations
|
||||
objects["detections"] = sorted(filter(lambda d: not 'Splunk Behavioral Analytics' in d['tags']['product'], objects["detections"]), key=lambda d: d['name'])
|
||||
objects["stories"] = sorted(filter(lambda s: not 'Splunk Behavioral Analytics' in s['tags']['product'], objects["stories"]), key=lambda s: s['name'])
|
||||
|
||||
# only use ESCU detections to the configurations
|
||||
objects["detections"] = sorted(filter(lambda d: not 'Splunk Behavioral Analytics' in d['tags']['product'], objects["detections"]), key=lambda d: d['name'])
|
||||
# only use ESCU stories to the configuration
|
||||
objects["stories"] = sorted(filter(lambda s: not 'Splunk Behavioral Analytics' in s['tags']['product'], objects["stories"]), key=lambda s: s['name'])
|
||||
if PRODUCT == "SSA":
|
||||
# only SSA detections, also no need to calculate stories
|
||||
objects["detections"] = sorted(filter(lambda d: 'Splunk Behavioral Analytics' in d['tags']['product'], objects["detections"]), key=lambda d: d['name'])
|
||||
objects["stories"] = sorted(filter(lambda s: 'Splunk Behavioral Analytics' in s['tags']['product'], objects["stories"]), key=lambda s: s['name'])
|
||||
|
||||
objects["macros"] = sorted(objects["macros"], key=lambda m: m['name'])
|
||||
|
||||
objects["detections"] = prepare_detections(objects["detections"], objects["deployments"], objects["playbooks"], OUTPUT_PATH)
|
||||
objects["stories"] = prepare_stories(objects["stories"], objects["detections"], objects["playbooks"])
|
||||
|
||||
@@ -654,31 +663,36 @@ def main(REPO_PATH, OUTPUT_PATH, PRODUCT, VERBOSE):
|
||||
try:
|
||||
if VERBOSE:
|
||||
print("generating Mitre lookups")
|
||||
generate_mitre_lookup(OUTPUT_PATH)
|
||||
# generate_mitre_lookup(OUTPUT_PATH)
|
||||
except Exception as e:
|
||||
print('Error: ' + str(e))
|
||||
print("WARNING: Generation of Mitre lookup failed.")
|
||||
|
||||
lookups_path = generate_transforms_conf(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
lookups_path = generate_collections_conf(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
lookups_files = generate_lookup_files(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH,REPO_PATH)
|
||||
|
||||
detection_path = generate_savedsearches_conf(objects["detections"], objects["deployments"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
# story_path = generate_analytic_story_conf(objects["stories"], objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
use_case_lib_path = generate_use_case_library_conf(objects["stories"], objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
macros_path = generate_macros_conf(objects["macros"], objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
workbench_panels_objects = generate_workbench_panels(objects["detections"], objects["stories"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
# calculate deprecation totals
|
||||
deprecated = []
|
||||
for d in objects['detections']:
|
||||
if 'deprecated' in d:
|
||||
deprecated.append(d)
|
||||
|
||||
detection_path = ''
|
||||
lookups_path = ''
|
||||
lookups_files= ''
|
||||
use_case_lib_path = ''
|
||||
macros_path = ''
|
||||
workbench_panels_objects = ''
|
||||
|
||||
if global_product == 'SSA':
|
||||
detection_path = generate_ssa_yaml(objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
objects["macros"] = []
|
||||
else:
|
||||
detection_path = generate_savedsearches_conf(objects["detections"], objects["deployments"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
lookups_path = generate_transforms_conf(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
lookups_path = generate_collections_conf(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
lookups_files = generate_lookup_files(objects["lookups"], TEMPLATE_PATH, OUTPUT_PATH,REPO_PATH)
|
||||
use_case_lib_path = generate_use_case_library_conf(objects["stories"], objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
macros_path = generate_macros_conf(objects["macros"], objects["detections"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
workbench_panels_objects = generate_workbench_panels(objects["detections"], objects["stories"], TEMPLATE_PATH, OUTPUT_PATH)
|
||||
|
||||
if VERBOSE:
|
||||
print("{0} stories have been successfully written to {1}".format(len(objects["stories"]), use_case_lib_path))
|
||||
print("{0} detections have been successfully written to {1}".format(len(objects["detections"]), detection_path))
|
||||
|
||||
+4
-10
@@ -12,9 +12,7 @@ last_modified_at: {{detection.date}}
|
||||
toc: true
|
||||
toc_label: ""
|
||||
tags:
|
||||
- {{ detection.type }}
|
||||
{%- for attack in detection.mitre_attacks %}
|
||||
- {{ attack.technique_id }}
|
||||
- {{ attack.technique }}
|
||||
{%- for attack_tactic in attack.tactic %}
|
||||
- {{ attack_tactic }}
|
||||
@@ -28,9 +26,6 @@ tags:
|
||||
{%- endfor -%}
|
||||
{%- for datamodel in detection.datamodel %}
|
||||
- {{ datamodel }}
|
||||
{%- endfor -%}
|
||||
{%- for phase in detection.tags.kill_chain_phases %}
|
||||
- {{ phase }}
|
||||
{%- endfor %}
|
||||
---
|
||||
|
||||
@@ -55,12 +50,11 @@ We have not been able to test, simulate or build datasets for it, use at your ow
|
||||
{% if detection.mitre_attacks %}
|
||||
#### [ATT&CK](https://attack.mitre.org/)
|
||||
|
||||
| ID | Technique | Tactic |
|
||||
| ----------- | ----------- | ----------- |
|
||||
{% for attack in detection.mitre_attacks -%}
|
||||
| ID | Technique | Tactic |
|
||||
| ----------- | ----------- |--------------- |
|
||||
{%- for attack in detection.mitre_attacks %}
|
||||
{% if attack.technique_id -%}
|
||||
{% set sub_technique = attack.technique_id.split('.') -%}
|
||||
{% if sub_technique | length > 1 -%}
|
||||
{% set sub_technique = attack.technique_id.split('.') %}{% if sub_technique | length > 1 -%}
|
||||
| [{{ attack.technique_id }}](https://attack.mitre.org/techniques/{{sub_technique[0]}}/{{sub_technique[1]}}/) | {{ attack.technique }} | {{ attack.tactic|join(', ') }} |
|
||||
{% else -%}
|
||||
| [{{ attack.technique_id }}](https://attack.mitre.org/techniques/{{attack.technique_id}}/) | {{ attack.technique }} | {{ attack.tactic|join(', ') }} |
|
||||
@@ -1,98 +0,0 @@
|
||||
=Splunk Security Content Detections =
|
||||
|
||||
----
|
||||
All the detections shipped to different Splunk products. Below is a breakdown by kind.
|
||||
{% for kind in kinds %}
|
||||
=={{ kind.name|capitalize }}==
|
||||
|
||||
{% for detection in kind.detections %}
|
||||
==={{ detection.name|capitalize}}===
|
||||
{{ detection.description }}
|
||||
|
||||
* '''Product''': {{ detection.tags.product|join(', ') }}
|
||||
* '''Datamodel''': {{ detection.datamodel|join(', ') }}
|
||||
* '''ATT&CK''': {% for attack in detection.mitre_attacks -%}
|
||||
{%- if attack.technique_id -%}
|
||||
{% set sub_technique = attack.technique_id.split('.') %}
|
||||
{%- if sub_technique | length > 1 -%}
|
||||
[https://attack.mitre.org/techniques/{{sub_technique[0] }}/{{sub_technique[1]}}/ {{ attack.technique_id }}]
|
||||
{%- else -%}
|
||||
[https://attack.mitre.org/techniques/{{attack.technique_id}}/ {{ attack.technique_id }}]
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% if not loop.last -%}, {% endif -%}
|
||||
{% endfor %}
|
||||
* '''Last Updated''': {{ detection.date }}
|
||||
|
||||
<div class="toccolours mw-collapsible mw-collapsed">
|
||||
<div class="mw-collapsible-content">
|
||||
|
||||
====Search====
|
||||
<search>{{ detection.search|replace("|", "\n|") }}</search>
|
||||
|
||||
====Associated Analytic Story====
|
||||
{% for story in detection.tags.analytic_story %}
|
||||
* [[Documentation:ESSOC:stories:UseCase#{{ story|replace(" ", "_") }}|{{ story }}]]
|
||||
{% endfor %}
|
||||
|
||||
====How To Implement====
|
||||
{{ detection.how_to_implement}}
|
||||
|
||||
====Required field====
|
||||
{% for field in detection.tags.required_fields %}
|
||||
* {{ field }}
|
||||
{% endfor %}
|
||||
|
||||
{% if detection.mitre_attacks|length > 0 %}
|
||||
====ATT&CK====
|
||||
{|
|
||||
! style="text-align:left;"| ID
|
||||
! Technique
|
||||
! Tactic
|
||||
{%-for attack in detection.mitre_attacks %}
|
||||
|-
|
||||
| {{ attack.technique_id }}
|
||||
| {{ attack.technique }}
|
||||
| {{ attack.tactic|join(', ') }}
|
||||
{%- endfor %}
|
||||
|}
|
||||
{% endif %}
|
||||
|
||||
====Kill Chain Phase====
|
||||
{% for phase in detection.tags.kill_chain_phases %}
|
||||
* {{ phase }}
|
||||
{% endfor %}
|
||||
|
||||
====Known False Positives====
|
||||
{{ detection.known_false_positives}}
|
||||
|
||||
====Reference====
|
||||
{% if detection.references %}
|
||||
{% for reference in detection.references %}
|
||||
* {{ reference }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
====Test Dataset====
|
||||
{% for dataset in detection.tags.dataset %}
|
||||
* {{ dataset }}
|
||||
{% endfor %}
|
||||
|
||||
''version'': {{detection.version}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
----
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<pre>
|
||||
#############
|
||||
# Automatically generated by doc_gen.py in https://github.com/splunk/security_content''
|
||||
# On Date: {{ time }} UTC''
|
||||
# Author: Splunk Security Research''
|
||||
# Contact: research@splunk.com''
|
||||
#############
|
||||
</pre>
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
=Splunk Security Content Analytic Story =
|
||||
|
||||
----
|
||||
All the Analytic Stories shipped to different Splunk products. Below is a breakdown by Category.
|
||||
{% for category in categories %}
|
||||
=={{ category.name }}==
|
||||
|
||||
{% for story in category.stories %}
|
||||
==={{ story.name|capitalize }}===
|
||||
{{ story.description }}
|
||||
|
||||
* '''Product''': {{ story.tags.product|join(', ') }}
|
||||
* '''Datamodel''': {%-for datamodel in story.data_models %}[https://docs.splunk.com/Documentation/CIM/latest/User/{{ datamodel|replace("_", "")}} {{ datamodel }}]{% if not loop.last %}, {% endif %}{%-endfor %}
|
||||
* '''Last Updated''': {{ story.date }}
|
||||
* '''Use Case''': {{ story.tags.usecase }}
|
||||
|
||||
<div class="toccolours mw-collapsible">
|
||||
<div class="mw-collapsible-content">
|
||||
|
||||
====Detection Profile====
|
||||
{|
|
||||
! style="text-align:left;"| name
|
||||
! ID
|
||||
! Technique
|
||||
! Tactic
|
||||
! Type
|
||||
{%- for detection in story.detections %}
|
||||
|-
|
||||
| [[Documentation:ESSOC:detections:Detections#{{ detection.name|replace(" ", "_")|capitalize }}|{{ detection.name }}]]
|
||||
{% if story.mitre_attacks|length > 0 %}
|
||||
| {%-for attack in detection.mitre_attacks %}
|
||||
[https://attack.mitre.org/techniques/{{ attack.technique_id }}/ {{ attack.technique_id }}]{% if not loop.last %}, {% endif %}
|
||||
{%-endfor %}
|
||||
| {%-for attack in detection.mitre_attacks %}
|
||||
{{ attack.technique}}{{ ", " if not loop.last else "" }}
|
||||
{%- endfor %}
|
||||
| {%-for attack in detection.mitre_attacks %}
|
||||
{{ attack.tactic|join(', ') }}{{ ", " if not loop.last else "" }}
|
||||
{%- endfor %}
|
||||
{% else %}
|
||||
|
|
||||
|
|
||||
|
|
||||
{% endif %}
|
||||
| {{ detection.type }}
|
||||
{%- endfor %}
|
||||
|}
|
||||
|
||||
====Kill Chain Phase====
|
||||
{% for phase in story.kill_chain_phases %}
|
||||
* {{ phase }}
|
||||
{% endfor %}
|
||||
|
||||
====Reference====
|
||||
{% for reference in story.references %}
|
||||
* {{ reference }}
|
||||
{% endfor %}
|
||||
|
||||
''version'': {{story.version}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
----
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<pre>
|
||||
#############
|
||||
# Automatically generated by doc_gen.py in https://github.com/splunk/security_content
|
||||
# On Date: {{ time }} UTC
|
||||
# Author: Splunk Security Research
|
||||
# Contact: research@splunk.com
|
||||
#############
|
||||
</pre>
|
||||
+3
-6
@@ -103,16 +103,13 @@ def main(args):
|
||||
|
||||
# validate arguments
|
||||
validate_parser.set_defaults(func=validate, epilog="""
|
||||
Validates security manifest for correctness, adhering to spec and other common items.
|
||||
VALIDATE DOES NOT PROCESS RESPONSES SPEC for the moment.""")
|
||||
Validates security manifest for correctness, adhering to spec and other common items.""")
|
||||
|
||||
# generate arguments
|
||||
generate_parser.add_argument("-f", "--format", required=False, type=str, default="splunk_app",
|
||||
help="Format of our deployment package, defaults to `splunk_app`.\n The deployment `splunk_app` runs on product Splunk Enterprise Security and Splunk Enterprise.")
|
||||
generate_parser.add_argument("-o", "--output", required=False, type=str, default="dist/escu",
|
||||
help="Path where to store the deployment package, defaults to `dist/escu`")
|
||||
generate_parser.add_argument("--product", required=False, type=str, default="ESCU",
|
||||
help="Type of package to create, choose between `ESCU`, or `SAAWS`. Defaults to `ESCU`")
|
||||
generate_parser.add_argument("-p", "--product", required=False, type=str, default="ESCU",
|
||||
help="Type of package to create, choose between `ESCU`, `DevSecOps`, `SAAWS`, or `SSA`. Defaults to `ESCU`")
|
||||
generate_parser.set_defaults(func=generate)
|
||||
|
||||
# # parse them
|
||||
|
||||
@@ -19,7 +19,9 @@ search: '`gsuite_drive` NOT (email IN("", "null")) | rex field=parameters.owner
|
||||
| `gsuite_drive_share_in_external_email_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. In order for the search to work for your environment, please edit the query to use your company specific email domain instead of `internal_test_email.com`.
|
||||
extension, source email, destination email, num of attachment and etc. In order
|
||||
for the search to work for your environment, please edit the query to use your company
|
||||
specific email domain instead of `internal_test_email.com`.
|
||||
known_false_positives: network admin or normal user may share files to customer and
|
||||
external team.
|
||||
references:
|
||||
@@ -67,4 +69,3 @@ tags:
|
||||
- parameters.doc_type
|
||||
risk_score: 72
|
||||
security_domain: endpoint
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ search: '`gsuite_drive` parameters.owner_is_team_drive=false "parameters.doc_tit
|
||||
| `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. In order for the search to work for your environment, please edit the query to use your company specific email domain instead of `internal_test_email.com`.
|
||||
extension, source email, destination email, num of attachment and etc. In order
|
||||
for the search to work for your environment, please edit the query to use your company
|
||||
specific email domain instead of `internal_test_email.com`.
|
||||
known_false_positives: normal user or normal transaction may contain the subject and
|
||||
file type attachment that this detection try to search
|
||||
references:
|
||||
|
||||
@@ -19,6 +19,8 @@ tags:
|
||||
- CIS 3
|
||||
- CIS 4
|
||||
- CIS 18
|
||||
cve:
|
||||
- CVE-2016-4859
|
||||
kill_chain_phases:
|
||||
- Delivery
|
||||
nist:
|
||||
@@ -35,5 +37,3 @@ tags:
|
||||
required_fields:
|
||||
- _time
|
||||
security_domain: network
|
||||
cve:
|
||||
- CVE-2016-4859
|
||||
|
||||
@@ -24,6 +24,8 @@ tags:
|
||||
asset_type: Endpoint
|
||||
cis20:
|
||||
- CIS 4
|
||||
cve:
|
||||
- CVE-2017-5753
|
||||
nist:
|
||||
- ID.RA
|
||||
- RS.MI
|
||||
@@ -36,5 +38,3 @@ tags:
|
||||
required_fields:
|
||||
- _time
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2017-5753
|
||||
|
||||
@@ -26,6 +26,8 @@ tags:
|
||||
- CIS 3
|
||||
- CIS 4
|
||||
- CIS 18
|
||||
cve:
|
||||
- CVE-2018-11409
|
||||
kill_chain_phases:
|
||||
- Delivery
|
||||
nist:
|
||||
@@ -42,6 +44,3 @@ tags:
|
||||
required_fields:
|
||||
- _time
|
||||
security_domain: network
|
||||
cve:
|
||||
- CVE-2018-11409
|
||||
|
||||
@@ -33,13 +33,29 @@ tags:
|
||||
analytic_story:
|
||||
- Windows Persistence Techniques
|
||||
- Windows Privilege Escalation
|
||||
automated_detection_testing: passed
|
||||
confidence: 80
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/t1547.014/active_setup_stubpath/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1547.014
|
||||
- T1547
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -51,21 +67,5 @@ tags:
|
||||
- Registry.registry_path
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_value_name
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 80
|
||||
risk_score: 64
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Attacker Tools On Endpoint
|
||||
id: a51bfe1a-94f0-48cc-b4e4-16a110145893
|
||||
version: 1
|
||||
date: '2021-06-21'
|
||||
version: 2
|
||||
date: '2021-11-04'
|
||||
author: Bhavin Patel, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
@@ -14,7 +14,7 @@ search: '| tstats `security_content_summariesonly` count min(_time) as firstTime
|
||||
Processes.user!=unknown by Processes.dest Processes.user Processes.process_name
|
||||
Processes.process | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
|
||||
| `drop_dm_object_name(Processes)` | lookup attacker_tools attacker_tool_names AS
|
||||
process_name OUTPUT description | search description=* | `attacker_tools_on_endpoint_filter`'
|
||||
process_name OUTPUT description | search description !=false| `attacker_tools_on_endpoint_filter`'
|
||||
how_to_implement: To successfully implement this search, you must be ingesting data
|
||||
that records process activity from your hosts to populate the endpoint data model
|
||||
in the processes node. This is typically populated via endpoint detection-and-response
|
||||
|
||||
@@ -30,13 +30,29 @@ tags:
|
||||
analytic_story:
|
||||
- Windows Persistence Techniques
|
||||
- Windows Privilege Escalation
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1546.001/txtfile_reg/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1546.001
|
||||
- T1546
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -48,21 +64,5 @@ tags:
|
||||
- Registry.registry_path
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_value_name
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
name: CMD Carry Out String Command Parameter
|
||||
id: 54a6ed00-3256-11ec-b031-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-21'
|
||||
author: Teoderick Contreras, Splunk, Bhavin Patel, Splunk
|
||||
type: Hunting
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This search looks for command-line arguments where `cmd.exe /c` is used
|
||||
to execute a program. This technique is commonly seen in adversaries and malware
|
||||
to execute batch command using different shell like powershell or different process
|
||||
other than cmd.exe. This is a good hunting query for suspicious commandline made
|
||||
by a script or relative process execute it.
|
||||
search: '| tstats `security_content_summariesonly` min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where `process_cmd` AND Processes.process="*
|
||||
/c *" by Processes.dest Processes.user Processes.parent_process Processes.process_name
|
||||
Processes.original_file_name Processes.process Processes.process_id Processes.parent_process_id
|
||||
| `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
|
||||
| `cmd_carry_out_string_command_parameter_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: unknown
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IcedID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/cmd_carry_str_param/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1059.003
|
||||
- T1059
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.parent_process_name
|
||||
- Processes.parent_process
|
||||
- Processes.process_name
|
||||
- Processes.process_id
|
||||
- Processes.process
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 60
|
||||
confidence: 50
|
||||
risk_score: 30
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Execution
|
||||
message: $process_name$ with commandline $process$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Endpoint
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -6,25 +6,30 @@ author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This search is to detect a suspicious parent process execution of commandline
|
||||
tool not in shell commandline. This technique was seen in FIN7 JSSLoader .net compile
|
||||
payload where it run ipconfig.exe and systeminfo.exe using .net application. This
|
||||
event cause some good TTP since those tool are commonly run in commandline not by
|
||||
another application. This TTP is a good indicator for application gather host information
|
||||
either an attacker or an automated tool made by admin.
|
||||
description: The following analytic identifies a non-standard parent process (not
|
||||
matching CMD, PowerShell, or Explorer) spawning `ipconfig.exe` or `systeminfo.exe`.
|
||||
This particular behavior was seen in FIN7's JSSLoader .NET payload. This is also
|
||||
typically seen when an adversary is injected into another process performing different
|
||||
discovery techniques. This event stands out as a TTP since these tools are commonly
|
||||
executed with a shell application or Explorer parent, and not by another application.
|
||||
This TTP is a good indicator for an adversary gathering host information, but one
|
||||
possible false positive might be an automated tool used by a system administator.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where (Processes.process_name = "ipconfig.exe"
|
||||
OR Processes.process_name = "systeminfo.exe") AND NOT (Processes.parent_process_name
|
||||
= "cmd.exe" OR Processes.parent_process_name = "powershell*" OR Processes.parent_process_name
|
||||
= "explorer.exe") by Processes.parent_process_name Processes.parent_process Processes.process_name
|
||||
Processes.process_id Processes.process Processes.dest Processes.user | `drop_dm_object_name(Processes)`
|
||||
= "cmd.exe" OR Processes.parent_process_name = "powershell*" OR Processes.parent_process_name="pwsh.exe"
|
||||
OR Processes.parent_process_name = "explorer.exe") by Processes.parent_process_name
|
||||
Processes.parent_process Processes.process_name Processes.original_file_name Processes.process_id
|
||||
Processes.process Processes.dest Processes.user | `drop_dm_object_name(Processes)`
|
||||
| `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `cmdline_tool_not_executed_in_cmd_shell_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: network operator or admin may create this type of tool to gather
|
||||
host information
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition,
|
||||
confirm the latest CIM App 4.20 or higher is installed and the latest TA for the
|
||||
endpoint product.
|
||||
known_false_positives: A network operator or systems administrator may utilize an
|
||||
automated host discovery application that may generate false positives. Filter as
|
||||
needed.
|
||||
references:
|
||||
- https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html
|
||||
- https://attack.mitre.org/groups/G0046/
|
||||
@@ -41,8 +46,8 @@ tags:
|
||||
impact: 70
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: parent process name $parent_process_name$ with child process $process_name$
|
||||
to execute commandline tool in $dest$
|
||||
message: A non-standard parent process $parent_process_name$ spawned child process
|
||||
$process_name$ to execute command-line tool on $dest$.
|
||||
mitre_attack_id:
|
||||
- T1059
|
||||
- T1059.007
|
||||
@@ -55,18 +60,30 @@ tags:
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: parent_process_name
|
||||
type: Parent Process
|
||||
role:
|
||||
- Parent Process
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.parent_process_name
|
||||
- Processes.parent_process
|
||||
- Processes.process_name
|
||||
- Processes.process_id
|
||||
- Processes.process
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.parent_process
|
||||
- Processes.original_file_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_path
|
||||
- Processes.process_path
|
||||
- Processes.parent_process_id
|
||||
risk_score: 56
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -39,6 +39,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1218.002/atomic_red_team/windows-sysmon.log
|
||||
impact: 80
|
||||
@@ -84,5 +86,3 @@ tags:
|
||||
- Processes.parent_process_id
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
|
||||
@@ -30,6 +30,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Lateral Movement
|
||||
cve:
|
||||
- CVE-2020-1472
|
||||
impact: 70
|
||||
kill_chain_phases:
|
||||
- Actions on Objectives
|
||||
@@ -67,5 +69,3 @@ tags:
|
||||
- user
|
||||
risk_score: 49
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2020-1472
|
||||
|
||||
@@ -40,6 +40,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
cve:
|
||||
- CVE-2021-36934
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1003.002/serioussam/windows-powershell.log
|
||||
impact: 80
|
||||
@@ -72,5 +74,3 @@ tags:
|
||||
- EventCode
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-36934
|
||||
|
||||
@@ -10,8 +10,8 @@ description: The following analytic identifies regasm.exe with no command line a
|
||||
This particular behavior occurs when another process injects into regasm.exe, no
|
||||
command line arguments will be present. During investigation, identify any network
|
||||
connections and parallel processes. Identify any suspicious module loads related
|
||||
to credential dumping or file writes. Regasm.exe are natively found in C:\Windows\Microsoft.NET\Framework\v*\regasm|regsvcs.exe
|
||||
and C:\Windows\Microsoft.NET\Framework64\v*\regasm|regsvcs.exe.
|
||||
to credential dumping or file writes. Regasm.exe are natively found in `C:\Windows\Microsoft.NET\Framework\v*\regasm|regsvcs.exe`
|
||||
and `C:\Windows\Microsoft.NET\Framework64\v*\regasm|regsvcs.exe`.
|
||||
search: '| tstats `security_content_summariesonly` count FROM datamodel=Endpoint.Processes
|
||||
where `process_regasm` by _time span=1h Processes.process_id Processes.process_name
|
||||
Processes.dest Processes.process_path Processes.process Processes.parent_process_name
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
name: Disable Defender AntiVirus Registry
|
||||
id: aa4f695a-3024-11ec-9987-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This particular behavior is typically executed when an adversaries or
|
||||
malware gains access to an endpoint and beings to perform execution and to evade
|
||||
detections. Usually, a batch (.bat) will be executed and multiple registry and scheduled
|
||||
task modifications will occur. During triage, review parallel processes and identify
|
||||
any further file modifications. Endpoint should be isolated.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\Policies\\Microsoft\\Windows
|
||||
Defender*" Registry.registry_value_name = DisableAntiVirus Registry.registry_value_data
|
||||
= 0x00000001 by Registry.dest Registry.user Registry.registry_path Registry.registry_value_name
|
||||
Registry.registry_value_data | `drop_dm_object_name(Registry)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_defender_antivirus_registry_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Disable Defender BlockAtFirstSeen Feature
|
||||
id: 2dd719ac-3021-11ec-97b4-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic is to detect a suspicious modification of registry to disable
|
||||
windows defender feature. This technique is to bypassed or evade detection from
|
||||
Windows Defender AV product specially the BlockAtFirstSeen feature where it block
|
||||
suspicious file first seen in the host.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\Microsoft\\Windows
|
||||
Defender\\SpyNet*" Registry.registry_value_name = DisableBlockAtFirstSeen Registry.registry_value_data
|
||||
= 0x00000001 by Registry.dest Registry.user Registry.registry_path Registry.registry_value_name
|
||||
Registry.registry_value_data | `drop_dm_object_name(Registry)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_defender_blockatfirstseen_feature_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Disable Defender Enhanced Notification
|
||||
id: dc65678c-301f-11ec-8e30-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic is to detect a suspicious modification of registry to disable
|
||||
windows defender feature. This technique is to bypassed or evade detection from
|
||||
Windows Defender AV product specially the Enhanced Notification feature wher user
|
||||
or admin set to show or display alerts.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*Microsoft\\Windows
|
||||
Defender\\Reporting*" Registry.registry_value_name = DisableEnhancedNotifications
|
||||
Registry.registry_value_data = 0x00000001 by Registry.dest Registry.user Registry.registry_path
|
||||
Registry.registry_value_name Registry.registry_value_data | `drop_dm_object_name(Registry)`
|
||||
| `security_content_ctime(lastTime)` | `security_content_ctime(firstTime)` | `disable_defender_enhanced_notification_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data executions from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: user may choose to disable windows defender AV
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,66 @@
|
||||
name: Disable Defender MpEngine Registry
|
||||
id: cc391750-3024-11ec-955a-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This particular behavior is typically executed when an adversaries or
|
||||
malware gains access to an endpoint and beings to perform execution and to evade
|
||||
detections. Usually, a batch (.bat) will be executed and multiple registry and scheduled
|
||||
task modifications will occur. During triage, review parallel processes and identify
|
||||
any further file modifications. Endpoint should be isolated.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\Policies\\Microsoft\\Windows
|
||||
Defender\\MpEngine*" Registry.registry_value_name = MpEnablePus Registry.registry_value_data
|
||||
= 0x00000000 by Registry.dest Registry.user Registry.registry_path Registry.registry_value_name
|
||||
Registry.registry_value_data | `drop_dm_object_name(Registry)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_defender_mpengine_registry_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Disable Defender Spynet Reporting
|
||||
id: 898debf4-3021-11ec-ba7c-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic is to detect a suspicious modification of registry to disable
|
||||
windows defender feature. This technique is to bypassed or evade detection from
|
||||
Windows Defender AV product specially the spynet reporting for its telemetry.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\Microsoft\\Windows
|
||||
Defender\\SpyNet*" Registry.registry_value_name = SpynetReporting Registry.registry_value_data
|
||||
= 0x00000000 by Registry.dest Registry.user Registry.registry_path Registry.registry_value_name
|
||||
Registry.registry_value_data | `drop_dm_object_name(Registry)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_defender_spynet_reporting_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Disable Defender Submit Samples Consent Feature
|
||||
id: 73922ff8-3022-11ec-bf5e-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: his analytic is to detect a suspicious modification of registry to disable
|
||||
windows defender feature. This technique is to bypassed or evade detection from
|
||||
Windows Defender AV product specially the submit samples feature for further analysis..
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\Microsoft\\Windows
|
||||
Defender\\SpyNet*" Registry.registry_value_name = SubmitSamplesConsent Registry.registry_value_data
|
||||
= 0x00000000 by Registry.dest Registry.user Registry.registry_path Registry.registry_value_name
|
||||
Registry.registry_value_data | `drop_dm_object_name(Registry)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_defender_submit_samples_consent_feature_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the registry value name, registry path, and registry value data from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,62 @@
|
||||
name: Disable Schedule Task
|
||||
id: db596056-3019-11ec-a9ff-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-18'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic is to detect a suspicious commandline to disable existing
|
||||
schedule task. This technique is used by adversaries or commodity malware like IceID
|
||||
to disable security application (AV products) in the targetted host to evade detections.
|
||||
This TTP is a good pivot to check further why and what other process run before
|
||||
and after this detection. check which process execute the commandline and what task
|
||||
is disabled. parent child process is quite valuable in this scenario too.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime
|
||||
max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.process_name=schtasks.exe
|
||||
Processes.process=*/change* Processes.process=*/disable* by Processes.user Processes.process_name
|
||||
Processes.process Processes.parent_process_name Processes.parent_process Processes.dest
|
||||
| `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
|
||||
| `disable_schedule_task_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin may disable problematic schedule task
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IcedID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_schtask/sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.user
|
||||
- Processes.process_name
|
||||
- Processes.parent_process_name
|
||||
- Processes.dest
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 80
|
||||
risk_score: 56
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: schtask process with commandline $process$ to disable schedule task in
|
||||
$dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Endpoint
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -15,9 +15,9 @@ search: '| tstats `security_content_summariesonly` count min(_time) as firstTim
|
||||
by Registry.dest Registry.user Registry.registry_value_name Registry.registry_key_name
|
||||
Registry.registry_path Registry.registry_value_data | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `disable_security_logs_using_minint_registry_filter`'
|
||||
how_to_implement: To successfully implement this search, you must be ingesting
|
||||
data that records registry activity from your hosts to populate the endpoint data
|
||||
model in the registry node. This is typically populated via endpoint detection-and-response
|
||||
how_to_implement: To successfully implement this search, you must be ingesting data
|
||||
that records registry activity from your hosts to populate the endpoint data model
|
||||
in the registry node. This is typically populated via endpoint detection-and-response
|
||||
product, such as Carbon Black or endpoint data sources, such as Sysmon. The data
|
||||
used for this search is typically generated via logs that report reads and writes
|
||||
to the registry.
|
||||
@@ -27,12 +27,28 @@ references:
|
||||
tags:
|
||||
analytic_story:
|
||||
- Windows Defense Evasion Tactics
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1112/minint_reg/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1112
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -45,21 +61,5 @@ tags:
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -31,13 +31,29 @@ tags:
|
||||
analytic_story:
|
||||
- Windows Defense Evasion Tactics
|
||||
- Suspicious Windows Registry Activities
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1548.002/LocalAccountTokenFilterPolicy/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1548.002
|
||||
- T1548
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -50,21 +66,5 @@ tags:
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Disabling Defender Services
|
||||
id: 911eacdc-317f-11ec-ad30-acde48001122
|
||||
version: 1
|
||||
date: '2021-10-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This particular behavior is typically executed when an adversaries or
|
||||
malware gains access to an endpoint and beings to perform execution and to evade
|
||||
detections. Usually, a batch (.bat) will be executed and multiple registry and scheduled
|
||||
task modifications will occur. During triage, review parallel processes and identify
|
||||
any further file modifications. Endpoint should be isolated.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Registry where Registry.registry_path = "*\\System\\CurrentControlSet\\Services\\*"
|
||||
AND (Registry.registry_path IN("*WdBoot*", "*WdFilter*", "*WdNisDrv*", "*WdNisSvc*",
|
||||
"*WinDefend*", "*SecurityHealthService*")) AND Registry.registry_value_name = Start
|
||||
Registry.registry_value_data = 0x00000004 by Registry.dest Registry.user Registry.registry_path
|
||||
Registry.registry_value_name Registry.registry_value_data | `drop_dm_object_name(Registry)`
|
||||
| `security_content_ctime(lastTime)` | `security_content_ctime(firstTime)` | `disabling_defender_services_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you must have at least version 6.0.4 of the
|
||||
Sysmon TA.
|
||||
known_false_positives: admin or user may choose to disable windows defender product
|
||||
references:
|
||||
- https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/
|
||||
tags:
|
||||
analytic_story:
|
||||
- IceID
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/icedid/disable_av/sysmon2.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Registry.dest
|
||||
- Registry.user
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: modified/added/deleted registry entry $registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
@@ -17,9 +17,9 @@ search: '| tstats `security_content_summariesonly` count min(_time) as firstTim
|
||||
= 0x00000001 by Registry.dest Registry.user Registry.registry_value_name Registry.registry_key_name
|
||||
Registry.registry_path Registry.registry_value_data | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `enable_wdigest_uselogoncredential_registry_filter`'
|
||||
how_to_implement: To successfully implement this search, you must be ingesting
|
||||
data that records registry activity from your hosts to populate the endpoint data
|
||||
model in the registry node. This is typically populated via endpoint detection-and-response
|
||||
how_to_implement: To successfully implement this search, you must be ingesting data
|
||||
that records registry activity from your hosts to populate the endpoint data model
|
||||
in the registry node. This is typically populated via endpoint detection-and-response
|
||||
product, such as Carbon Black or endpoint data sources, such as Sysmon. The data
|
||||
used for this search is typically generated via logs that report reads and writes
|
||||
to the registry.
|
||||
@@ -29,13 +29,29 @@ references:
|
||||
tags:
|
||||
analytic_story:
|
||||
- Credential Dumping
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Credential Access
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1003/wdigest_enable/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: wdigest registry $registry_path$ was modified in $dest$
|
||||
mitre_attack_id:
|
||||
- T1112
|
||||
- T1003
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -48,21 +64,5 @@ tags:
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_path
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Credential Access
|
||||
message: wdigest registry $registry_path$ was modified in $dest$
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -28,14 +28,30 @@ tags:
|
||||
analytic_story:
|
||||
- Windows Persistence Techniques
|
||||
- Windows Privilege Escalation
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1127/etw_disable/sysmon.log
|
||||
impact: 90
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1562.006
|
||||
- T1127
|
||||
- T1562
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -48,21 +64,5 @@ tags:
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_value_name
|
||||
- Registry.registry_value_data
|
||||
security_domain: endpoint
|
||||
impact: 90
|
||||
confidence: 100
|
||||
risk_score: 90
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -28,13 +28,29 @@ tags:
|
||||
analytic_story:
|
||||
- Windows Persistence Techniques
|
||||
- Windows Privilege Escalation
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1037.001/logonscript_reg/sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
mitre_attack_id:
|
||||
- T1037
|
||||
- T1037.001
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -46,21 +62,5 @@ tags:
|
||||
- Registry.registry_path
|
||||
- Registry.registry_key_name
|
||||
- Registry.registry_value_name
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- source:endpoint
|
||||
- stage:Privilege Escalation Persistence
|
||||
message: modified/added/deleted registry entry $Registry.registry_path$ in $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: user
|
||||
type: user
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -46,13 +46,30 @@ tags:
|
||||
analytic_story:
|
||||
- Suspicious Regsvr32 Activity
|
||||
- Remcos
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/remcos/remcos/windows-sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: The $process_name$ was identified on endpoint $dest$ modifying the registry
|
||||
with a known malicious clsid under InProcServer32.
|
||||
mitre_attack_id:
|
||||
- T1218.010
|
||||
- T1112
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -65,22 +82,5 @@ tags:
|
||||
- registry_key_name
|
||||
- registry_value_name
|
||||
- user
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: The $process_name$ was identified on endpoint $dest$ modifying the registry
|
||||
with a known malicious clsid under InProcServer32.
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
+22
-18
@@ -5,18 +5,22 @@ date: '2021-10-05'
|
||||
author: David Dorsey, Michael Haag Splunk
|
||||
type: Hunting
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: 'The following hunting analytic identifies PowerShell commands utilizing the WindowStyle parameter to hide the window on the compromised endpoint. This combination of command-line options is suspicious because it is overriding the default PowerShell execution policy, attempts to hide its activity from the user, and connects to the Internet.
|
||||
Removed in this version of the query is New-Object.
|
||||
The analytic identifies all variations of WindowStyle, as PowerShell allows the ability to shorten the parameter. For example w, win, windowsty and so forth. In addition, through our research it was identified that PowerShell will interpret different command switch types beyond the hyphen. We have added endash, emdash, horizontal bar, and forward slash.'
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where `process_powershell` by Processes.user
|
||||
Processes.process_name Processes.process Processes.parent_process_name Processes.original_file_name Processes.dest Processes.process_id
|
||||
| `drop_dm_object_name(Processes)`
|
||||
| `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)`
|
||||
| where match(process,"(?i)[\-|\/|–|—|―]w(in*d*o*w*s*t*y*l*e*)*\s+[^-]")
|
||||
| `malicious_powershell_process___connect_to_internet_with_hidden_window_filter`'
|
||||
- Endpoint
|
||||
description: The following hunting analytic identifies PowerShell commands utilizing
|
||||
the WindowStyle parameter to hide the window on the compromised endpoint. This combination
|
||||
of command-line options is suspicious because it is overriding the default PowerShell
|
||||
execution policy, attempts to hide its activity from the user, and connects to the
|
||||
Internet. Removed in this version of the query is New-Object. The analytic identifies
|
||||
all variations of WindowStyle, as PowerShell allows the ability to shorten the parameter.
|
||||
For example w, win, windowsty and so forth. In addition, through our research it
|
||||
was identified that PowerShell will interpret different command switch types beyond
|
||||
the hyphen. We have added endash, emdash, horizontal bar, and forward slash.
|
||||
search: "| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)\
|
||||
\ as lastTime from datamodel=Endpoint.Processes where `process_powershell` by Processes.user\
|
||||
\ Processes.process_name Processes.process Processes.parent_process_name Processes.original_file_name\
|
||||
\ Processes.dest Processes.process_id | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`\
|
||||
\ | `security_content_ctime(lastTime)` | where match(process,\"(?i)[\\-|\\/|\u2013\
|
||||
|\u2014|\u2015]w(in*d*o*w*s*t*y*l*e*)*\\s+[^-]\") | `malicious_powershell_process___connect_to_internet_with_hidden_window_filter`"
|
||||
how_to_implement: You must be ingesting data that records process activity from your
|
||||
hosts to populate the Endpoint data model in the Processes node. You must also be
|
||||
ingesting logs with both the process name and command line from your endpoints.
|
||||
@@ -24,11 +28,11 @@ how_to_implement: You must be ingesting data that records process activity from
|
||||
model.
|
||||
known_false_positives: Legitimate process can have this combination of command-line
|
||||
options, but it's not common.
|
||||
references:
|
||||
- https://regexr.com/663rr
|
||||
- https://github.com/redcanaryco/AtomicTestHarnesses/blob/master/TestHarnesses/T1059.001_PowerShell/OutPowerShellCommandLineParameter.ps1
|
||||
- https://ss64.com/ps/powershell.html
|
||||
- https://twitter.com/M_haggis/status/1440758396534214658?s=20
|
||||
references:
|
||||
- https://regexr.com/663rr
|
||||
- https://github.com/redcanaryco/AtomicTestHarnesses/blob/master/TestHarnesses/T1059.001_PowerShell/OutPowerShellCommandLineParameter.ps1
|
||||
- https://ss64.com/ps/powershell.html
|
||||
- https://twitter.com/M_haggis/status/1440758396534214658?s=20
|
||||
tags:
|
||||
analytic_story:
|
||||
- Malicious PowerShell
|
||||
@@ -86,4 +90,4 @@ tags:
|
||||
- Processes.parent_process_name
|
||||
- Processes.dest
|
||||
risk_score: 81
|
||||
security_domain: endpoint
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -5,29 +5,38 @@ date: '2021-10-05'
|
||||
author: David Dorsey, Michael Haag, Splunk
|
||||
type: Hunting
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: 'The following analytic identifies the use of the EncodedCommand PowerShell parameter. This is typically used by Administrators to run complex scripts, but commonly used by adversaries to hide their code. \
|
||||
|
||||
The analytic identifies all variations of EncodedCommand, as PowerShell allows the ability to shorten the parameter. For example enc, enco, encod and so forth. In addition, through our research it was identified that PowerShell will interpret different command switch types beyond the hyphen. We have added endash, emdash, horizontal bar, and forward slash. \
|
||||
|
||||
During triage, review parallel events to determine legitimacy. Tune as needed based on admin scripts in use. \
|
||||
|
||||
- Endpoint
|
||||
description: 'The following analytic identifies the use of the EncodedCommand PowerShell
|
||||
parameter. This is typically used by Administrators to run complex scripts, but
|
||||
commonly used by adversaries to hide their code. \
|
||||
|
||||
The analytic identifies all variations of EncodedCommand, as PowerShell allows the
|
||||
ability to shorten the parameter. For example enc, enco, encod and so forth. In
|
||||
addition, through our research it was identified that PowerShell will interpret
|
||||
different command switch types beyond the hyphen. We have added endash, emdash,
|
||||
horizontal bar, and forward slash. \
|
||||
|
||||
During triage, review parallel events to determine legitimacy. Tune as needed based
|
||||
on admin scripts in use. \
|
||||
|
||||
Alternatively, may use regex per matching here https://regexr.com/662ov.'
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where `process_powershell` by Processes.user
|
||||
Processes.process_name Processes.process Processes.parent_process_name Processes.original_file_name Processes.dest Processes.process_id
|
||||
| `drop_dm_object_name(Processes)`
|
||||
| `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)`
|
||||
| where match(process,"(?i)[\-|\/|–|—|―]e(nc*o*d*e*d*c*o*m*m*a*n*d*)*\s+[^-]")
|
||||
| `malicious_powershell_process___encoded_command_filter`'
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information on process that include the name of the process responsible for the changes from your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition, confirm the latest CIM App 4.20 or higher is installed and the latest TA for the endpoint product.
|
||||
search: "| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)\
|
||||
\ as lastTime from datamodel=Endpoint.Processes where `process_powershell` by Processes.user\
|
||||
\ Processes.process_name Processes.process Processes.parent_process_name Processes.original_file_name\
|
||||
\ Processes.dest Processes.process_id | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`\
|
||||
\ | `security_content_ctime(lastTime)` | where match(process,\"(?i)[\\-|\\/|\u2013\
|
||||
|\u2014|\u2015]e(nc*o*d*e*d*c*o*m*m*a*n*d*)*\\s+[^-]\") | `malicious_powershell_process___encoded_command_filter`"
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition,
|
||||
confirm the latest CIM App 4.20 or higher is installed and the latest TA for the
|
||||
endpoint product.
|
||||
known_false_positives: System administrators may use this option, but it's not common.
|
||||
references:
|
||||
- https://regexr.com/662ov
|
||||
- https://github.com/redcanaryco/AtomicTestHarnesses/blob/master/TestHarnesses/T1059.001_PowerShell/OutPowerShellCommandLineParameter.ps1
|
||||
- https://ss64.com/ps/powershell.html
|
||||
- https://twitter.com/M_haggis/status/1440758396534214658?s=20
|
||||
- https://regexr.com/662ov
|
||||
- https://github.com/redcanaryco/AtomicTestHarnesses/blob/master/TestHarnesses/T1059.001_PowerShell/OutPowerShellCommandLineParameter.ps1
|
||||
- https://ss64.com/ps/powershell.html
|
||||
- https://twitter.com/M_haggis/status/1440758396534214658?s=20
|
||||
tags:
|
||||
analytic_story:
|
||||
- Malicious PowerShell
|
||||
@@ -75,4 +84,4 @@ tags:
|
||||
- Processes.dest
|
||||
- Processes.process_id
|
||||
risk_score: 35
|
||||
security_domain: endpoint
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -6,12 +6,12 @@ author: Teoderick Contreras, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic is to detect a suspicious child process of MSBuild
|
||||
spawned by Windows Script Host - cscript or wscript.
|
||||
This behavior or event are commonly seen and used by malware or adversaries
|
||||
to execute malicious msbuild process using malicious script in the compromised host.
|
||||
During triage, review parallel processes and identify any file modifications. MSBuild
|
||||
may load a script from the same path without having command-line arguments.
|
||||
description: This analytic is to detect a suspicious child process of MSBuild spawned
|
||||
by Windows Script Host - cscript or wscript. This behavior or event are commonly
|
||||
seen and used by malware or adversaries to execute malicious msbuild process using
|
||||
malicious script in the compromised host. During triage, review parallel processes
|
||||
and identify any file modifications. MSBuild may load a script from the same path
|
||||
without having command-line arguments.
|
||||
search: '| tstats `security_content_summariesonly` count values(Processes.process_name)
|
||||
as process_name values(Processes.process) as process min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where Processes.parent_process_name
|
||||
@@ -19,20 +19,42 @@ search: '| tstats `security_content_summariesonly` count values(Processes.proces
|
||||
Processes.parent_process_name Processes.process_name Processes.original_file_name
|
||||
Processes.user | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)` | `msbuild_suspicious_spawned_by_script_process_filter`'
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information on process that include the name of the process responsible for the changes from your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition, confirm the latest CIM App 4.20 or higher is installed and the latest TA for the endpoint product.
|
||||
known_false_positives: False positives should be limited as developers do not spawn MSBuild via a WSH.
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition,
|
||||
confirm the latest CIM App 4.20 or higher is installed and the latest TA for the
|
||||
endpoint product.
|
||||
known_false_positives: False positives should be limited as developers do not spawn
|
||||
MSBuild via a WSH.
|
||||
references:
|
||||
- https://app.any.run/tasks/dc93ee63-050c-4ff8-b07e-8277af9ab939/#
|
||||
tags:
|
||||
analytic_story:
|
||||
- Trusted Developer Utilities Proxy Execution MSBuild
|
||||
automated_detection_testing: passed
|
||||
confidence: 70
|
||||
context:
|
||||
- Stage:Execution
|
||||
- Stage:Defense Evasion
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1127.001/regsvr32_silent/sysmon.log
|
||||
impact: 70
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: Msbuild.exe process spawned by $parent_process_name$ on $dest$ executed
|
||||
by $user$
|
||||
mitre_attack_id:
|
||||
- T1127.001
|
||||
- T1127
|
||||
observable:
|
||||
- name: dest
|
||||
type: Endpoint
|
||||
role:
|
||||
- Victim
|
||||
- name: User
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
@@ -45,22 +67,5 @@ tags:
|
||||
- Processes.process_name
|
||||
- Processes.original_file_name
|
||||
- Processes.user
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Stage:Execution
|
||||
- Stage:Defense Evasion
|
||||
message: Msbuild.exe process spawned by $parent_process_name$ on $dest$ executed
|
||||
by $user$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Endpoint
|
||||
role:
|
||||
- Victim
|
||||
- name: User
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
automated_detection_testing: passed
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -33,6 +33,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/macro/windows-sysmon_mshtml.log
|
||||
impact: 80
|
||||
@@ -69,5 +71,3 @@ tags:
|
||||
- dest
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
|
||||
@@ -41,6 +41,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/macro/windows-sysmon_cabinf.log
|
||||
impact: 80
|
||||
@@ -74,5 +76,3 @@ tags:
|
||||
- file_path
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
|
||||
@@ -42,6 +42,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1566.001/macro/windows-sysmon_control.log
|
||||
impact: 80
|
||||
@@ -83,5 +85,3 @@ tags:
|
||||
- Processes.parent_process_id
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-40444
|
||||
|
||||
@@ -39,6 +39,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Credential Access
|
||||
cve:
|
||||
- CVE-2021-36942
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1187/petitpotam/windows-security.log
|
||||
impact: 80
|
||||
@@ -68,5 +70,3 @@ tags:
|
||||
- Message
|
||||
risk_score: 56
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-36942
|
||||
|
||||
@@ -33,6 +33,8 @@ tags:
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Credential Access
|
||||
cve:
|
||||
- CVE-2021-36942
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1187/petitpotam/windows-security.log
|
||||
impact: 80
|
||||
@@ -61,5 +63,3 @@ tags:
|
||||
- Message
|
||||
risk_score: 56
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-36942
|
||||
|
||||
@@ -42,6 +42,9 @@ tags:
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Defense Evasion
|
||||
- Scope:Incoming
|
||||
cve:
|
||||
- CVE-2021-34527
|
||||
- CVE-2021-1675
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1547.012/printnightmare/windows-printservice_operational.log
|
||||
impact: 80
|
||||
@@ -68,6 +71,3 @@ tags:
|
||||
- Message
|
||||
risk_score: 72
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-34527
|
||||
- CVE-2021-1675
|
||||
|
||||
@@ -40,6 +40,9 @@ tags:
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Defense Evasion
|
||||
- Scope:Incoming
|
||||
cve:
|
||||
- CVE-2021-34527
|
||||
- CVE-2021-1675
|
||||
dataset: []
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
@@ -66,6 +69,3 @@ tags:
|
||||
- Message
|
||||
risk_score: 72
|
||||
security_domain: endpoint
|
||||
cve:
|
||||
- CVE-2021-34527
|
||||
- CVE-2021-1675
|
||||
|
||||
@@ -32,7 +32,8 @@ how_to_implement: To successfully implement this search you need to be ingesting
|
||||
latest TA for the endpoint product.
|
||||
known_false_positives: False positives should be limited, however it is possible to
|
||||
filter by Processes.process_name and specific processes (ex. wscript.exe). Filter
|
||||
as needed. This may need modification based on EDR telemetry and how it brings in registry data. For example, removal of (Default).
|
||||
as needed. This may need modification based on EDR telemetry and how it brings in
|
||||
registry data. For example, removal of (Default).
|
||||
references:
|
||||
- https://blog.f-secure.com/hunting-for-koadic-a-com-based-rootkit/
|
||||
- https://www.script-coding.com/dynwrapx_eng.html
|
||||
@@ -42,34 +43,21 @@ references:
|
||||
tags:
|
||||
analytic_story:
|
||||
- Remcos
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/remcos/remcos/windows-sysmon.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1059
|
||||
- T1559.001
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- dest
|
||||
- process_name
|
||||
- process_guid
|
||||
- file_name
|
||||
- file_path
|
||||
- file_create_time user
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
automated_detection_testing: passed
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/malware/remcos/remcos/windows-sysmon.log
|
||||
impact: 80
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: An instance of $process_name$ was identified on endpoint $dest$ downloading
|
||||
the DynamicWrapperX dll.
|
||||
mitre_attack_id:
|
||||
- T1059
|
||||
- T1559.001
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
@@ -83,4 +71,17 @@ tags:
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
automated_detection_testing: passed
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- dest
|
||||
- process_name
|
||||
- process_guid
|
||||
- file_name
|
||||
- file_path
|
||||
- file_create_time user
|
||||
risk_score: 80
|
||||
security_domain: endpoint
|
||||
|
||||
@@ -11,14 +11,13 @@ description: The search looks for modifications to registry keys that can be use
|
||||
search: '| tstats `security_content_summariesonly` count values(Registry.registry_key_name)
|
||||
as registry_key_name values(Registry.registry_path) as registry_path min(_time)
|
||||
as firstTime max(_time) as lastTime FROM datamodel=Endpoint.Registry where (Registry.registry_path=*\\currentversion\\run*
|
||||
OR Registry.registry_path=*\\currentVersion\\Windows\\Appinit_Dlls* OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Shell*
|
||||
OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Notify*
|
||||
OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Userinit* OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\VmApplet*
|
||||
OR Registry.registry_path=*\\currentversion\\policies\\explorer\\run* OR Registry.registry_path=*\\currentversion\\runservices*
|
||||
OR Registry.registry_path=HKLM\\SOFTWARE\\Microsoft\\Netsh\\* OR (Registry.registry_path="*Microsoft\\Windows
|
||||
NT\\CurrentVersion\\Image File Execution Options*" AND Registry.registry_key_name=Debugger)
|
||||
OR (Registry.registry_path="*\\CurrentControlSet\\Control\\Lsa" AND Registry.registry_key_name="Security
|
||||
Packages") OR (Registry.registry_path="*\\CurrentControlSet\\Control\\Lsa\\OSConfig"
|
||||
OR Registry.registry_path=*\\currentVersion\\Windows\\Appinit_Dlls* OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Shell*
|
||||
OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Notify* OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\Userinit*
|
||||
OR Registry.registry_path=*\\CurrentVersion\\Winlogon\\VmApplet* OR Registry.registry_path=*\\currentversion\\policies\\explorer\\run*
|
||||
OR Registry.registry_path=*\\currentversion\\runservices* OR Registry.registry_path=HKLM\\SOFTWARE\\Microsoft\\Netsh\\*
|
||||
OR (Registry.registry_path="*Microsoft\\Windows NT\\CurrentVersion\\Image File Execution
|
||||
Options*" AND Registry.registry_key_name=Debugger) OR (Registry.registry_path="*\\CurrentControlSet\\Control\\Lsa"
|
||||
AND Registry.registry_key_name="Security Packages") OR (Registry.registry_path="*\\CurrentControlSet\\Control\\Lsa\\OSConfig"
|
||||
AND Registry.registry_key_name="Security Packages") OR (Registry.registry_path="*\\Microsoft\\Windows
|
||||
NT\\CurrentVersion\\SilentProcessExit\\*") OR (Registry.registry_path="*currentVersion\\Windows"
|
||||
AND Registry.registry_key_name="Load") OR (Registry.registry_path="*\\CurrentVersion"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user