Skip to main content

Angularjs CSTI Scanner

acstis logo

License Apache-2.0GitHub release (latest SemVer)OWASP Incubator 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/"