CVE-2023-34231 (Go, published 2023-06-08T20:15Z)
Description: value: gosnowflake is th Snowflake Golang driver. Prior to version 1.6.19, a command injection vulnerability exists in the Snowflake Golang driver via single sign-on (SSO) browser URL authentication. In order to exploit the potential for command injection, an attacker would need to be successful in (1) establishing a malicious resource and (2) redirecting users to utilize the resource. The attacker could set up a malicious, publicly accessible server which responds to the SSO URL with an attack payload. If the attacker then tricked a user into visiting the maliciously crafted connection URL, the user’s local machine would render the malicious payload, leading to a remote code execution. This attack scenario can be mitigated through URL whitelisting as well as common anti-phishing resources. A patch is available in version 1.6.19.
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-77 \u2014 Improper Neutralization of Special Elements used in a Command ('Command Injection')
The product constructs all or part of a command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended command when it is sent to a downstream component.
Repository: https://github.com/snowflakedb/gosnowflake
Files changed:
url_util.go
util_test.go
Commit message: SNOW-761744 Added URL Validator and URL Encoder (#757)



Vulnerable code:

Fixed code:
package gosnowflake

import (
	"net/url"
	"regexp"
)

var (
	matcher, _ = regexp.Compile(`^http(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z@:])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\&\(\)\/\\\+&%\$#_=@]*)?$`)
)

func isValidURL(targetURL string) bool {
	if !matcher.MatchString(targetURL) {
		logger.Infof(" The provided URL is not a valid URL - " + targetURL)
		return false
	}
	return true
}

func urlEncode(targetString string) string {
	// We use QueryEscape instead of PathEscape here
	// for consistency across Drivers. For example:
	// QueryEscape escapes space as "+" whereas PE
	// it as %20F. PE also does not escape @ or &
	// either but QE does.
	// The behavior of QE in Golang is more in sync
	// with URL encoders in Python and Java hence the choice
	return url.QueryEscape(targetString)
}

type tcURLList struct {
	in  string
	out bool
}

func TestValidURL(t *testing.T) {
	testcases := []tcURLList{
		{"https://ssoTestURL.okta.com", true},
		{"https://ssoTestURL.okta.com:8080", true},
		{"https://ssoTestURL.okta.com/testpathvalue", true},
		{"-a calculator", false},
		{"This is a random test", false},
		{"file://TestForFile", false},
	}
	for _, test := range testcases {
		result := isValidURL(test.in)
		if test.out != result {
			t.Errorf("Failed to validate URL, input :%v, expected: %v, got: %v", test.in, test.out, result)
		}
	}
}

type tcEncodeList struct {
	in  string
	out string
}

func TestEncodeURL(t *testing.T) {
	testcases := []tcEncodeList{
		{"Hello @World", "Hello+%40World"},
		{"Test//String", "Test%2F%2FString"},
	}

	for _, test := range testcases {
		result := urlEncode(test.in)
		if test.out != result {
			t.Errorf("Failed to encode string, input %v, expected: %v, got: %v", test.in, test.out, result)
		}
	}
}