Go语言安全编程
这篇文章主要讨论Go语言对于安全编程所提供的相关模组
输入校验
对于外部输入的校验是许多安全编码的基本守则, Go 语言提供哪些机制可以做输入验证?
字串转换 Strconv
https://golang.org/pkg/strconv/
常见的字串转换有 Atoi, ParseBool, ParseFloat, ParseInt
字串处理 Strings
https://golang.org/pkg/strings/
常见的字串处理有: Trim, ToLower, ToTitle
UTF8验证
https://golang.org/pkg/unicode/utf8/
相关处理 UTF8有效性验证的有: Valid, ValidRune, ValidString, EncodeRune
Email, URL, IP 等验证
当需要验证 Email, URL, IP 等的格式合法性怎么处理? 是否有线有的函数可以使用?
笔者推荐使用三方模组 : https://github.com/asaskevich/govalidator
这个模组除了提供许多现成的验证, 还可以方便的自订白/黑名单
- func IsASCII(str string) bool
func IsAlpha(str string) bool
func IsAlphanumeric(str string) bool - func IsEmail(str string) bool
func IsFilePath(str string) (bool, int) - func IsIPv4(str string) bool
func IsIPv6(str string) bool - func IsNumeric(str string) bool
- func SafeFileName(str string) string
- func Trim(str, chars string) string
- func IsRequestURI(rawurl string) bool
WEB CSRF攻击
CSRF的防护就是产生 Token ,
Go 也为 CSRF 提供特别的模组, 让开发者不用自行处理产生 Token
http://www.gorillatoolkit.org/pkg/csrf
Cookie 防护
http://www.gorillatoolkit.org/pkg/securecookie#overview
HTML Sanitization
对于过滤 HTML tag Go有许多的模组可以参考选择,
EscapeString
主要将关键的字符编码 , “<” 转换成 “<” 目前支援五种字符号转换 <, >, &, ‘
参考: https://golang.org/pkg/html/#EscapeString
stripTags
将 HTML Tag 移除之后, 文字输出,
举例来说 :
`<b> Hello! </b> <script>...</script>`
经过 stripTags 之后换变成只剩下:
Hello!
参考: https://golang.org/search?q=stripTags
三方模组
其他还有相关三方模组可以使用, 作为输入参数的 Sanitize
- https://github.com/kennygrant/sanitize
- https://github.com/maxwells/sanitize
- https://github.com/microcosm-cc/bluemonday
日志审计
日志机制Go提供许多模组, 哪个比较优选笔者暂时没有好的答案
日志审计原则上要注意的有:
- 操作日志, 系统日志, 安全日志权限控制存取
- 日志保存, 大小控制与备份时间
- 日志注入问题
- 敏感信息打印于日志中
- 系统配置, 权限, 帐号更改, 软件更新等必须要做日志
SQL 注入
要防止SQL注入一定要用 prepare statement, 当然 Go语言也提供类似的方式
https://golang.org/pkg/database/sql/#DB.Prepare
ctx := context.Background() customerId := r.URL.Query().Get(“id”) query := “SELECT number FROM customer WHERE customerId = ?” stmt, _ := db.QueryContext(ctx, query, customerId) |
customerName := r.URL.Query().Get(“name”) db.Exec(“UPDATE number SET name=? WHERE customerId=?“, customerName, 90) |
避免 XSS 注入
HTMLEscapeString
https://golang.org/search?q=HTMLEscapeString
JSEscapeString
https://golang.org/pkg/text/template/#JSEscapeString
密码储存加密
密码储存时一定要加密, 加密方式业界目前公认的有下列几种方式
Go 提供 Bcrypt 与 PBKDF2, 其中 PBKDF2为 美国NIST主要推荐
为什么一定要用这种加密方式, 其他不行吗?
主要是其他加密方式容易受到 RainBow Table 攻击
https://godoc.org/golang.org/x/crypto/bcrypt
https://github.com/p-h-c/phc-winner-argon2
https://godoc.org/golang.org/x/crypto/pbkdf2
文件类型
当服务提供文件上传功能时, 对于文件的检查其中可以运用这函数检查该文件类型
https://golang.org/pkg/net/http/#DetectContentType
主要透過文件頭 512 bytes 检查 MIME文件类型
http://mimesniff.spec.whatwg.org/
随机数
https://golang.org/pkg/math/rand/
https://golang.org/pkg/crypto/rand/
随机数的产生有两种方式, 笔者初步测试 math/rand不建议采用,
加密传输 TLS or WebSocket
當要使用加密傳輸時候, 可以使用这模组
https://golang.org/pkg/crypto/tls/#pkg-overview
測試上可用 SSLTest, 该协议是否为 TLS 1.2
为什么要用 Go?
Go十分适合任何人初学程式语言
Go 语言为什么变得热门? 为什么要用 Go 语言? 简单来说:
Go = C 语言语法 + C 跨平台可编译执行 EXE + Python 高阶语法简洁 + Python 网络/Web 等模组功能
C语言的优点: 跨平台与编译后执行效率, 但是用C 来编写 Web 相关的服务, 或是网络等功能却很费时
Python 优点: 语法简单高阶, 有许多网络模组可以很容易实现Web服务功能, 缺点是脚本执行 (非二进制), 执行时需要部署 Python与相关模组等
Go 语言的出现结合 C 与 Python 的优点, 又解决两者的缺点, 有程序经验的程序员上手容易