Skip to content

CORS: unconditionally reflecting Origin in Access-Control-Allow-Origin is insecure #2400

Description

@jub0bs

Issue Description

Echo's CORS middleware actively bypasses the so-called wildcard exception: if developers configure their CORS middleware to allow credentials and specify the wildcard as an allowed origin, the resulting middleware unconditionally reflects the value of the request's Origin header in the Access-Control-Allow-Origin response header.

This is insecure insofar as it exposes users to cross-origin attacks that can be mounted from any origin.

For information, a similar issue was reported to (and subsequently fixed by) other Web frameworks/libraries:

Checklist

  • Dependencies installed
  • No typos
  • Searched existing issues and docs

Expected behaviour

Perhaps the following:

curl -sD - -o /dev/null \
  -H "Origin: https://attacker.org" \
  localhost:8081/hello
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
-snip-

Ideally, though, the resulting middleware should not be built at all, since it is dysfunctional. More about this in my latest blog post.

Actual behaviour

curl -sD - -o /dev/null \
  -H "Origin: https://attacker.org" \
  localhost:8081/hello
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://attacker.org
-snip-

Note the unconditional reflection of the request's Origin header value (https://attacker.org) in the Access-Control-Allow-Origin response header.

Steps to reproduce

  1. Run mkdir wildcardcraziness && cd $_.
  2. Save the program below to main.go.
    1. Run go mod init whatever && go mod tidy.
  3. Run go run main.go.
  4. Run curl -sD - -o /dev/null -H "Origin: https://attacker.org" localhost:8081/hello.

Working code to debug

package main

import (
  "net/http"

  "github.com/labstack/echo/v4"
  "github.com/labstack/echo/v4/middleware"
)

func main() {
  e := echo.New()
  e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
    AllowOrigins:     []string{"*"},
    AllowCredentials: true,
  }))
  e.GET("/hello", hello)
  e.Logger.Fatal(e.Start(":8081"))
}

func hello(c echo.Context) error {
  return c.String(http.StatusOK, "Hello, World!")
}

Version/commit

v4.10.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions