Skip to content

πŸ”Ž Application Vulnerability Scanning

βœ… EXERCISE: Build a Continuous Integration Pipeline

For this exercise, go to the repository setComparisontings and set juice-shop > CI/CD Settings and set CI/CD configuration file to .gitlab/.gitlab-ci.yml, otherwise the pipeline will try to be created on root folder.

INSECURE PIPELINE! Avoid saving passwords as variables!

variables:
  IMAGE_NAME: onisimiacob/demo-app
  IMAGE_VERSION: juice-shop-1.0

stages:
  - cache
  - test
  - build

# Improove build times with a cache task that saves the dependencies as an artifact
create_cache:
  image: node:18-bullseye
  stage: cache
  script:
    - yarn install --ignore-engines 
  cache:
    key:
      files:
        - yarn.lock
    paths:
      - node_modules
      - yarn.lock
      - .yarn
    policy: pull-push

# Test using the cache to speedup testing
yarn_test:
  image: node:18-bullseye
  stage: test
  script:
    - yarn install --ignore-engines # fix The engine "node" is incompatible with this module. Expected version "20 || >=22". Got "18.20.8"
    - yarn test
  cache:
    key:
      files:
        - yarn.lock
    paths:
      - node_modules
      - yarn.lock
      - .yarn
    policy: pull

# Build the docker image
build_image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_USER: onisimiacob
    DOCKER_PASS: 1234567890!
  before_script:
    - echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
  script:
    - docker build -t $IMAGE_NAME:$IMAGE_VERSION .
    - docker push $IMAGE_NAME:$IMAGE_VERSION

SECURE PIPELINE!

Instead of only building the application, we DevSecOps integrates security through the workflow. Such vulnerabilities could be hardcoded passwords, connection strings (secrets). This is a leaky asset, and you never know where it ends up.

Secret scanning with Gitleaks

Lightweight open-source application for git repositories that detects over 160 secret types, new types added all the time.

Running this command inside the git repository, will mount the "." local path with /path inside the docker and allow us to scan for all vulnerabilities.

In addition add --verbose flag at the end to see on screen what are the encountered vulnerabilites.

docker run -v .:/path zricethezav/gitleaks:latest detect --source="/path" #--verbose to see vulnearbilities on screen


    β—‹
    β”‚β•²
    β”‚ β—‹
    β—‹ β–‘
    β–‘    gitleaks

7:11PM INF 132 commits scanned.
7:11PM INF scanned ~9214215 bytes (9.21 MB) in 1.93s
7:11PM WRN leaks found: 42

Pre-Commit hook for secret scanning

We can add hooks such as pre-commits which are actions that gets executed before a push is made to remote. These hooks are stored on .git/hooks/pre-commits

Note

It can be easily be automated with pre-commit which is a python package.

False Positives

First, we cannot block the pipeline deployment with tools that we are not yet sure on how they may behave. This is why we need to allow builds to continue. This can be achieved with pipeline flags such as:

gitleaks:
  stage: test
  image:
    name: zricethezav/gitleaks:latest
    entrypoint: [""]
  script:
    - gitleaks detect --verbose --source .
  allow_failure: true # <- This allows the task to fail but continue!

Pipeline Variables

On the Gitlab Project you can head to juice-shop > CI/CD Settings > Variables > Add variable > Key: DOCKER_PASS; Value: my_pass.

Note

Only DevOps or repository Admins/Owners (1 or 2 team members) should have access to the repository settings to add or modify variables.

...
  variables:
   DOCKER_USER: onisimiacob
   DOCKER_PASS: 1234567890! # BAD PRACTICE!!!
...

Warning

We should CHANGE THE PASSWORD as we already gitted the password. Gitleaks searches all commits, so we need to recreate a new password to fully fix the issue.

...
  variables:
   DOCKER_USER: $DOCKER_USER
   DOCKER_PASS: $DOCKER_PASS # GOOD PRACTICE :)
...

SAST Example Tools

Static analysis Security Testing (SAST) main goal is to reduce security findings over time and so that nothing gets deployed to production.

  • Write secure code.
  • Configure app and system securely.

We add tools to scan the static code, we have SAST tools based on the programming language. For our exercise, we can use a Njscan tool and another Semgrep tool that allows us to scan the local code (thats why it is called static) for vulnerabilities.

...
# Scan for NodeJS SAST vulnerabilies
njsscan:
  stage: test
  image: python
  before_script:
    - pip3 install --upgrade njsscan
  script:
    - njsscan --exit-warning . --sarif -o njsscan.sarif
  allow_failure: true

# Scan with SemGrep
semgrep:
  stage: test
  image: semgrep/semgrep
  variables:
    SEMGREP_RULES: p/javascript
  script:
    - semgrep ci --json --output semgrep.json
  allow_failure: true
...

SAST Scan Results

However, this will create different type of results such as:

  • NjsScan: It is pretty usefull and easy to understand!

NjsScan Screenshot

  • SemGrep: On the other hand, some tools may detect more vulnerabilites but the output is humanly unreadable...

SemGrep Screenshot