Author: Andrew Luke - Dec. 2018
This is a set of security guidelines for the Golang programming language. Each element in this document will be Golang-specific. General web application and API guidelines will be covered here. This guideline is intended to be a living security reference for development teams and quality assurance as part of the Application Security Team’s Secure Software Development Lifecycle (SSDLC). As such, it will be continually added to and updated as the Application Security team is made aware of new security considerations or gaps in the current guidelines.
Golang is a strongly typed language that has taken steps to prevent security issues found in other languages. For example, there is no pointer arithmetic. Garbage collection is automatic. Another example, the standard crypto package for AES does not provide Cipher Block Chaining (CBC) as an option.
- Bcrypt for password hashing: https://godoc.org/golang.org/x/crypto/bcrypt
- AES for symmetric encryption:
- CSRF Protection: https://github.com/gorilla/csrf
- Validator for input validation: https://github.com/go-playground/validator
- Output Sanitization:
- Pseudo-random number generation: https://golang.org/pkg/crypto/rand/
- Safe SQL Queries:
- Checkmarx Web Application Secure Coding Practices: https://checkmarx.gitbooks.io/go-scp/
- Output Encoding with Native Templates
- Beware Output Encoding Bypasses
- Go Security Protections Don’t Extend To C Code
- Use crypto/rand Instead Of math/rand
The net/http Package does not provide any type of output encoding. The html/template package implements data-driven templates for generating HTML output safe against code injection. It provides the same interface as package text/template and should be used instead of text/template whenever the output is HTML. This package wraps package text/template so you can share its template API to parse and execute HTML templates safely. This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing functions to each simple action pipeline.
Using the net/http package exposes web application users to cross-site scripting attacks due to its lack of output encoding.
Use the html/template package to automatically escape HTML, CSS, JavaScript, and URIs. If the net/http package is used, use manual escaping and manually set the Content-Type, because it is set automatically depending on what is served.
High
The html/template package provides a way to circumvent the escaping pipeline, using template. [HTML|JS|URL]()
method set a string to its type.
Placing user into into this declaration function will bypass default output encoding, introduce cross-site scripting and HTML injection vulnerabilities into your web application. Example of Issue:
The following will declare the <b>World</b>
string as HTML, printing it as-is into the HTML:
tmpl.Execute(out, template.HTML(`<b>World</b>`))
The EscapeString() function in the native html package accepts a string and returns the same string with the special characters escaped. (i.e. <
becomes <
). The html/template package has a stripTags() function, but it's unexported.
The html/template package provides several functions for escaping strings:
HTMLEscape()
HTMLEscapeString()
HTMLEscaper()
JSEscape()
JSEscapeString()
JSEscaper()
URLQueryEscaper
Avoid using template Typed Strings on user input.
High
- https://golang.org/pkg/html/template/
- https://github.com/kennygrant/sanitize
- https://github.com/microcosm-cc/bluemonday
The cmd/cgo package provides a way to call C code within a Go application. Go was created with many security protections in place, like memory safety and strong typing. These protections do not extend to the C code called with this package.
By using cmd/cgo, you introduce all of the C code security considerations and concerns into your Go application.
Be aware that C code security concerns are still present when ran by a Go application. Understand the inherent security issues with various C code functionality used, and develop the C code ran by your Go application in a secure manner.
High
The math/rand package is a deterministic, pseudo-random number generator. It takes a seed and generates pseudo-random numbers with it. Because it is deterministic, these values will be the same each time the application is ran, allowing an attacker to predict the values.
Anyone with knowledge of the math/rand seed can determine the pseudo-random values used by the application.
The crypto/rand package should be used instead of the math/rand package. This package uses operating system randomness to generate pseudo-random numbers. Due to this, the generated values are not deterministic and a seed is not needed.
Example:
This example reads 10 cryptographically secure pseudorandom numbers from rand.Reader and writes them to a byte slice:
package main
import (
"bytes"
"crypto/rand"
"fmt"
)
func main() {
c := 10
b := make([]byte, c)
_, err := rand.Read(b)
if err != nil {
fmt.Println("error:", err)
return
}
// The slice should now contain random bytes instead of only zeroes.
fmt.Println(bytes.Equal(b, make([]byte, c)))
}
High