Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ipfs/kubo
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a105b2f68062
Choose a base ref
...
head repository: ipfs/kubo
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e0fe22da4d9c
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Jul 29, 2015

  1. fix API handler to respect referer + exit on CORS

    this commit makes the API handler short circuit the request if the
    CORS headers say its not allowed. (the CORS handler only sets the
    headers, but does not short-circuit)
    
    It also makes the handler respect the referer again. See security
    discussion at #1532
    
    License: MIT
    Signed-off-by: Juan Batiz-Benet <juan@benet.ai>
    jbenet committed Jul 29, 2015
    Copy the full SHA
    cd8a281 View commit details
  2. more serious CORS tests.

    this commit introduces more serious CORS tests that check
    status response codes, and run real HTTP requests.
    
    License: MIT
    Signed-off-by: Juan Batiz-Benet <juan@benet.ai>
    jbenet committed Jul 29, 2015

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e0fe22d View commit details
Showing with 408 additions and 54 deletions.
  1. +63 −0 commands/http/handler.go
  2. +309 −50 commands/http/handler_test.go
  3. +3 −3 core/corehttp/commands.go
  4. +33 −1 core/mock/mock.go
63 changes: 63 additions & 0 deletions commands/http/handler.go
Original file line number Diff line number Diff line change
@@ -45,6 +45,13 @@ const (
applicationJson = "application/json"
applicationOctetStream = "application/octet-stream"
plainText = "text/plain"
originHeader = "origin"
)

const (
ACAOrigin = "Access-Control-Allow-Origin"
ACAMethods = "Access-Control-Allow-Methods"
ACACredentials = "Access-Control-Allow-Credentials"
)

var localhostOrigins = []string{
@@ -115,6 +122,13 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Debug("Incoming API request: ", r.URL)

if !allowOrigin(r, i.cfg) || !allowReferer(r, i.cfg) {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("403 - Forbidden"))
log.Warningf("API blocked request to %s. (possible CSRF)", r.URL)
return
}

req, err := Parse(r, i.root)
if err != nil {
if err == ErrNotFound {
@@ -311,3 +325,52 @@ func sanitizedErrStr(err error) string {
s = strings.Split(s, "\r")[0]
return s
}

// allowOrigin just stops the request if the origin is not allowed.
// the CORS middleware apparently does not do this for us...
func allowOrigin(r *http.Request, cfg *ServerConfig) bool {
origin := r.Header.Get("Origin")
for _, o := range cfg.CORSOpts.AllowedOrigins {
if o == "*" { // ok! you asked for it!
return true
}

if o == origin { // allowed explicitly
return true
}
}

return false
}

// allowReferer this is here to prevent some CSRF attacks that
// the API would be vulnerable to. We check that the Referer
// is allowed by CORS Origin (origins and referrers here will
// work similarly in the normla uses of the API).
// See discussion at https://github.com/ipfs/go-ipfs/issues/1532
func allowReferer(r *http.Request, cfg *ServerConfig) bool {
referer := r.Referer()

// curl, or ipfs shell, typing it in manually, or clicking link
// NOT in a browser. this opens up a hole. we should close it,
// but right now it would break things. TODO
if referer == "" {
return true
}

// check CORS ACAOs and pretend Referer works like an origin.
// this is valid for many (most?) sane uses of the API in
// other applications, and will have the desired effect.
for _, o := range cfg.CORSOpts.AllowedOrigins {
if o == "*" { // ok! you asked for it!
return true
}

// referer is allowed explicitly
if o == referer {
return true
}
}

return false
}
Loading