在go语言中安全问题之文件操作、系统接口、通信安全场景示例
Go  /  管理员 发布于 1年前   474
go语言安全问题之文件操作、系统接口、通信安全场景
场景1:文件操作
路径穿越检查
- 在进行文件操作时,如果对外部传入的文件名未做限制,可能导致任意文件读取或者任意文件写入,严重可能导致代码执行。
// bad: 任意文件读取
func handler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query()["path"][0]
// 未过滤文件路径,可能导致任意文件读取
data, _ := ioutil.ReadFile(path) w.Write(data)
// 对外部传入的文件名变量,还需要验证是否存在../等路径穿越的文件名
data, _ = ioutil.ReadFile(filepath.Join("/home/user/", path)) w.Write(data)}
// bad: 任意文件写入
func unzip(f string) {
r, _ := zip.OpenReader(f) for _, f := range r.File { p, _ := filepath.Abs(f.Name) // 未验证压缩文件名,可能导致../等路径穿越,任意文件路径写入
ioutil.WriteFile(p, []byte("present"), 0640) }}
// good: 检查压缩的文件名是否包含..路径穿越特征字符,防止任意写入
func unzipGood(f string) bool {
r, err := zip.OpenReader(f) if err != nil { fmt.Println("read zip file fail") return false } for _, f := range r.File { if !strings.Contains(f.Name, "..") { p, _ := filepath.Abs(f.Name) ioutil.WriteFile(p, []byte("present"), 0640) } else { return false } } return true}
文件访问权限
根据创建文件的敏感性设置不同级别的访问权限,以防止敏感数据被任意权限用户读取。例如,设置文件权限为:-rw-r-----
ioutil.WriteFile(p, []byte("present"), 0640)
场景2:系统接口
命令执行检查
使用 exec.Command、exec.CommandContext、syscall.StartProcess、os.StartProcess 等函数时,第一个参数(path)直接取外部输入值时,应使用白名单限定可执行的命令范围,不允许传入 bash、cmd、sh 等命令;
使用 exec.Command、exec.CommandContext 等函数时,通过 bash、cmd、sh 等创建 shell,-c 后的参数(arg)拼接外部输入,应过滤 \n $ & ; | ‘ “() ` 等潜在恶意字符;
// bad
func foo() {
userInputedVal := "&& echo 'hello'" // 假设外部传入该变量值
cmdName := "ping " + userInputedVal
// 未判断外部输入是否存在命令注入字符,结合sh可造成命令注入
cmd := exec.Command("sh", "-c", cmdName) output, _ := cmd.CombinedOutput() fmt.Println(string(output))
cmdName := "ls" // 未判断外部输入是否是预期命令
cmd := exec.Command(cmdName) output, _ := cmd.CombinedOutput() fmt.Println(string(output))}
// good
func checkIllegal(cmdName string) bool {
if strings.Contains(cmdName, "&") || strings.Contains(cmdName, "|") || strings.Contains(cmdName, ";") || strings.Contains(cmdName, "$") || strings.Contains(cmdName, "'") || strings.Contains(cmdName, "`") || strings.Contains(cmdName, "(") || strings.Contains(cmdName, ")") || strings.Contains(cmdName, "\"") { return true } return false}
func main() {
userInputedVal := "&& echo 'hello'" cmdName := "ping " + userInputedVal
if checkIllegal(cmdName) { // 检查传给sh的命令是否有特殊字符
return // 存在特殊字符直接return
}
cmd := exec.Command("sh", "-c", cmdName) output, _ := cmd.CombinedOutput() fmt.Println(string(output))}
场景3:通信安全
网络通信采用 TLS 方式
明文传输的通信协议目前已被验证存在较大安全风险,被中间人劫持后可能导致许多安全风险,因此必须采用至少 TLS 的安全通信方式保证通信安全,例如 gRPC/Websocket 都使用 TLS1.3。
// good
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains") w.Write([]byte("This is an example server.\n")) })
// 服务器配置证书与私钥
log.Fatal(http.ListenAndServeTLS(":443", "yourCert.pem", "yourKey.pem", nil))}
TLS 启用证书验证
TLS 证书应当是有效的、未过期的,且配置正确的域名,生产环境的服务端应启用证书验证。
// bad
import (
"crypto/tls" "net/http")
func doAuthReq(authReq *http.Request) *http.Response {
tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} res, _ := client.Do(authReq) return res}
// good
import (
"crypto/tls" "net/http")
func doAuthReq(authReq *http.Request) *http.Response {
tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: false}, } client := &http.Client{Transport: tr} res, _ := client.Do(authReq) return res}
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号