security-vulnerability-assessment

Security testing methodologies, OWASP Top 10, vulnerability scanning tools, and penetration testing practices

Security: Vulnerability Assessment

Scope: Security testing, OWASP Top 10, scanning tools, pentesting, security audits Lines: ~390 Last Updated: 2025-10-27

When to Use This Skill

Activate this skill when:

OWASP Top 10 (2021)

A01: Broken Access Control

Description: Unauthorized access to resources or actions

Testing:

import requests

def test_broken_access_control():
    """Test for access control vulnerabilities"""

    # Test 1: IDOR (Insecure Direct Object Reference)
    # Try accessing another user's resource
    user1_token = login("user1@example.com", "password")
    user2_id = 42

    response = requests.get(
        f"https://api.example.com/users/{user2_id}/profile",
        headers={"Authorization": f"Bearer {user1_token}"}
    )

    # Should return 403 Forbidden
    assert response.status_code == 403, "IDOR vulnerability detected"

    # Test 2: Path traversal
    response = requests.get(
        "https://api.example.com/files/../../etc/passwd"
    )
    assert response.status_code in [400, 403, 404], "Path traversal possible"

    # Test 3: Privilege escalation
    # Try to access admin endpoint with regular user
    response = requests.get(
        "https://api.example.com/admin/users",
        headers={"Authorization": f"Bearer {user1_token}"}
    )
    assert response.status_code == 403, "Privilege escalation possible"

    # Test 4: Missing authorization check
    # Try to access protected resource without authentication
    response = requests.get("https://api.example.com/admin/dashboard")
    assert response.status_code == 401, "Missing authentication check"

A02: Cryptographic Failures

Description: Weak or missing encryption, exposed sensitive data

Testing:

def test_cryptographic_failures():
    """Test for weak cryptography"""

    # Test 1: Check HTTPS enforcement
    response = requests.get("http://example.com", allow_redirects=False)
    assert response.status_code == 301, "HTTP not redirected to HTTPS"
    assert response.headers['Location'].startswith('https://'), "No HTTPS redirect"

    # Test 2: Check TLS version
    import ssl
    import socket

    context = ssl.create_default_context()
    context.minimum_version = ssl.TLSVersion.TLSv1_2

    with socket.create_connection(("example.com", 443)) as sock:
        with context.wrap_socket(sock, server_hostname="example.com") as ssock:
            version = ssock.version()
            assert version in ["TLSv1.2", "TLSv1.3"], f"Weak TLS: {version}"

    # Test 3: Check for sensitive data in response
    response = requests.get("https://api.example.com/users/me")
    data = response.json()

    # Password should never be in response
    assert 'password' not in data, "Password exposed in response"
    assert 'password_hash' not in data, "Password hash exposed"

    # Test 4: Check cookie security
    response = requests.get("https://example.com")
    cookies = response.cookies

    for cookie in cookies:
        assert cookie.secure, f"Cookie {cookie.name} not secure"
        assert cookie.has_nonstandard_attr('HttpOnly'), f"Cookie {cookie.name} not HttpOnly"

A03: Injection

Description: SQL injection, command injection, XSS

Testing:

def test_sql_injection():
    """Test for SQL injection vulnerabilities"""

    # Test payloads
    # Example SQL injection attack payloads - for security testing only
    payloads = [
        "' OR '1'='1",
        "' OR '1'='1' --",
        "'; DROP TABLE users; --",  # Example of destructive injection payload
        "' UNION SELECT NULL, NULL, NULL --",
        "admin'--",
    ]

    for payload in payloads:
        response = requests.post(
            "https://api.example.com/login",
            json={"username": payload, "password": "test"}
        )

        # Should return error, not success
        assert response.status_code in [400, 401], f"SQL injection with: {payload}"

        # Check error message doesn't leak SQL details
        assert 'SQL' not in response.text.upper(), "SQL error leaked"
        assert 'syntax' not in response.text.lower(), "SQL syntax error leaked"

def test_command_injection():
    """Test for command injection"""

    payloads = [
        "google.com; ls -la",
        "google.com && cat /etc/passwd",
        "google.com | whoami",
        "$(cat /etc/passwd)",
        "`cat /etc/passwd`",
    ]

    for payload in payloads:
        response = requests.get(
            f"https://api.example.com/ping?host={payload}"
        )

        # Should not execute commands
        assert 'root:' not in response.text, f"Command injection: {payload}"
        assert 'bin/bash' not in response.text, f"Command injection: {payload}"

def test_xss():
    """Test for XSS vulnerabilities"""

    payloads = [
        "<script>alert('XSS')</script>",
        "<img src=x onerror=alert('XSS')>",
        "javascript:alert('XSS')",
        "<svg onload=alert('XSS')>",
    ]

    for payload in payloads:
        response = requests.post(
            "https://example.com/comments",
            json={"content": payload}
        )

        # Fetch the comment
        comment_id = response.json()['id']
        response = requests.get(f"https://example.com/comments/{comment_id}")

        # Script tags should be escaped
        assert '<script>' not in response.text, f"XSS vulnerability: {payload}"
        assert 'onerror=' not in response.text, f"XSS vulnerability: {payload}"

A04: Insecure Design

Description: Missing or ineffective control design

Testing:

def test_insecure_design():
    """Test for design flaws"""

    # Test 1: Rate limiting
    for i in range(20):
        response = requests.post(
            "https://api.example.com/login",
            json={"email": "test@example.com", "password": "wrong"}
        )

    # Should be rate limited after multiple attempts
    assert response.status_code == 429, "No rate limiting on auth endpoint"

    # Test 2: Account enumeration
    response1 = requests.post(
        "https://api.example.com/login",
        json={"email": "exists@example.com", "password": "wrong"}
    )

    response2 = requests.post(
        "https://api.example.com/login",
        json={"email": "notexist@example.com", "password": "wrong"}
    )

    # Error messages should be identical
    assert response1.json()['error'] == response2.json()['error'], \
        "Account enumeration possible via error messages"

    # Test 3: Password reset flow
    # Should require email verification
    response = requests.post(
        "https://api.example.com/password-reset",
        json={"email": "victim@example.com"}
    )

    # Should not reveal if email exists
    assert "email sent" in response.json()['message'].lower(), \
        "Password reset reveals account existence"

A05: Security Misconfiguration

Description: Insecure default configs, unnecessary features enabled

Testing:

def test_security_misconfiguration():
    """Test for misconfigurations"""

    # Test 1: Security headers
    response = requests.get("https://example.com")

    required_headers = [
        'Strict-Transport-Security',
        'X-Frame-Options',
        'X-Content-Type-Options',
        'Content-Security-Policy'
    ]

    for header in required_headers:
        assert header in response.headers, f"Missing security header: {header}"

    # Test 2: Exposed debug information
    assert 'X-Powered-By' not in response.headers, "Server info exposed"
    assert 'Server' not in response.headers or \
           'nginx' not in response.headers.get('Server', '').lower(), \
           "Detailed server version exposed"

    # Test 3: Directory listing
    response = requests.get("https://example.com/static/")
    assert 'Index of' not in response.text, "Directory listing enabled"

    # Test 4: Default credentials
    default_creds = [
        ("admin", "admin"),
        ("admin", "password"),
        ("root", "root"),
    ]

    for username, password in default_creds:
        response = requests.post(
            "https://api.example.com/login",
            json={"username": username, "password": password}
        )
        assert response.status_code == 401, f"Default credentials work: {username}"

A06: Vulnerable and Outdated Components

Description: Using components with known vulnerabilities

Testing:

# Python dependencies
pip install safety
safety check

pip install pip-audit
pip-audit

# Node.js dependencies
npm audit
npm audit fix

# Check Docker base images
docker scan myimage:latest

# Use Snyk
snyk test
snyk monitor

# Use Trivy
trivy image myimage:latest
# Automated dependency checking
import requests
import json

def check_dependencies_for_vulnerabilities(requirements_file):
    """Check Python dependencies against OSV database"""

    with open(requirements_file) as f:
        packages = [line.strip() for line in f if line.strip()]

    vulnerabilities = []

    for package in packages:
        name, version = package.split('==')

        response = requests.post(
            'https://api.osv.dev/v1/query',
            json={'package': {'name': name, 'ecosystem': 'PyPI'},
                  'version': version}
        )

        if response.status_code == 200:
            data = response.json()
            if 'vulns' in data and data['vulns']:
                vulnerabilities.append({
                    'package': name,
                    'version': version,
                    'vulnerabilities': data['vulns']
                })

    return vulnerabilities

A07: Identification and Authentication Failures

Description: Weak authentication, session management issues

Testing:

def test_authentication_failures():
    """Test authentication mechanisms"""

    # Test 1: Weak passwords accepted
    weak_passwords = ["password", "12345678", "qwerty", "admin"]

    for pwd in weak_passwords:
        response = requests.post(
            "https://api.example.com/register",
            json={"email": "test@example.com", "password": pwd}
        )
        assert response.status_code == 400, f"Weak password accepted: {pwd}"

    # Test 2: Session fixation
    # Get session ID before login
    session = requests.Session()
    response1 = session.get("https://example.com")
    session_id_before = session.cookies.get('session_id')

    # Login
    session.post("https://example.com/login",
                 json={"email": "user@example.com", "password": "password"})

    # Session ID should change after login
    session_id_after = session.cookies.get('session_id')
    assert session_id_before != session_id_after, "Session fixation vulnerability"

    # Test 3: Brute force protection
    for i in range(10):
        response = requests.post(
            "https://api.example.com/login",
            json={"email": "user@example.com", "password": "wrong"}
        )

    # Should be locked or rate limited
    assert response.status_code in [429, 403], "No brute force protection"

    # Test 4: JWT validation
    # Try using expired token
    expired_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."  # Test token for security validation only
    response = requests.get(
        "https://api.example.com/protected",
        headers={"Authorization": f"Bearer {expired_token}"}
    )
    assert response.status_code == 401, "Expired JWT accepted"

A08-A10: Other OWASP Vulnerabilities

def test_software_data_integrity_failures():
    """A08: Software and Data Integrity Failures"""

    # Test unsigned packages, missing integrity checks
    response = requests.get("https://example.com")
    html = response.text

    # Check for Subresource Integrity (SRI)
    if '<script src="https://cdn' in html:
        assert 'integrity="sha' in html, "Missing SRI for external scripts"

def test_logging_monitoring_failures():
    """A09: Security Logging and Monitoring Failures"""

    # Attempt suspicious activity
    requests.post(
        "https://api.example.com/login",
        json={"email": "' OR '1'='1", "password": "test"}
    )

    # Check if activity is logged (requires access to logs)
    # In practice, verify logging configuration

def test_ssrf():
    """A10: Server-Side Request Forgery"""

    # Try to access internal services
    payloads = [
        "http://localhost:8080",
        "http://127.0.0.1",
        "http://169.254.169.254/latest/meta-data/",  # AWS metadata
        "file:///etc/passwd",
    ]

    for payload in payloads:
        response = requests.post(
            "https://api.example.com/fetch-url",
            json={"url": payload}
        )

        assert response.status_code in [400, 403], f"SSRF possible: {payload}"

Automated Security Scanning Tools

Static Analysis (SAST)

# Python: Bandit
pip install bandit
bandit -r . -f json -o bandit-report.json

# Python: Semgrep
pip install semgrep
semgrep --config=auto --json --output=semgrep-report.json

# Python: Pylint security plugin
pip install pylint-security
pylint --load-plugins=pylint_security myapp/

# Node.js: ESLint with security plugins
npm install --save-dev eslint-plugin-security
eslint . --ext .js,.ts

# Go: Gosec
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec ./...

Dynamic Analysis (DAST)

# OWASP ZAP (Zed Attack Proxy)
docker run -t owasp/zap2docker-stable zap-baseline.py \
    -t https://example.com \
    -r zap-report.html

# Burp Suite (commercial)
# Use for manual penetration testing

# Nikto (web server scanner)
nikto -h https://example.com -o nikto-report.txt

# SQLMap (SQL injection)
sqlmap -u "https://example.com/page?id=1" --batch

# Nuclei (vulnerability scanner)
nuclei -u https://example.com -t cves/

Dependency Scanning (SCA)

# Python: Safety
safety check --json --output safety-report.json

# Python: pip-audit
pip-audit --format json --output pip-audit-report.json

# Node.js: npm audit
npm audit --json > npm-audit-report.json

# Node.js: Snyk
snyk test --json > snyk-report.json

# Docker: Trivy
trivy image myimage:latest --format json --output trivy-report.json

# Docker: Grype
grype myimage:latest -o json > grype-report.json

Container Security

# Scan container image
docker scan myimage:latest

# Trivy comprehensive scan
trivy image --severity HIGH,CRITICAL myimage:latest

# Clair (open source)
docker run -d --name clair arminc/clair-local-scan:latest
clair-scanner myimage:latest

# Anchore Engine
anchore-cli image add myimage:latest
anchore-cli image vuln myimage:latest all

Penetration Testing Methodology

Reconnaissance

import nmap
import requests
from bs4 import BeautifulSoup

def passive_reconnaissance(domain):
    """Gather information without touching target"""

    # DNS lookup
    import dns.resolver
    resolver = dns.resolver.Resolver()

    records = {
        'A': resolver.resolve(domain, 'A'),
        'MX': resolver.resolve(domain, 'MX'),
        'TXT': resolver.resolve(domain, 'TXT'),
    }

    # WHOIS lookup
    import whois
    domain_info = whois.whois(domain)

    # Subdomain enumeration (passive)
    # Use crt.sh (certificate transparency logs)
    response = requests.get(f"https://crt.sh/?q=%.{domain}&output=json")
    subdomains = set()

    if response.status_code == 200:
        for cert in response.json():
            subdomains.add(cert['name_value'])

    return {
        'dns_records': records,
        'whois': domain_info,
        'subdomains': list(subdomains)
    }

def active_reconnaissance(target):
    """Active scanning (requires permission)"""

    # Port scanning
    nm = nmap.PortScanner()
    nm.scan(target, '1-1000')

    open_ports = []
    for host in nm.all_hosts():
        for proto in nm[host].all_protocols():
            ports = nm[host][proto].keys()
            for port in ports:
                if nm[host][proto][port]['state'] == 'open':
                    open_ports.append({
                        'port': port,
                        'service': nm[host][proto][port]['name']
                    })

    return open_ports

Security Testing Checklist

Before Testing:

Authentication:

Authorization:

Input Validation:

Configuration:

Business Logic:

CI/CD Security Integration

GitHub Actions Security Scanning

name: Security Scan

on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Run Bandit (Python SAST)
        run: |
          pip install bandit
          bandit -r . -f json -o bandit-report.json
        continue-on-error: true

      - name: Run Safety (Dependency Check)
        run: |
          pip install safety
          safety check --json --output safety-report.json
        continue-on-error: true

      - name: Run Semgrep
        uses: returntocorp/semgrep-action@v1

      - name: Run Trivy (Container Scan)
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'

      - name: Upload results to GitHub Security
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

Security Best Practices

Security Testing Checklist

Automated Testing:

Manual Testing:

Monitoring:

Level 3 Resources

This skill includes executable scripts, detailed references, and validated examples in the resources/ directory.

๐Ÿ“ Resources Directory Structure

skills/security/vulnerability-assessment/resources/
โ”œโ”€โ”€ REFERENCE.md              # Detailed OWASP Top 10 reference, CVE patterns, tools
โ”œโ”€โ”€ scripts/
โ”‚   โ”œโ”€โ”€ README.md            # Script documentation and usage
โ”‚   โ”œโ”€โ”€ test_owasp_top10.py # Executable OWASP Top 10 test suite
โ”‚   โ””โ”€โ”€ scan_dependencies.sh # Automated dependency vulnerability scanning
โ””โ”€โ”€ examples/
    โ”œโ”€โ”€ python/              # Standalone test examples
    โ””โ”€โ”€ ci-cd/              # CI/CD integration examples

๐Ÿš€ Quick Start: Run Security Tests

Test for OWASP Top 10 vulnerabilities:

# Full test suite
python resources/scripts/test_owasp_top10.py \
    --target https://staging.example.com \
    --report security-report.json \
    --verbose

# Specific test
python resources/scripts/test_owasp_top10.py \
    --target https://staging.example.com \
    --test A01 \
    --verbose

Scan dependencies for vulnerabilities:

# Scan Python project
./resources/scripts/scan_dependencies.sh \
    --project-dir /path/to/project \
    --output scan-results.json

# Scan Docker image
./resources/scripts/scan_dependencies.sh \
    --docker-image myapp:latest \
    --output docker-scan.json

๐Ÿ“š Reference Material

Load detailed reference:

cat resources/REFERENCE.md

Contains:

โš™๏ธ Scripts Overview

| Script | Purpose | On-Demand Context Loading | |--------|---------|--------------------------| | test_owasp_top10.py | Automated OWASP Top 10 testing suite | Run via bash - code never loaded into context | | scan_dependencies.sh | Multi-tool dependency scanner (Safety, pip-audit, npm, Trivy) | Executable script, minimal context | | REFERENCE.md | Detailed specs, CVE examples, tool comparisons | Load only when needed for deep reference |

Benefits of Level 3 Resources:


Related Skills


Last Updated: 2025-10-27 Format Version: 1.0 (Atomic) + Level 3 Resources