id: waf-detect-aws-waf
info:
  name: AWS WAF Detection
  author: waftester
  severity: info
  description: |
    Detects AWS WAF, AWS Shield, and AWS CloudFront presence via response
    headers, error pages, and blocking behavior. Identifies x-amzn headers,
    CloudFront distribution IDs, and AWS WAF block responses.
  reference:
    - https://docs.aws.amazon.com/waf/latest/developerguide/
    - https://github.com/0xInfection/Awesome-WAF
  tags: waf,detection,aws,shield,cloudfront,fingerprint,waftester
  classification:
    cwe-id:
      - CWE-200
  metadata:
    verified: true
    max-request: 2
    shodan-query: "http.headers.x-amz"
    fofa-query: "header=\"x-amzn\""

http:
  - method: GET
    path:
      - "{{BaseURL}}/"

    stop-at-first-match: true
    matchers-condition: or
    matchers:
      - type: word
        part: header
        words:
          - "x-amzn-requestid"
          - "x-amz-cf-id"
          - "x-amz-cf-pop"
          - "x-amzn-waf"
          - "x-amz-id-2"
          - "x-amz-request-id"
          - "x-amzn-trace-id"
          - "x-amz-apigw-id"
          - "x-amzn-remapped-"
        condition: or
        case-insensitive: true

      - type: regex
        part: header
        regex:
          - "(?i)server:\\s*(CloudFront|AmazonS3|awselb)"
          - "(?i)x-amz-cf-id:\\s*[A-Za-z0-9_=-]+"
          - "(?i)x-cache:\\s*(Miss|Hit) from cloudfront"
          - "(?i)via:\\s*.*\\.cloudfront\\.net"

      - type: word
        part: body
        words:
          - "Request blocked"
          - "AWS WAF"
          - "awswaf"
          - "x-amzn-waf"
          - "AWSALB"
          - "Generated by cloudfront"
        condition: or
        case-insensitive: true

      - type: word
        part: header
        words:
          - "AWSALB"
          - "AWSALBCORS"
          - "awselb"
          - "AWSALBTG"
        condition: or
        case-insensitive: true

    extractors:
      - type: kval
        kval:
          - x-amzn-requestid
          - x-amz-cf-id
          - server
          - x-amz-cf-pop

      - type: regex
        part: header
        group: 1
        regex:
          - "(?i)x-amz-cf-pop:\\s*([A-Z]{3}[0-9]+-[A-Z0-9]+)"

  # Trigger WAF block to confirm active protection
  - method: GET
    path:
      - "{{BaseURL}}/?<script>alert(1)</script>"

    matchers-condition: or
    matchers:
      - type: word
        part: body
        words:
          - "Request blocked"
          - "AWS WAF"
          - "This request has been blocked"
          - "If you believe this is an error"
        condition: or
        case-insensitive: true

      - type: dsl
        dsl:
          - "status_code == 403 && (contains(tolower(body), 'aws') || contains(tolower(body), 'request blocked'))"

    extractors:
      - type: regex
        part: body
        regex:
          - "(?i)(requestid|request.id).*?([a-f0-9-]{36})"