gokart icon indicating copy to clipboard operation
gokart copied to clipboard

False positives for SSRF

Open stevenjohnstone opened this issue 4 years ago • 2 comments
trafficstars

Finding gokart really useful so far: nice work!

Using 0.1.0, I see quite a lot of false positives for SSRF. For example,

package bug

import "net/http"

func doSomething(req *http.Request) (*http.Response, error) {
	return http.DefaultClient.Do(req)
}

func DoSomething() (*http.Response, error) {
	req, err := http.NewRequest("GET", "http://example.com", nil)
	if err != nil {
		return nil, err
	}
	return doSomething(req)
}

$ gokart scan
Using default analyzers config found at "~/.gokart/analyzers.yml".

Revving engines VRMMM VRMMM
3...2...1...Go!

(SSRF) Danger: possible SSRF detected

/home/stevie/gokart/bug.go:6
Vulnerable Function: [ doSomething(...) (*net/http.Response, error ]
      5:	func doSomething(req *http.Request) (*http.Response, error) {
    > 6:		return http.DefaultClient.Do(req)
      7:	}

/home/stevie/gokart/bug.go:5
Source of Untrusted Input: [ doSomething(...) (*net/http.Response, error ]
      4:	
    > 5:	func doSomething(req *http.Request) (*http.Response, error) {
      6:		return http.DefaultClient.Do(req)
------------------------------------------------------------------------------

Race Complete! Analysis took 417.122169ms and 81 Go files were scanned (including imported packages)
GoKart found 1 potentially vulnerable functions

It looks like any function which takes an *http.Request as an argument and passes it to Do will be flagged as potentially vulnerable? In the above example, the request url comes from a string literal so isn't tainted.

stevenjohnstone avatar Aug 19 '21 10:08 stevenjohnstone

Hey @stevenjohnstone, thanks for the issue submission. We're glad that you're finding gokart useful!

I am able to reproduce this issue using the test file that you've included. We'll take a deeper look here to resolve.

praetorian-harry avatar Aug 19 '21 23:08 praetorian-harry

I have reproduced this issue scanning the provided test file using gokart v0.5.1 and tried to check if the same result is returned after scanning the following code, which replaces the doSomething function call for its body.

package bug

import "net/http"

func DoSomething() (*http.Response, error) {
    req, err := http.NewRequest("GET", "http://example.com", nil)
    if err != nil {
        return nil, err
    }
    return http.DefaultClient.Do(req)
}

The scan does not consider the function vulnerable to SSRF as presented below.

$ gokart scan bugs/ssrf03/bug.go 
Using config found at /home/saullo/.gokart/analyzers.yml

Revving engines VRMMM VRMMM
3...2...1...Go!

Race Complete! Analysis took 398.462088ms and 82 Go files were scanned (including imported packages)
GoKart found 0 potentially vulnerable functions

As this got me curious, I took a deeper look into what gokart does and discovered the following.

While recursively taint analyzing the provided test code, the req expression is *ssa.Parameter and the req variable type is *http/net.Request, which meets a tainted condition and vulnerable is set to true in util/taint.go at line 133.

https://github.com/praetorian-inc/gokart/blob/3d38a9ae72f7d67d5c13f83ec5669630868e409e/util/taint.go#L119-L142

The functions that have a *http/net.Request parameter are considered tainted by the default gokart configuration in ~/.gokart/analyzers.yml.

https://github.com/praetorian-inc/gokart/blob/3d38a9ae72f7d67d5c13f83ec5669630868e409e/util/analyzers.yml#L90-L93

I wonder if it wouldn't be possible to use a more detailed condition to taint vulnerable functions and avoid false positives. Where does the Go documentation state that a *http/net.Request parameter is untrusted?

saullocarvalho avatar May 02 '23 15:05 saullocarvalho