Testing & Mocking

API Security Testing: OWASP ZAP, Burp Suite, and Automated Scanning

How to test APIs for security vulnerabilities — OWASP ZAP automated scanning, Burp Suite manual testing, injection attacks, and authentication bypass testing.

API Security Testing Scope

API security testing is not the same as web application security testing. APIs expose business logic more directly, often return richer data, and are attacked by automated scripts rather than humans in browsers.

The OWASP API Security Top 10 defines the most critical API vulnerabilities:

RankVulnerabilityExample
API1Broken Object Level Authorization (BOLA)User A accesses User B's data via /api/orders/456
API2Broken AuthenticationWeak tokens, missing expiry, no brute-force protection
API3Broken Object Property Level AuthMass assignment, exposing internal fields
API4Unrestricted Resource ConsumptionNo rate limiting, large payloads accepted
API5Broken Function Level AuthorizationRegular users can call admin endpoints
API6Unrestricted Access to Sensitive Business FlowsBot-accessible purchase flows
API7Server-Side Request Forgery (SSRF)API fetches attacker-controlled URLs
API8Security MisconfigurationDebug endpoints exposed, verbose errors
API9Improper Inventory ManagementUndocumented endpoints left accessible
API10Unsafe Consumption of APIsTrusting upstream APIs without validation

OWASP ZAP

OWASP ZAP (Zed Attack Proxy) is a free, open-source security scanner that works well for automated API scanning in CI pipelines.

API Scan via Docker

# API scan using OpenAPI spec
docker run --rm \
  -v $(pwd):/zap/wrk \
  ghcr.io/zaproxy/zaproxy:stable \
  zap-api-scan.py \
  -t http://host.docker.internal:8000/openapi.yaml \
  -f openapi \
  -r zap-report.html \
  -J zap-report.json

ZAP in CI (GitHub Actions)

- name: Start API
  run: docker compose up -d api

- name: ZAP API Scan
  uses: zaproxy/[email protected]
  with:
    target: http://localhost:8000/openapi.yaml
    format: openapi
    fail_action: true
    rules_file_name: .zap/rules.tsv  # suppress known false positives
    cmd_options: '-a'  # include alpha active scan rules

- name: Upload ZAP report
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: zap-report
    path: report_html.html

Suppressing False Positives

Create .zap/rules.tsv to suppress rules that don't apply:

# Rule ID	Threshold	Comment
10096	OFF	Timestamp disclosure is acceptable for our API
90005	OFF	CSP not applicable (JSON API, no HTML)

Burp Suite

Burp Suite (Community or Professional) is the industry-standard tool for manual API security testing. It acts as an intercepting proxy between your test client and the API.

Setup

  • Configure your HTTP client to proxy through Burp (default: 127.0.0.1:8080)
  • Import your OpenAPI spec via Target > Import > From URL
  • Browse or script API calls — all traffic appears in Proxy > HTTP history

Repeater for Manual Testing

# Capture this request in Burp Proxy, send to Repeater:
GET /api/orders/1234 HTTP/1.1
Host: api.example.com
Authorization: Bearer user-a-token

# Modify the order ID to another user's order:
GET /api/orders/5678 HTTP/1.1  ← User B's order
Host: api.example.com
Authorization: Bearer user-a-token  ← Still User A's token

# If you get 200, you have a BOLA vulnerability.
# Expected: 403 Forbidden

Intruder for Fuzzing

Burp Intruder automates fuzzing attack payloads. For API testing:

POST /api/login HTTP/1.1
Content-Type: application/json

{"email": "§[email protected]§", "password": "§password§"}

Set payload positions around § markers. Intruder will try each payload and show which ones return 200 (success) vs 401 (failure), revealing weak credentials.

Testing BOLA (Broken Object Level Authorization)

BOLA is the most common API vulnerability. Write explicit tests:

import pytest
from django.test import TestCase
from myapp.models import User, Order

class BOLATests(TestCase):
    def setUp(self):
        self.user_a = User.objects.create_user('alice', password='pass')
        self.user_b = User.objects.create_user('bob', password='pass')
        self.order_b = Order.objects.create(user=self.user_b, total=9999)

    def test_user_a_cannot_access_user_b_order(self):
        self.client.force_login(self.user_a)
        response = self.client.get(f'/api/orders/{self.order_b.id}/')
        # Must return 403 or 404 — NOT 200
        self.assertIn(response.status_code, [403, 404])

    def test_user_a_cannot_delete_user_b_order(self):
        self.client.force_login(self.user_a)
        response = self.client.delete(f'/api/orders/{self.order_b.id}/')
        self.assertIn(response.status_code, [403, 404])
        self.assertTrue(Order.objects.filter(pk=self.order_b.pk).exists())

Testing Mass Assignment

def test_user_cannot_set_admin_flag_via_api():
    self.client.force_login(self.regular_user)
    response = self.client.patch('/api/profile/', {
        'name': 'Hacker',
        'is_admin': True,    # should be ignored
        'credits': 99999,   # should be ignored
    }, content_type='application/json')
    # Request might succeed (200) but the sensitive fields must not change
    assert response.status_code in (200, 400)
    self.regular_user.refresh_from_db()
    assert self.regular_user.is_admin is False
    assert self.regular_user.credits == 0  # unchanged

Automation Pipeline

A practical API security pipeline:

# Layer 1: Pre-commit (fast, developer machine)
# - bandit (Python SAST)
# - semgrep (pattern matching for common vulnerabilities)

# Layer 2: CI (each PR)
# - ZAP API scan against staging
# - Explicit BOLA/auth tests in test suite

# Layer 3: Scheduled (weekly/nightly)
# - Full Burp Suite scan (if Pro)
# - Dependency audit (pip-audit, npm audit)

steps:
  - name: SAST
    run: |
      pip install bandit semgrep
      bandit -r myapp/ -ll
      semgrep --config=p/python --config=p/owasp-top-ten .

  - name: Dependency audit
    run: pip-audit --require-hashes -r requirements.txt

Security testing is not a one-time audit — it should be woven into every PR and every deployment cycle. Automated scanning catches the low-hanging fruit; manual testing and explicit authorization tests catch the vulnerabilities that matter most.

Protocolos relacionados

Termos do glossário relacionados

Mais em Testing & Mocking