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.
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