From 7ce444abd0f5b4ca1c93122b9e92769cc716c215 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sat, 4 Apr 2020 01:55:36 +0200 Subject: [PATCH 1/2] HTTP API: Disallow GET requests on API This commit upgrades go-ipfs-cmds and configures the commands HTTP API Handler to only allow POST/OPTIONS, disallowing GET and others in the handling of command requests in the IPFS HTTP API (where before every type of request method was handled, with GET/POST/PUT/PATCH being equivalent). The Read-Only commands that the HTTP API attaches to the gateway endpoint will additional handled GET as they did before (but stop handling PUT,DELETEs). By limiting the request types we address the possibility that a website accessed by a browser abuses the IPFS API by issuing GET requests to it which have no Origin or Referrer set, and are thus bypass CORS and CSRF protections. This is a breaking change for clients that relay on GET requests against the HTTP endpoint (usually :5001). Applications integrating on top of the gateway-read-only API should still work (including cross-domain access). Co-Authored-By: Steven Allen Co-Authored-By: Marcin Rataj This commit was moved from ipfs/kubo@1b490476e5517931b8d31a6636e7008771db201d --- gateway/core/corehttp/commands.go | 18 ++++++++++++------ gateway/core/corehttp/webui.go | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/gateway/core/corehttp/commands.go b/gateway/core/corehttp/commands.go index d63099bfb..0f9b8d603 100644 --- a/gateway/core/corehttp/commands.go +++ b/gateway/core/corehttp/commands.go @@ -117,11 +117,17 @@ func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) { c.SetAllowedOrigins(newOrigins...) } -func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption { +func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool) ServeOption { return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { cfg := cmdsHttp.NewServerConfig() - cfg.SetAllowedMethods(http.MethodGet, http.MethodPost, http.MethodPut) + cfg.AllowGet = allowGet + corsAllowedMethods := []string{http.MethodPost} + if allowGet { + corsAllowedMethods = append(corsAllowedMethods, http.MethodGet) + } + + cfg.SetAllowedMethods(corsAllowedMethods...) cfg.APIPath = APIPath rcfg, err := n.Repo.Config() if err != nil { @@ -140,15 +146,15 @@ func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption { } // CommandsOption constructs a ServerOption for hooking the commands into the -// HTTP server. +// HTTP server. It will NOT allow GET requests. func CommandsOption(cctx oldcmds.Context) ServeOption { - return commandsOption(cctx, corecommands.Root) + return commandsOption(cctx, corecommands.Root, false) } // CommandsROOption constructs a ServerOption for hooking the read-only commands -// into the HTTP server. +// into the HTTP server. It will allow GET requests. func CommandsROOption(cctx oldcmds.Context) ServeOption { - return commandsOption(cctx, corecommands.RootRO) + return commandsOption(cctx, corecommands.RootRO, true) } // CheckVersionOption returns a ServeOption that checks whether the client ipfs version matches. Does nothing when the user agent string does not contain `/go-ipfs/` diff --git a/gateway/core/corehttp/webui.go b/gateway/core/corehttp/webui.go index 21d3eeea6..4a31f719a 100644 --- a/gateway/core/corehttp/webui.go +++ b/gateway/core/corehttp/webui.go @@ -1,7 +1,7 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/Qmexhq2sBHnXQbvyP2GfUdbnY7HCagH2Mw5vUNSBn2nxip" +const WebUIPath = "/ipfs/bafybeihpkhgv3jfnyx5qcexded7agjpwbgvtc3o6lnk6n3cs37fh4xx4fe" // this is a list of all past webUI paths. var WebUIPaths = []string{ @@ -33,6 +33,7 @@ var WebUIPaths = []string{ "/ipfs/QmcjeTciMNgEBe4xXvEaA4TQtwTRkXucx7DmKWViXSmX7m", "/ipfs/QmfNbSskgvTXYhuqP8tb9AKbCkyRcCy3WeiXwD9y5LeoqK", "/ipfs/QmPkojhjJkJ5LEGBDrAvdftrjAYmi9GU5Cq27mWvZTDieW", + "/ipfs/Qmexhq2sBHnXQbvyP2GfUdbnY7HCagH2Mw5vUNSBn2nxip", } var WebUIOption = RedirectOption("webui", WebUIPath) From ecb855b21a5a4722a802632fedb2520e532c4657 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sat, 4 Apr 2020 02:06:06 +0200 Subject: [PATCH 2/2] corehttp: Gateway handler: add Allow headers when returning MethodNotAllowed Spec says that response with 405 must set Allow headers. This commit was moved from ipfs/kubo@73405436159b5953f6ed107f45d7aa3badf4bf44 --- gateway/core/corehttp/gateway_handler.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gateway/core/corehttp/gateway_handler.go b/gateway/core/corehttp/gateway_handler.go index d3c4d2639..d26f21d54 100644 --- a/gateway/core/corehttp/gateway_handler.go +++ b/gateway/core/corehttp/gateway_handler.go @@ -127,6 +127,9 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !i.config.Writable { status = http.StatusMethodNotAllowed errmsg = errmsg + "read only access" + w.Header().Add("Allow", http.MethodGet) + w.Header().Add("Allow", http.MethodHead) + w.Header().Add("Allow", http.MethodOptions) } else { status = http.StatusBadRequest errmsg = errmsg + "bad request for " + r.URL.Path