-
Notifications
You must be signed in to change notification settings - Fork 4
Security Testing Methodologies
Security testing is a critical part of application development that helps identify and address vulnerabilities before attackers can exploit them. This guide covers comprehensive security testing methodologies, tools, and best practices for web applications.
Test Type | Description | When to Use |
---|---|---|
Vulnerability Assessment | Scan for known vulnerabilities | Regularly throughout development |
Penetration Testing | Simulate attacks to exploit vulnerabilities | Pre-release, major changes |
Static Application Security Testing (SAST) | Analyze source code for security issues | During development, CI/CD |
Dynamic Application Security Testing (DAST) | Test running applications for vulnerabilities | Integration testing, staging |
Interactive Application Security Testing (IAST) | Combine SAST and DAST | Advanced CI/CD pipelines |
Software Composition Analysis (SCA) | Analyze dependencies for vulnerabilities | Throughout development |
Security Code Review | Manual review of code for security issues | Critical security components |
Similar to the test pyramid, security testing should follow a structured approach:
/\
/ \
/ \ Manual Penetration Testing
/ \
/________\ DAST / API Security Testing
| |
| | IAST / Fuzzing
|________|
| |
| | SAST / SCA / Secret Scanning
|________|
- Base layers: Automated, fast, frequent (SAST, SCA)
- Middle layers: Semi-automated, targeted (IAST, API testing)
- Top layers: Manual, expert-driven (penetration testing)
OWASP ZAP is a free, open-source security tool for finding vulnerabilities in web applications.
# Install ZAP via Docker
docker pull owasp/zap2docker-stable
Run automated scan
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-baseline.py
-t https://example.com -g gen.conf -r testreport.html
# .github/workflows/zap-scan.yml
name: OWASP ZAP Integration
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 0 * * 0' # Weekly scan
jobs:
zap_scan:
runs-on: ubuntu-latest
name: Scan the application
steps:
- name: Checkout
uses: actions/checkout@v2
- name: ZAP Scan
uses: zaproxy/action-baseline@v0.7.0
with:
target: 'https://staging.example.com'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a'
Nuclei is a fast, template-based vulnerability scanner focusing on extensive coverage.
# Install Nuclei
GO111MODULE=on go get -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei
Run scan with common vulnerabilities
nuclei -u https://example.com -t nuclei-templates/
Use specific templates
nuclei -u https://example.com -t nuclei-templates/cves/ -t nuclei-templates/vulnerabilities/
Generate HTML report
nuclei -u https://example.com -t nuclei-templates/ -o report.html -me html
# Run SonarQube with Docker
docker run -d --name sonarqube -p 9000:9000 sonarqube:latest
Run SonarScanner for JavaScript project
docker run --rm -e SONAR_HOST_URL="http://localhost:9000"
-v "$(pwd):/usr/src"
sonarsource/sonar-scanner-cli
-Dsonar.projectKey=my-project
-Dsonar.sources=.
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
SonarQube configuration file (sonar-project.properties):
# Project settings
sonar.projectKey=my-project
sonar.projectName=My Project
sonar.projectVersion=1.0
Path to source directories
sonar.sources=src
sonar.tests=tests
Exclude files from analysis
sonar.exclusions=node_modules/,/.spec.ts,**/.test.ts
Language
sonar.language=js
sonar.javascript.lcov.reportPaths=coverage/lcov.info
Encoding of the source files
sonar.sourceEncoding=UTF-8
Security-focused rules
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=*
sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.test.js
# Install ESLint security plugins
npm install eslint eslint-plugin-security --save-dev
ESLint configuration (.eslintrc.js):
module.exports = {
'plugins': [
'security'
],
'extends': [
'plugin:security/recommended'
],
'rules': {
'security/detect-buffer-noassert': 'error',
'security/detect-child-process': 'error',
'security/detect-disable-mustache-escape': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-no-csrf-before-method-override': 'error',
'security/detect-non-literal-fs-filename': 'error',
'security/detect-non-literal-regexp': 'error',
'security/detect-non-literal-require': 'error',
'security/detect-object-injection': 'error',
'security/detect-possible-timing-attacks': 'error',
'security/detect-pseudoRandomBytes': 'error',
'security/detect-unsafe-regex': 'error'
}
};
Semgrep is a lightweight static analysis tool for finding bugs and enforcing code standards.
# Install Semgrep
pip install semgrep
Run scan with security rules
semgrep --config=p/security-audit src/
Scan with specific ruleset
semgrep --config=p/owasp-top-ten src/
Generate JSON report
semgrep --config=p/security-audit --json > security-report.json
Custom Semgrep rule for finding hardcoded secrets:
# .semgrep/hardcoded-secrets.yml
rules:
- id: hardcoded-api-key
pattern: |
$X = "sk_live_"
message: "Hardcoded API key detected"
languages: [javascript, typescript, python]
severity: ERROR
- id: hardcoded-jwt-secret
patterns:
- pattern-either:
- pattern: |
$JWT_SECRET = "..."
- pattern: |
$JWT_KEY = "..."
message: "Hardcoded JWT secret detected"
languages: [javascript, typescript, python]
severity: ERROR
# Run ZAP Active Scan (more thorough than baseline)
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-full-scan.py \
-t https://staging.example.com -g gen.conf -r full-report.html
Scan with authentication
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-full-scan.py
-t https://staging.example.com
-z "auth.loginurl=https://staging.example.com/login
auth.username=test@example.com
auth.password=Password123
auth.auto=true"
-r authenticated-report.html
# Create an OpenAPI definition file (openapi.json)
# Then use it to test the API
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-api-scan.py \
-t https://api.example.com -f openapi -f openapi.json \
-r api-report.html
# Run Dependency Check with Docker
docker run --rm \
-v $(pwd):/src \
-v $(pwd)/reports:/report \
owasp/dependency-check \
--scan /src \
--format "HTML" \
--project "My Project" \
--out /report
# Install Snyk
npm install -g snyk
Authenticate
snyk auth
Test for vulnerabilities
snyk test
Test with JSON output
snyk test --json > snyk-results.json
Monitor project continuously
snyk monitor
Fix vulnerabilities where possible
snyk wizard
// Newman (Postman CLI) with fuzzing collection
const newman = require('newman');
// Load fuzzing data
const fuzzingData = require('./fuzzing-data.json');
// For each fuzzing test case
fuzzingData.forEach(testCase => {
newman.run({
collection: require('./api-collection.json'),
environment: require('./environment.json'),
iterationData: [testCase],
reporters: ['cli', 'json'],
reporter: {
json: {
export: ./reports/fuzzing-${testCase.name}.json
}
}
}, function (err) {
if (err) { throw err; }
console.log(Completed fuzzing test: ${testCase.name}
);
});
});
Example fuzzing test cases (fuzzing-data.json):
[
{
"name": "sql-injection",
"endpoint": "/api/users",
"input": {
"username": "admin' OR 1=1--",
"email": "test@example.com"
}
},
{
"name": "xss-attack",
"endpoint": "/api/comments",
"input": {
"content": "<script>alert('XSS')</script>"
}
},
{
"name": "nosql-injection",
"endpoint": "/api/products",
"input": {
"id": {"$gt": ""}
}
}
]
American Fuzzy Lop (AFL++) is a powerful fuzzing tool:
# Install AFL++
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make
sudo make install
Instrument your program
afl-gcc -o my_program my_program.c
Start fuzzing
afl-fuzz -i input_dir -o output_dir -- ./my_program @@
The OWASP Testing Guide provides a comprehensive methodology for web application penetration testing:
-
Information Gathering
- Identify IP ranges, domains, technologies
- Fingerprint web servers, frameworks
- Map application architecture
-
Configuration Management Testing
- Test file extensions handling
- Review old/backup files
- Check for security headers
- Test HTTP methods
-
Authentication Testing
- Test credential transport
- Check default/weak credentials
- Test authentication bypasses
- Test session management
-
Authorization Testing
- Test path traversal
- Test for privilege escalation
- Check for insecure direct object references
-
Session Management Testing
- Test session fixation
- Check cookie attributes
- Test session timeout
-
Data Validation Testing
- Test for SQL injection
- Cross-site scripting (XSS)
- CSRF vulnerabilities
- Command injection
-
Denial of Service Testing
- Resource consumption
- User lockout
- Distributed testing
-
Business Logic Testing
- Test workflows and workflows bypasses
- Test for abuse of functionality
-
Client-side Testing
- DOM-based vulnerabilities
- JavaScript execution
- Local storage issues
# Start Metasploit
msfconsole
Web application scanning
use auxiliary/scanner/http/dir_scanner
set RHOSTS target.example.com
set THREADS 10
run
Vulnerability scanning
use auxiliary/scanner/http/wordpress_scanner
set RHOSTS blog.example.com
run
Burp Suite workflow (manual steps):
- Set up proxy and capture requests
- Spider the target application
- Use the Active Scanner on found endpoints
- Manual verification of discovered issues
- Exploitation of confirmed vulnerabilities
- Report generation
# .github/workflows/security.yml
name: Security Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
schedule:
- cron: '0 0 * * 0' # Weekly scan
jobs:
security-sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: p/security-audit
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Snyk Test
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'My Project'
path: '.'
format: 'HTML'
out: 'reports'
args: >
--suppression suppression.xml
dynamic-testing:
runs-on: ubuntu-latest
needs: [security-sast, dependency-check]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Deploy to Testing
run: ./deploy-to-test.sh
- name: ZAP API Scan
uses: zaproxy/action-api-scan@v0.1.0
with:
target: 'https://test-api.example.com'
api_definition: 'openapi.json'
format: 'json'
fail_action: false
- name: Upload Security Reports
uses: actions/upload-artifact@v2
with:
name: security-reports
path: reports/
# .gitlab-ci.yml
stages:
- build
- test
- sast
- dast
- deploy
variables:
DOCKER_DRIVER: overlay2
SAST_ANALYZER_IMAGE: gitlab/gitlab-sast:latest
DAST_ANALYZER_IMAGE: gitlab/gitlab-dast:latest
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/DAST.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
Enable SAST analyzers
sast:
variables:
SAST_EXCLUDED_PATHS: "node_modules, dist, coverage, vendor"
SCAN_KUBERNETES_MANIFESTS: "true"
Custom dependency scanning
dependency_scanning:
variables:
DS_EXCLUDED_PATHS: "test, tests, spec, specs"
DAST configuration
dast:
variables:
DAST_WEBSITE: https://staging.example.com
DAST_FULL_SCAN_ENABLED: "true"
DAST_ZAP_USE_AJAX_SPIDER: "true"
DAST_AUTH_URL: https://staging.example.com/login
DAST_USERNAME: test@example.com
DAST_PASSWORD: $DAST_PASSWORD
DAST_USERNAME_FIELD: "email"
DAST_PASSWORD_FIELD: "password"
artifacts:
paths:
- gl-dast-report.json
Custom security job
custom_security_scan:
stage: sast
image: python:3.9
script:
- pip install semgrep
- semgrep --config=p/security-audit --json > semgrep-report.json
artifacts:
paths:
- semgrep-report.json
# Security Vulnerability Report
Summary
-
Vulnerability: SQL Injection in User Search API
-
Severity: Critical (CVSS 9.8)
-
Affected Component: /api/v1/users/search endpoint
-
Status: Confirmed
-
Discovered: 2023-04-15
-
Reported: 2023-04-16
Description
The user search API endpoint is vulnerable to SQL injection attacks through the 'name' parameter. This allows an attacker to execute arbitrary SQL commands against the database.
Proof of Concept
Request:
GET /api/v1/users/search?name=test' OR 1=1--
Response:
```json
{
"users": [
{"id": 1, "name": "Admin User", "email": "admin@example.com"},
{"id": 2, "name": "Test User", "email": "test@example.com"},
...
]
}
An attacker can:
- Access sensitive user data
- Potentially modify or delete database contents
- Potentially execute code on the database server
- Implement parameterized queries for all database operations
- Validate and sanitize all user inputs
- Implement proper error handling to prevent information disclosure
// BEFORE (vulnerable)
const query = `SELECT * FROM users WHERE name LIKE '%${name}%'`;
// AFTER (secure)
const query = SELECT * FROM users WHERE name LIKE $1
;
const params = [%${name}%
];