Skip to main content

Angularjs CSTI Scanner

acstis logo

License Apache-2.0GitHub release (latest SemVer)OWASP Lab ProjectArtifact HUBGitHub Repo starsTwitter Follower

What is AngularJS Client-Side Template Injection Scanner (acstis)?

The AngularJS Client-Side Template Injection Scanner (acstis) is an open source scanner for finding possible template injection vulnerabilities on websites using AngularJS.

For more information visit the projects GitHub site.

Deployment

The angularjs-csti-scanner chart can be deployed via helm:

# Install HelmChart (use -n to configure another namespace)
helm upgrade --install angularjs-csti-scanner secureCodeBox/angularjs-csti-scanner

Scanner Configuration

The only mandatory parameter is:

Optional arguments:

-c, --crawl                                                                      use the crawler to scan all the entire domain
-vp, --verify-payload use a javascript engine to verify if the payload was executed (otherwise false positives may occur)
-av ANGULAR_VERSION, --angular-version ANGULAR_VERSION manually pass the angular version (e.g. 1.4.2) if the automatic check doesn't work
-vrl VULNERABLE_REQUESTS_LOG, --vulnerable-requests-log VULNERABLE_REQUESTS_LOG log all vulnerable requests to this file (e.g. /var/logs/acstis.log or urls.log)
-siv, --stop-if-vulnerable (crawler option) stop scanning if a vulnerability was found
-pmm, --protocol-must-match (crawler option) only scan pages with the same protocol as the starting point (e.g. only https)
-sos, --scan-other-subdomains (crawler option) also scan pages that have another subdomain than the starting point
-soh, --scan-other-hostnames (crawler option) also scan pages that have another hostname than the starting point
-sot, --scan-other-tlds (crawler option) also scan pages that have another tld than the starting point
-md MAX_DEPTH, --max-depth MAX_DEPTH (crawler option) the maximum search depth (default is unlimited)
-mt MAX_THREADS, --max-threads MAX_THREADS (crawler option) the maximum amount of simultaneous threads to use (default is 20)
-iic, --ignore-invalid-certificates (crawler option) ignore invalid ssl certificates

Do not override the option -vrl or --vulnerable-requests-log. It is already configured for automatic findings parsing.

Requirements

Kubernetes: >=v1.11.0-0

Additional Chart Configurations

Request configuration

Because acstis does not provide command line arguments for configuring the sent requests, you have to mount a config map into the scan container on a specific location. Your additional config map should be mounted to /home/angularjscsti/acstis/config/acstis-config.py. For example create a config map:

kubectl create configmap --from-file /path/to/my/acstis-config.py acstis-config

Then, mount it into the container:

    volumes:
- name: "acstis-config"
configMap:
name: "acstis-config"
volumeMounts:
- name: "acstis-config"
mountPath: "/home/angularjscsti/acstis/config/"

Configuration options in acstis-config.py

Add the following snippets to the acstis-config.py file to enable further options. The options are python code which will be injected into the acstis script before execution.

Basic Authentication

options.identity.auth = HTTPBasicAuth("username", "password")

Cookies

options.identity.cookies.set(name='tasty_cookie', value='yum', domain='finnwea.com', path='/cookies')
options.identity.cookies.set(name='gross_cookie', value='blech', domain='finnwea.com', path='/elsewhere')

Headers

options.identity.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Authorization": "Bearer ey3jafoe.2jefo..."
})

Proxies

options.identity.proxies = {
# No authentication
# 'http': 'http://host:port',
# 'https': 'http://host:port',

# Basic authentication
# 'http': 'http://user:pass@host:port',
# 'https': 'https://user:pass@host:port',

# SOCKS
'http': 'socks5://user:pass@host:port',
'https': 'socks5://user:pass@host:port'
}

Scope options

options.scope.protocol_must_match = False

options.scope.subdomain_must_match = True

options.scope.hostname_must_match = True

options.scope.tld_must_match = True

options.scope.max_depth = None

options.scope.request_methods = [
Request.METHOD_GET,
Request.METHOD_POST,
Request.METHOD_PUT,
Request.METHOD_DELETE,
Request.METHOD_OPTIONS,
Request.METHOD_HEAD
]

Values

KeyTypeDefaultDescription
cascadingRules.enabledboolfalseEnables or disables the installation of the default cascading rules for this scanner
parser.affinityobject{}Optional affinity settings that control how the parser job is scheduled (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)
parser.envlist[]Optional environment variables mapped into each parseJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
parser.image.pullPolicystring"IfNotPresent"Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images
parser.image.repositorystring"docker.io/securecodebox/parser-angularjs-csti-scanner"Parser image repository
parser.image.tagstringdefaults to the charts versionParser image tag
parser.scopeLimiterAliasesobject{}Optional finding aliases to be used in the scopeLimiter.
parser.tolerationslist[]Optional tolerations settings that control how the parser job is scheduled (see: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)
parser.ttlSecondsAfterFinishedstringnilseconds after which the kubernetes job for the parser will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/
scanner.activeDeadlineSecondsstringnilThere are situations where you want to fail a scan Job after some amount of time. To do so, set activeDeadlineSeconds to define an active deadline (in seconds) when considering a scan Job as failed. (see: https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup)
scanner.affinityobject{}Optional affinity settings that control how the scanner job is scheduled (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)
scanner.backoffLimitint3There are situations where you want to fail a scan Job after some amount of retries due to a logical error in configuration etc. To do so, set backoffLimit to specify the number of retries before considering a scan Job as failed. (see: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy)
scanner.envlist[]Optional environment variables mapped into each scanJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
scanner.extraContainerslist[]Optional additional Containers started with each scanJob (see: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)
scanner.extraVolumeMountslist[]Optional VolumeMounts mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
scanner.extraVolumeslist[]Optional Volumes mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/)
scanner.image.pullPolicystring"IfNotPresent"Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images
scanner.image.repositorystring"docker.io/securecodebox/scanner-angularjs-csti-scanner"Container Image to run the scan
scanner.image.tagstringnildefaults to the charts appVersion
scanner.nameAppendstringnilappend a string to the default scantype name.
scanner.resourcesobject{}CPU/memory resource requests/limits (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/)
scanner.securityContextobject{"allowPrivilegeEscalation":false,"capabilities":{"drop":["all"]},"privileged":false,"readOnlyRootFilesystem":false,"runAsNonRoot":true}Optional securityContext set on scanner container (see: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
scanner.securityContext.allowPrivilegeEscalationboolfalseEnsure that users privileges cannot be escalated
scanner.securityContext.capabilities.drop[0]string"all"This drops all linux privileges from the container.
scanner.securityContext.privilegedboolfalseEnsures that the scanner container is not run in privileged mode
scanner.securityContext.readOnlyRootFilesystemboolfalsePrevents write access to the containers file system
scanner.securityContext.runAsNonRootbooltrueEnforces that the scanner image is run as a non root user
scanner.tolerationslist[]Optional tolerations settings that control how the scanner job is scheduled (see: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)
scanner.ttlSecondsAfterFinishedstringnilseconds after which the kubernetes job for the scanner will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/

License

License

Code of secureCodeBox is licensed under the Apache License 2.0.

Examples

scan-single-url

This example scans a single URL.

# SPDX-FileCopyrightText: the secureCodeBox authors
#
# SPDX-License-Identifier: Apache-2.0

apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "scan-single-url"
spec:
scanType: "angularjs-csti-scanner"
parameters:
- "-d"
- "https://example.com"

scan-website-with-options

To add some headers to the scanners requests create a file called acstis-config.py with the following content:

options.identity.headers.update({
"Authorization": "Bearer <JWT>"
})

Then create a config map from this file:

kubectl create configmap --from-file /path/to/my/acstis-config.py acstis-config 

After mounting the config map to the specified path you can execute your scan.

# SPDX-FileCopyrightText: the secureCodeBox authors
#
# SPDX-License-Identifier: Apache-2.0

apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "scan-website-with-jwt"
spec:
scanType: "angularjs-csti-scanner"
parameters:
- "-d"
- "https://example.com"
- "-c"
# you should always specify a max depth when crawling
- "-md"
- "3"
volumes:
- name: "acstis-config"
configMap:
name: "acstis-config"
volumeMounts:
- name: "acstis-config"
mountPath: "/home/angularjscsti/acstis/config/"