Security Application Security Testing (SAST)
Static Application Security Testing (SAST) aims to scan source code to identify poor coding practices that could lead to security vulnerabilities. A number of vendors are now providing SAST tools as part of their offerings geared towards security-concious customers. Platforms such as GitHub, GitLab, Snyk, SonarQube offer cloud-based integration of SAST features in the CI/CD pipeline.
phpcs-security-audit
phpcs-security-audit
provides a set of PHP CodeSniffer rules geared towards
vulnerability scanning. GitLab uses this analyzer to scan PHP-based repos. Being
an open source product, phpcs-security-audit
is also provided as a Docker
image on the GitLab Container
Registry.
Automating local deployment and analysis
The following script setups everything needed to deploy phpcs-security-audit
analyzer as a docker container on your system. The
/opt/code_analysis/sast_script.sh
is then set as the entrypoint
for the
docker container. You can add or remove more PHP repos by editing the $scan_repos
variable in the sast_script.sh
script. Finally, docker volumes are used to
make the /opt/repos
and /opt/code_analysis
directories available within the
container to avoid code duplication.
#!/bin/sh
# This script makes use of GitLab's phpcs-security-audit analyzer to perform
# Static Application Security Testing (SAST), also known as source code
# scanning. This script automates the docker setup and uses a script named
# 'sast_script.sh' to perform SAST analysis on all paths provided via the
# $scan_repos variable.
#
# Assumptions:
# - The /opt/repos directory holds all the code repositories
# - The /opt/code_analysis directory holds all SAST-related code
# - The SAST reports will be saved to /opt/code_analysis/sast_reports
# Pull the docker image from GitLab Container Registry
docker pull registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit:4.1.5
# Setup the required directory structure
mkdir -p /opt/code_analysis
mkdir -p /opt/code_analysis/sast_reports
mkdir -p /opt/repos
chmod -R o+w /opt/code_analysis
chmod -R o+w /opt/repos
## Clone the required repos to /opt/repos
read -p "Clone the required repos to /opt/repos/. Press enter to continue."
# We will use this script as the entry point for our docker container. You can
# configure the $scan_repos variable to specify the repos you want to be
# analyzed.
cat << 'EOF' > /opt/code_analysis/sast_script.sh
#!/bin/sh
report_dir="/opt/code_analysis/sast_reports"
scan_repos="$scan_repos /opt/repos/DVWA"
scan_repos="$scan_repos /opt/repos/OSTE-Vulnerable-Web-Application"
default_sast_report_name="gl-sast-report.json"
for repo in $scan_repos;
do
echo $repo;
repo_basename="$(echo $repo | cut -d\/ -f4)"
echo $repo_basename
sast_report_name=$repo_basename"_gl_sast-""$(date +%Y-%m-%d-%H:%M).json"
/analyzer run --target-dir $repo
mv $repo/$default_sast_report_name $report_dir/$sast_report_name
done
EOF
chmod +x /opt/code_analysis/sast_script.sh
# We mount /opt/repos and /opt/code_analysis in the docker container
docker run --name phpcs-security-audit \
-v /opt/repos/:/opt/repos -v /opt/code_analysis/:/opt/code_analysis/ \
--entrypoint /opt/code_analysis/sast_script.sh \
registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit
# For future runs simply run `docker start phpcs-security-audit` to re-analyze
# the PHP repos. You can always edit the $scan_repos in the sast_script.sh file.
SAST scan results
As with any SAST tool, the output can be quite a handful. The reports are
available at /opt/code_analysis/sast_reports/
. For the Damn
Vulnerable Web Application (DVWA), these
results were returned:
- 7 high severity vulnerabilities
- 80 low severity vulnerabilities
- 87 total vulnerabilities
The listing below shows the details of the 7 high severity vulnerabilities.
{
"version": "15.0.7",
"vulnerabilities": [
{
"id": "3ebb204839b890ee7d5259b5861a28a251f3cf527bb91ce93dcd6d6e37214862",
"category": "sast",
"name": "Filesystem function basename() detected with dynamic parameter directly from user input",
"description": "Filesystem function basename() detected with dynamic parameter directly from user input",
"cve": "opt/repos/DVWA/vulnerabilities/upload/source/high.php:PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/upload/source/high.php",
"start_line": 6
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"value": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem"
}
]
},
{
"id": "e3e4402bfa97f19eef757a16e2dcc7b976a7f9cecb11aae537a3c8bc266257be",
"category": "sast",
"name": "Filesystem function move_uploaded_file() detected with dynamic parameter directly from user input",
"description": "Filesystem function move_uploaded_file() detected with dynamic parameter directly from user input",
"cve": "opt/repos/DVWA/vulnerabilities/upload/source/low.php:PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/upload/source/low.php",
"start_line": 9
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"value": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem"
}
]
},
{
"id": "eb1c249548a5a9eb970fafe34d3aba706df7ca6f28d2cd1d44d4d6f0888f584f",
"category": "sast",
"name": "Filesystem function basename() detected with dynamic parameter directly from user input",
"description": "Filesystem function basename() detected with dynamic parameter directly from user input",
"cve": "opt/repos/DVWA/vulnerabilities/upload/source/low.php:PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/upload/source/low.php",
"start_line": 6
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"value": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem"
}
]
},
{
"id": "9874685197baa59a2a5b26d6bf3b2af935bf4967b8d91a812d8f099a50a1e797",
"category": "sast",
"name": "Filesystem function basename() detected with dynamic parameter directly from user input",
"description": "Filesystem function basename() detected with dynamic parameter directly from user input",
"cve": "opt/repos/DVWA/vulnerabilities/upload/source/medium.php:PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/upload/source/medium.php",
"start_line": 6
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"value": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem"
}
]
},
{
"id": "3102c84676fab5cf9e5a34c5d183112ae9c3b5270f44d6dcb55c0a7acc63649f",
"category": "sast",
"name": "Filesystem function move_uploaded_file() detected with dynamic parameter directly from user input",
"description": "Filesystem function move_uploaded_file() detected with dynamic parameter directly from user input",
"cve": "opt/repos/DVWA/vulnerabilities/upload/source/medium.php:PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/upload/source/medium.php",
"start_line": 18
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem",
"value": "PHPCS_SecurityAudit.BadFunctions.FilesystemFunctions.ErrFilesystem"
}
]
},
{
"id": "0f3169524cf4c57cf08947d8f06beb765e4f60168ef89811aff2d5149890ca9c",
"category": "sast",
"name": "Please do not use eval() functions",
"description": "Please do not use eval() functions",
"cve": "opt/repos/DVWA/vulnerabilities/view_help.php:PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/view_help.php",
"start_line": 22
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals",
"value": "PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals"
}
]
},
{
"id": "be6fbfc48621ec0230cac67cb104da3d9629583f040d7d3b91b1670f91359364",
"category": "sast",
"name": "Please do not use eval() functions",
"description": "Please do not use eval() functions",
"cve": "opt/repos/DVWA/vulnerabilities/view_help.php:PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals",
"severity": "High",
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2"
},
"location": {
"file": "opt/repos/DVWA/vulnerabilities/view_help.php",
"start_line": 20
},
"identifiers": [
{
"type": "phpcs_security_audit_source",
"name": "PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals",
"value": "PHPCS_SecurityAudit.BadFunctions.NoEvals.NoEvals"
}
]
},
],
"dependency_files": [],
"scan": {
"analyzer": {
"id": "phpcs-security-audit",
"name": "phpcs-security-audit v2",
"url": "https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit",
"vendor": {
"name": "GitLab"
},
"version": "4.1.5"
},
"scanner": {
"id": "phpcs_security_audit",
"name": "phpcs-security-audit v2",
"url": "https://github.com/FloeDesignTechnologies/phpcs-security-audit",
"vendor": {
"name": "GitLab"
},
"version": "2.0.1"
},
"type": "sast",
"start_time": "2024-03-27T12:06:01",
"end_time": "2024-03-27T12:06:01",
"status": "success"
}
}