go-restful icon indicating copy to clipboard operation
go-restful copied to clipboard

[security] Path parser inconsistency could lead to bypass several security checks in emicklei/go-restful

Open JamieSlome opened this issue 2 years ago • 21 comments

Reported via huntr.dev here.

Created: May 28th 2022

Description

There is a inconsistency between how golang(and other packages) and go-restful parses url path. This incosistency could lead several security check bypass in a complex system.

Steps to reproduce

Copy and run the code below

package main

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

func main() {

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    })

// If a user request matches with this path then it will be checked and if it didn't match then the request will be directly forwarded to the go-restful server.
    http.HandleFunc("/users/id_will_be_here", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info")
    })

    log.Fatal(http.ListenAndServe(":8081", nil))

}

Now If you send a request to the http://localhost:8081/users/id_will_be_here then you will get a hit to the expected endpoint and it will check the authorization part Now if you send a request to the http://localhost:8081/users/id_will_be_here/ (notice the extra / in last) then this server won't process this request as the path name doesn't match but the problem is that go-restful treat this path and the previous as same. So this inconsistency could lead some issues in this scenerio as the first sever wont check the security checks but the second server(go-restful) will return user data.

Impact

Security check bypass

Occurrences

web_service.go L80

JamieSlome avatar May 30 '22 09:05 JamieSlome

Thank you for reporting this. I will investigate this further.

emicklei avatar Jun 02 '22 20:06 emicklei

i was able to reproduce this issue.

your example output

~/tmp/issue497
$ curl http://localhost:8081/users/id_will_be_here
I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info

emicklei@Ernests-iMac-10 on Sat Jun 04 at 10:35 AM
~/tmp/issue497
$ curl http://localhost:8081/users/id_will_be_here/
Hello, "/users/id_will_be_here/"

go-restful example:

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"

	restful "github.com/emicklei/go-restful/v3"
)

func main() {
	ws := new(restful.WebService)
	ws.Route(ws.GET("/").To(hello))
	ws.Route(ws.GET("/users/id_will_be_here").To(check))
	restful.Add(ws)
	log.Fatal(http.ListenAndServe(":8081", nil))
}

func hello(req *restful.Request, resp *restful.Response) {
	fmt.Fprintf(resp, "Hello, %q", html.EscapeString(req.Request.URL.Path))
}

func check(req *restful.Request, resp *restful.Response) {
	fmt.Fprintf(resp, "I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info")
}

go-restful output:

~/tmp/issue497
$ curl http://localhost:8081/users/id_will_be_here/
I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info

emicklei@Ernests-iMac-10 on Sat Jun 04 at 10:39 AM
~/tmp/issue497
$ curl http://localhost:8081/users/id_will_be_here
I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info

emicklei avatar Jun 04 '22 08:06 emicklei

here, the slash is trimmed

https://github.com/emicklei/go-restful/blob/c2c010a8bf168730835fc945ba2f2d01bc764fe2/route.go#L167

now the problem is that change this code will break existing behavior ; client of the package may be affected negatively. So I am thinking about added a feature flag to disable the trimming and by default this is set to false. Only when it is explicitly set to true then the behavior is conform the standard route matching. This of course need to be documented.

emicklei avatar Jun 04 '22 08:06 emicklei

@emicklei May I know any update on this? As OTEL has used this package, it's affecting many other users using OTEL images. thanks! OTEL Link

Report from Security scanning tools: github.com/emicklei/go-restful/v3 module from all versions is vulnerable to Authentication Bypass by Primary Weakness. There is an inconsistency in how go-restful parses URL paths. This inconsistency could lead several security check bypass in a complex system.

starzhanganz avatar Sep 19 '22 06:09 starzhanganz

Hello guys,

Is there any update on this?

codechris1 avatar Sep 30 '22 01:09 codechris1

hi all, sorry for the delay. I will add this feature flag as mentioned. Will that suffice?

emicklei avatar Sep 30 '22 06:09 emicklei

After the change, two test fail. Need to check if the test was correct in the first place

--- FAIL: Test_matchesRouteByPathTokens (0.00s)
--- FAIL: TestMatchesPath_VarOnFront (0.00s)

emicklei avatar Sep 30 '22 17:09 emicklei

please check https://github.com/emicklei/go-restful/pull/511

emicklei avatar Sep 30 '22 18:09 emicklei

@JamieSlome i believe the PR will fix the reported issue

emicklei avatar Oct 03 '22 19:10 emicklei

@benharvie

JamieSlome avatar Oct 04 '22 08:10 JamieSlome

Looks like the PR is still not merged yet, probably due to the code test coverage filed? Appreciate any update on this!

starzhanganz avatar Oct 18 '22 02:10 starzhanganz

PRISMA-2022-0227. The fix or an ETA is appreciated.

dvasilen avatar Nov 03 '22 13:11 dvasilen

Should this PR be closed since PR #511 has been merged?

jnewfield avatar Nov 10 '22 19:11 jnewfield

PRISMA-2022-0227. The fix or an ETA is appreciated.

hi. did the fix for this issue address PRISMA-2022-0227? a scan against v3.10.1 suggests the vulnerability is still here (?).

jimmyseto avatar Nov 22 '22 14:11 jimmyseto

I'm not sure this is a bypass. Yes, go-restful handles trailing slashes differently than net/http, but how could a bypass realistically occur? From above go-restful example,


// called from ws.Route(ws.GET("/users/id_will_be_here").To(check))
func check(req *restful.Request, resp *restful.Response) {
	fmt.Fprintf(resp, "I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info")
}

The presence or absence of the trailing / won't cause the authorization check to be skipped, or the wrong route to be selected. I'm trying to think of a realistic example where it would, and I can't.

brutif avatar Nov 22 '22 20:11 brutif

Is there a CVE assigned to this bug?

sam-trace avatar Jul 28 '23 10:07 sam-trace

Hey @emicklei - sorry to resurrect an old issue, but there has been a surprising amount of noise in the Go community around this - particularly due to the fact that Prisma cloud is reporting this as a high severity issue and the decision to not upgrade this dependency by some members of the k8s community (which I personally think is quite reasonable).

I'm in agreement with @brutif above, I'm struggling to see how this bug would ever constitute a security vulnerability. Barring a very bespoke authorization system, I can't imagine a situation in which this issue could reasonably be considered a vulnerability. The code example provided in this issue feels contrived, and to me only demonstrates unusual/unexpected behavior. It takes quite a leap of logic to consider that behavior to be a security vulnerability, in my opinion.

I'm wondering, as the maintainer of this project, do you consider this to be a valid vulnerability? If you do not think it is, and are willing to indicate so publicly in this issue, I'd be happy to open a case with Palo Alto to see if we can have the prisma-2022-0227 vulnerability removed from their database.

Thank you!

eastebry avatar Mar 26 '24 23:03 eastebry

hi @eastebry , thank you for notifying me about this ongoing discussion. I need to spent some time on reading the status and reasons for not upgrading (btw the breaking change was reverted in a later release). I will get back to this issue later.

emicklei avatar Mar 28 '24 20:03 emicklei