go 代码审计去的一些其他漏洞
文件操作、路径穿越、重定向、CORS
一个go写的WEB漏洞靶场,实际自己写一下,加固一下知识
https://github.com/godzeo/go-gin-vul
GIN框架 整个web框架是go-gin-Example 上面改的,没有前端框架,只有一个swagger,直接发包吧
0x04 File Operation 文件操作
0x041 path traversing 路径穿越
在执行文件操作时,如果对从外部传入的文件名没有限制,则可能导致任意文件读取或任意文件写入,这可能严重导致代码执行。
0x0411 arbitrary file read 任意文件读
routers/api/unAuth/path.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func FileRead(c *gin.Context) { path := c.Query("filename")
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), })
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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), }) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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 remove 任意文件删除
1 2 3 4 5
| func Fileremove(c *gin.Context) { path := c.Query("path") os.Remove(path) }
|
0x0414 FIX 修复
routers/api/unAuth/path.go
过滤 ..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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", }) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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 文件权限
根据创建文件的敏感度设置不同级别的访问权限,以防止具有任意权限的用户读取敏感数据。例如,将文件权限设置为: -rw-r -—-
1
| ioutil.WriteFile(p, []byte("present"), 0640)
|
1 2 3 4 5 6 7 8
| -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 重定向
不要直接重定向到用户可控制的地址。
1 2 3 4
| func redirect(c *gin.Context) { loc := c.Query("redirect") c.Redirect(302, loc) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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 修复
1 2 3 4 5
| func SafeRedirect(c *gin.Context) { baseUrl := "https://baidu.com/path?q=" loc := c.Query("redirect") c.Redirect(302, baseUrl+loc) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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
CORS请求保护不当会导致敏感信息泄露,因此应严格设置Access-Control-Allow-Origin以使用同源策略进行保护。
任意源
1 2 3 4 5 6 7
| func Cors1(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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
|
任意添加源
1 2 3 4 5 6 7
| 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")
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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 修复
直接白名单
code:
1 2 3 4 5 6
| 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") }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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
|