Browse Source

check BucketName and Endpoint for SSR attack

taowei.wtw 6 years ago
parent
commit
cb469bdf31
5 changed files with 117 additions and 3 deletions
  1. 5 2
      oss/client.go
  2. 42 0
      oss/client_test.go
  3. 15 1
      oss/conn.go
  4. 20 0
      oss/utils.go
  5. 35 0
      oss/utils_test.go

+ 5 - 2
oss/client.go

@@ -49,7 +49,10 @@ func New(endpoint, accessKeyID, accessKeySecret string, options ...ClientOption)
 
 	// URL parse
 	url := &urlMaker{}
-	url.Init(config.Endpoint, config.IsCname, config.IsUseProxy)
+	err := url.Init(config.Endpoint, config.IsCname, config.IsUseProxy)
+	if err != nil {
+		return nil, err
+	}
 
 	// HTTP connect
 	conn := &Conn{config: config, url: url}
@@ -66,7 +69,7 @@ func New(endpoint, accessKeyID, accessKeySecret string, options ...ClientOption)
 	}
 
 	// Create HTTP connection
-	err := conn.init(config, url, client.HTTPClient)
+	err = conn.init(config, url, client.HTTPClient)
 
 	return client, err
 }

+ 42 - 0
oss/client_test.go

@@ -2823,3 +2823,45 @@ func (s *OssClientSuite) TestClientSetLocalIpSuccess(c *C) {
 	err = client.DeleteBucket(bucketNameTest)
 	c.Assert(err, IsNil)
 }
+
+// TestCreateBucketInvalidName
+func (s *OssClientSuite) TestCreateBucketInvalidName(c *C) {
+	var bucketNameTest = "-" + bucketNamePrefix + randLowStr(6)
+	client, err := New(endpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+	// Create
+	err = client.CreateBucket(bucketNameTest)
+	c.Assert(err, NotNil)
+}
+
+// TestClientProcessEndpointSuccess
+func (s *OssClientSuite) TestClientProcessEndpointSuccess(c *C) {
+	var bucketNameTest = bucketNamePrefix + randLowStr(6)
+
+	testEndpoint := endpoint + "/" + "sina.com" + "?" + "para=abc"
+
+	client, err := New(testEndpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+
+	// Create
+	err = client.CreateBucket(bucketNameTest)
+	c.Assert(err, IsNil)
+
+	// delete
+	err = client.DeleteBucket(bucketNameTest)
+	c.Assert(err, IsNil)
+}
+
+// TestClientProcessEndpointSuccess
+func (s *OssClientSuite) TestClientProcessEndpointError(c *C) {
+	var bucketNameTest = bucketNamePrefix + randLowStr(6)
+
+	testEndpoint := "https://127.0.0.1/" + endpoint
+
+	client, err := New(testEndpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+
+	// Create
+	err = client.CreateBucket(bucketNameTest)
+	c.Assert(err, NotNil)
+}

+ 15 - 1
oss/conn.go

@@ -78,6 +78,10 @@ func (conn *Conn) init(config *Config, urlMaker *urlMaker, client *http.Client)
 // Do sends request and returns the response
 func (conn Conn) Do(method, bucketName, objectName string, params map[string]interface{}, headers map[string]string,
 	data io.Reader, initCRC uint64, listener ProgressListener) (*Response, error) {
+	err := CheckBucketName(bucketName)
+	if len(bucketName) > 0 && err != nil {
+		return nil, err
+	}
 	urlParams := conn.getURLParams(params)
 	subResource := conn.getSubResource(params)
 	uri := conn.url.getURL(bucketName, objectName, urlParams)
@@ -656,7 +660,7 @@ type urlMaker struct {
 }
 
 // Init parses endpoint
-func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) {
+func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) error {
 	if strings.HasPrefix(endpoint, "http://") {
 		um.Scheme = "http"
 		um.NetLoc = endpoint[len("http://"):]
@@ -668,6 +672,14 @@ func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) {
 		um.NetLoc = endpoint
 	}
 
+	//use url.Parse() to get real host
+	strUrl := um.Scheme + "://" + um.NetLoc
+	url, err := url.Parse(strUrl)
+	if err != nil {
+		return err
+	}
+
+	um.NetLoc = url.Host
 	host, _, err := net.SplitHostPort(um.NetLoc)
 	if err != nil {
 		host = um.NetLoc
@@ -685,6 +697,8 @@ func (um *urlMaker) Init(endpoint string, isCname bool, isProxy bool) {
 		um.Type = urlTypeAliyun
 	}
 	um.IsProxy = isProxy
+
+	return nil
 }
 
 // getURL gets URL

+ 20 - 0
oss/utils.go

@@ -377,3 +377,23 @@ func ChoiceHeadObjectOption(options []Option) []Option {
 
 	return outOption
 }
+
+func CheckBucketName(bucketName string) error {
+	nameLen := len(bucketName)
+	if nameLen < 3 || nameLen > 63 {
+		return fmt.Errorf("bucket name %s len is between [3-63],now is %d", bucketName, nameLen)
+	}
+
+	for _, v := range bucketName {
+		if !(('a' <= v && v <= 'z') || ('0' <= v && v <= '9') || v == '-') {
+			return fmt.Errorf("bucket name %s can only include lowercase letters, numbers, and -", bucketName)
+		}
+	}
+
+	if bucketName[0] == '-' || bucketName[nameLen-1] == '-' {
+		return fmt.Errorf("bucket name %s must start and end with a lowercase letter or number", bucketName)
+	}
+
+	return nil
+
+}

+ 35 - 0
oss/utils_test.go

@@ -218,3 +218,38 @@ func (s *OssUtilsSuite) TestAdjustRange(c *C) {
 	c.Assert(start, Equals, (int64)(0))
 	c.Assert(end, Equals, (int64)(8192))
 }
+
+func (s *OssUtilsSuite) TestUtilCheckBucketName(c *C) {
+	err := CheckBucketName("a")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("a11111111111111111111111111111nbbbbbbbbbbbbbbbbbbbbbbbbbbbqqqqqqqqqqqqqqqqqqqq")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("-abcd")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("abcd-")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("abcD")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("abc 1")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("abc&1")
+	c.Assert(err, NotNil)
+
+	err = CheckBucketName("abc-1")
+	c.Assert(err, IsNil)
+
+	err = CheckBucketName("1bc-1")
+	c.Assert(err, IsNil)
+
+	err = CheckBucketName("111-1")
+	c.Assert(err, IsNil)
+
+	err = CheckBucketName("abc123-def1")
+	c.Assert(err, IsNil)
+}