Scanner for Gitlab Security Mis-Configurations
Most of the tools for Code Analysis focus on scanning the code itself (like SAST tools), but what about the repository containing the code? Some vulnerabilities or mis-configuration in the repository could lead to countless attack vectors without having any vulnerability in the code itself.
Scanning repository mis-configurations it's a critical part of securing your infrastructure.
Here are some common mis-configurations checks for Gitlab repositories.
- Change to repostiory dir:
cd ess-gitlab
- Create venv for this project:
python3 -m venv venv/ess-gitlab
- Source venv you just created
source venv/ess-gitlab/bin/activate
- Install ess-gitlab requirements in the sourced venv:
pip3 install -r requirements.txt
- Gitlab Token:
export GITLAB_TOKEN=<your-token>
- Run:
./ess-gitlab.py --gitlab_url <your-gitlab-url> --mode baseline --check project --baseline baselines/log4j.yml --id <your-proj-id>
(Each time you need to use this program just source venv you created (step 3))
This tool can run in 2 different modes (--mode
):
- Inventory: It will fetch all the information for a specific scope (
check
+id
). - Baseline: It will fetch all the information for a specific scope (
check
+id
) and compare with the baseline definition for that scope for generating a mis-configuration report
You can define --id
as a "project id", as a "group id" for getting all project ids under that group or "all" for getting all project ids. You can use spaces to add more than 1.
For ESS-Gitlab to function properly it requires certain Gitlab scopes. Ensure you have at a minimum maintainer priviliges on the repository and use read_only (read_user, read_api, read_repository, read_registry) scopes for the Gitlab API token.
You can supply the gitlab token in two ways to ESS-Gitlab:
- Use environment variables called "gitlab_token" (RECOMMENDED)
- Use CLI switch --gitlab_token
Environment variable
EXPORT gitlab_token=<<token_value>>
./ess-gitlab.py --gitlab_url https://yourgitlab.com --mode inventory --check project --id <PROJECT_ID>/<GROUP ID>/all
CLI Switch
./ess-gitlab.py --gitlab_url https://yourgitlab.com --gitlab_token yourgitlabtoken --mode inventory --check project --id <PROJECT_ID>/<GROUP ID>/all
Environment variable
EXPORT gitlab_token=<<token_value>>
./ess-gitlab.py --gitlab_url https://yourgitlab.com --mode baseline --check project --id <PROJECT_ID>/<GROUP ID>/all
CLI Switch
./ess-gitlab.py --gitlab_url https://yourgitlab.com --gitlab_token yourgitlabtoken --mode baseline --check project --id <PROJECT_ID>/<GROUP ID>/all
--gitlab_token
: Gitlab API token with sufficient scope and privileges.--jsonfile
: Generates JSON file with output (inventory or baseline). Use --no-jsonfile, or omit, to not write to file.--jsonprint
: Print JSON to stdout. Use --no-jsonprint, or omit, to not write to stdout.--baseline
: Defines where is the baseline file. Default:baselines/default.yml
--log
: Logger level. Valid Options: ERROR, INFO or DEBUG. Default: ERROR--totalonly
: Only write total project findings to stdout. Default: False--scan-archived
: Scan also archived projects. Default: False--max-all
: If usingall
as--id
, this is the maximun amount of project to be scanned. Default: 100
You can define your own baseline based on your needs or use the default one. You can choose what checks to perform and the expected value of those checks.
You can define a baseline using the following type of values:
- None: Check disabled. Useful if you want to keep the baselines check keys as reference. None is the same as not adding that check key to the baseline.
- String: Matching string to output (Example: 'internal')
- Bool: True matchs if output has data or if output True. False matchs if no Data or if output False.
- List: At least 1 of the values must be in the output (Example: '[docker:latest]'). Empty list ('[]') same as False.
You can create a baseline that applies for all projects using project id as *
or you can specify what you expect from each projects project by defining a baseline with the specific id
of those projects.
You can use one baseline to define more than one project.
If you define a baseline for a specific project and in the same one also values for all projects, the most specific defintion will be apllied. So *
will not be check in the specific project.
TO DO: Baselines by Group IDs.
- Project Visibility
- Pages Access Level
- Security and Compliance
- Approvals before Merge
- Push Rules: Unsigned Commits
- Push Rules: Comitter Check
- Protected Branches
- Project Access Tokens
- Project Deploy Tokens
- Project Deploy Keys
- Project file pipeline (
.gitlab-ci.yml
) - Project Merged Pipeline
- Project Merged Pipeline block:
stages
- Project Merged Pipeline block:
image
- Project file codeowners (
CODEOWNERS
) - Project Shared Runners Enabled
- Project Runners
- Project Runners Shared
- Project Runners Not Shared
- Gitlab Documentation
- Baseline Key:
project_visibility
- Inventory Outputs:
internal
,public
,private
- Default Baseline:
internal
- Gitlab Documentation
- Baseline Key:
project_pages_access_level
- Inventory Outputs:
public
,private
- Default Baseline:
private
- Gitlab Documentation
- Baseline Key:
project_security_and_compliance_enabled
- Inventory Outputs:
true
,false
- Default Baseline:
true
- Gitlab Documentation
- Baseline Key:
project_approvals_before_merge
- Inventory Outputs: Number of Approvals before Merge
- Default Baseline:
1
- TO DO: optional/required different output
- Gitlab Documentation
- Baseline Key:
project_push_rules_unsigned_commits
- Inventory Outputs:
true
,false
- Default Baseline:
true
- Gitlab Documentation
- Baseline Key:
project_push_rules_comitter_check
- Inventory Outputs:
true
,false
- Default Baseline:
true
- Gitlab Documentation
- Baseline Key:
project_protected_branches
- Inventory Outputs: List of Protected Branches
- Default Baseline:
true
- TO DO: Check by branch
- Gitlab Documentation
- Baseline Key:
project_access_tokens
- Inventory Outputs: List of Project Access Tokens
- Default Baseline:
false
- Gitlab Documentation
- Baseline Key:
project_deploy_tokens
- Inventory Outputs: List of Project Deploy Tokens
- Default Baseline:
false
- Gitlab Documentation
- Baseline Key:
project_deploy_keys
- Inventory Outputs: List of Project Deploy Keys
- Default Baseline:
false
- Gitlab Documentation
- Baseline Key:
project_file_pipeline
- Inventory Outputs:
false
or.gitlab-ci.yml
content - Default Baseline:
true
- Gitlab Documentation
- Baseline Key:
project_merged_pipeline
- Inventory Outputs:
false
or full pipeline content (including "include" blocks) - Default Baseline:
true
- Gitlab Documentation
- Baseline Key:
project_merged_pipeline_stages
- Posible Outputs: List of all pipeline Stages (including "include" blocks)
- Default Baseline:
None
- Gitlab Documentation
- Baseline Key:
project_merged_pipeline_image
- Posible Outputs: List of all images in any stage of the pipeline (including "include" blocks)
- Default Baseline:
None
- Gitlab Documentation
- Baseline Key:
project_file_codeowners
- Inventory Outputs:
true
,false
- Default Baseline:
True
- Gitlab Documentation
- Baseline Key:
project_shared_runners_enabled
- Inventory Outputs:
true
,false
- Default Baseline:
False
- Gitlab Documentation
- Baseline Key:
project_runners
- Inventory Outputs: List of all runners configured in the project
- Default Baseline:
True
- Gitlab Documentation
- Baseline Key:
project_runners_shared
- Inventory Outputs: List of all runners shared configured in the project
- Default Baseline:
False
- Gitlab Documentation
- Baseline Key:
project_runners_notshared
- Inventory Outputs: List of all runners not shared configured in the project
- Default Baseline:
True
Needs to be used with flag --scanlog4j
- Baseline Key:
project_log4j
- Inventory Outputs: List search output for all
log4j
matchs. - Default Baseline: List search output based on
log4j
and that matchs content of keyproject_log4j
Check if "Push Rules: Unsigned Commits" and "Push Rules: Comitter Check" are enabled for all projects (*
)
projects:
- '*':
- project_push_rules_unsigned_commits: True
- project_push_rules_comitter_check: True
projects:
- '1234':
- project_visibility: 'internal'
- '4321':
- project_visibility: 'public'
projects:
- '*':
- project_merged_pipeline_image: ['docker:latest']
projects:
- '*':
- project_access_tokens: False
- project_deploy_tokens: False
- project_deploy_keys: False
projects:
- '*':
- project_file_pipeline: True
projects:
- '*':
- project_merged_pipeline: True
projects:
- '*':
- project_file_codeowners: True
This check needs to use the flag --scanlog4j
projects:
- '*':
- project_log4j: ['org.apache.logging.log4j']