← Back to all posts
Code Auditing5 min read

Go Code Auditing Vulnerabilities (File Operations\Redirects\CORS)

Other vulnerabilities encountered during Go code auditing, including file operations, path traversal, redirects, and CORS, demonstrated through a Go web vulnerability lab built on go-gin-example.

#Golang#web security
Read in Chinese→

Some other vulnerabilities encountered during Go code auditing
File operations, path traversal, redirects, and CORS

A web vulnerability lab written in Go, built hands-on to reinforce knowledge

https://github.com/godzeo/go-gin-vul

GIN framework. The entire web framework is based on go-gin-example. There is no frontend framework, only Swagger, so just send requests directly.

0x04 File Operations

0x041 Path Traversal

When performing file operations, failing to restrict externally supplied filenames may lead to arbitrary file reads or writes, potentially resulting in code execution.

0x0411 Arbitrary File Read

routers/api/unAuth/path.go

func FileRead(c *gin.Context) {
	path := c.Query("filename")

	// Unfiltered file paths
	data, _ := ioutil.ReadFile(path)

	c.JSON(200, gin.H{
		"success": "read: " + string(data),
	})

}

func Dirfile(c *gin.Context) {
	path := c.Query("filename")
	data, _ := ioutil.ReadFile(filepath.Join("/Users/zy", path))

	c.JSON(200, gin.H{
		"success": "read: " + string(data),
	})

}
GET /api/vul/read?filename=/../../../../../../../../../../etc/passwd HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

GET /api/vul/dir?filename=/../../etc/passwd HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

0x0412 Arbitrary File Write

routers/api/unAuth/path.go

func Unzip(c *gin.Context) {
	path := c.Query("filename")
	text := c.Query("text")
	file_path := filepath.Join("/Users/zy/", path)
	r, _ := zip.OpenReader(file_path)

	var abspath string
	for _, f := range r.File {
		abspath, _ = filepath.Abs(f.Name)
		ioutil.WriteFile(abspath, []byte(text), 0640)
	}

	data, _ := ioutil.ReadFile(abspath)

	c.JSON(200, gin.H{
		"success": "read: " + string(data),
	})
}
GET /api/vul/unzip?filename=radconfig.zip&text=Zeo666 HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

0x0413 Arbitrary File Removal

//arbitrary file remove
func Fileremove(c *gin.Context) {
 	path := c.Query("path")
	os.Remove(path)
}

0x0414 FIX

routers/api/unAuth/path.go

Filter ..

func Unzipsafe(c *gin.Context) {
	path := c.Query("filename")
	file_path := filepath.Join("/Users/zy/", path)
	r, err := zip.OpenReader(file_path)
	if err != nil {
		fmt.Println("read zip file fail")
		c.JSON(500, gin.H{
			"success": "err: " + err.Error(),
		})
	}
	for _, f := range r.File {
		if !strings.Contains(f.Name, "..") {
			p, _ := filepath.Abs(f.Name)
			ioutil.WriteFile(p, []byte("present"), 0640)
		} else {
			c.JSON(500, gin.H{
				"success": "err: " + err.Error(),
			})
		}
	}
	c.JSON(200, gin.H{
		"success": "OK",
	})
}
GET /api/safe/unzip?filename=../../radconfig.zip&text=Zeo666 HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
Date: Sat, 05 Nov 2022 08:04:40 GMT
Content-Length: 65
Connection: close

{"success":"err: open /radconfig.zip: no such file or directory"}

0x042 File Access Permissions

Set different access permission levels according to the sensitivity of the files being created to prevent users with inappropriate privileges from reading sensitive data. For example, set the file permissions to: -rw-r -––

ioutil.WriteFile(p, []byte("present"), 0640)
-rw------- (600)    只有拥有者有读写权限。
-rw------- (640)    只有拥有者和属组用户有读写权限。
-rw-r--r-- (644)    只有拥有者有读写权限;而属组用户和其他用户只有读权限。
-rwx------ (700)    只有拥有者有读、写、执行权限。
-rwxr-xr-x (755)    拥有者有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
-rwx--x--x (711)    拥有者有读、写、执行权限;而属组用户和其他用户只有执行权限。
-rw-rw-rw- (666)    所有用户都有文件读、写权限。
-rwxrwxrwx (777)    所有用户都有读、写、执行权限。

0x05 Open Redirect

Do not redirect directly to a user-controlled address.

func redirect(c *gin.Context) {
    loc := c.Query("redirect")
    c.Redirect(302, loc)
}
GET /api/vul/redirect?redirect=https://www.qq.com HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

0x42 FIX

func SafeRedirect(c *gin.Context) {
	baseUrl := "https://baidu.com/path?q="
	loc := c.Query("redirect")
	c.Redirect(302, baseUrl+loc)
}
GET /api/safe/redirect?redirect=https://www.qq.com HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

0x05 CORS

Improper protection of CORS requests can lead to sensitive information disclosure. Therefore, Access-Control-Allow-Origin should be configured strictly to enforce same-origin policy protections.

Allow any origin

func Cors1(c *gin.Context) {

	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")

}
GET /api/vul/cors1 HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *
Date: Sat, 05 Nov 2022 09:05:18 GMT
Content-Length: 0
Connection: close

Arbitrarily add origins

func Cors2(c *gin.Context) {

	origin := c.Request.Header.Get("Origin")
	c.Header("Access-Control-Allow-Origin", origin)
	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")

}
GET /api/vul/cors2 HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Origin: zeo.cool

HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: zeo.cool
Date: Sat, 05 Nov 2022 09:06:33 GMT
Content-Length: 0
Connection: close

FIX

Use an explicit allowlist

code:

func corsDemo2(c *gin.Context) {
    allowedOrigin := "https://test.com"
 
    c.Header("Access-Control-Allow-Origin", allowedOrigin)
    c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
}
GET /api/safe/cors HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Origin: zeo.cool

HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: https://test.com
Date: Sat, 05 Nov 2022 09:09:53 GMT
Content-Length: 0
Connection: close