Update modules/ROOT/pages/programming-languages/Go.adoc

rfc add Good Practices for Securing Go
This commit is contained in:
Judy Kelly 2022-02-10 18:44:13 +00:00
parent 9e19ddee41
commit 187fffcf68

View file

@ -108,3 +108,154 @@ but the original value is preserved. Using a fresh value (with
suitable default values if necessary) ensures that data from a
previous deserialization operation does not leak into the current
one. This is especially relevant when structs are deserialized.
[[chap-Defensive_Coding-Go-Marshaling]]
== Good Practices for Securing Go - High Level Overview
Secure coding is the practice of writing programs that are resistant to attack by malicious or mischievous people or programs.
Golangs adoption has been increasing over the years. Projects within Red Hat like https://cloud.redhat.com/learn/topics/operators/[*Operators*] and https://www.terraform.io/[*Terraform*] have been completed in this programming language.
=== 1. Use Go Modules
Modules are how Go manages dependencies. https://go.dev/ref/mod/[*Go Modules*] allow for dependency version pinning, including transitive modules, and also provides assurance against unexpected module mutation via the go.sum checksum database.
For an introduction to creating Go projects, see https://go.dev/doc/code/[*How to Write Go Code*]. For information on using modules, migrating projects to modules, and other topics, see the blog series starting with https://go.dev/blog/using-go-modules[*Using Go Modules*].
=== 2. Validate input entries
Helps avoid attackers who send us intrusive data that could damage the system.
To validate user input, you can use native Go packages like strconv to handle string conversions to other data types. Go also has support for regular expressions with regexp for complex validations. Even though Gos preference is to use native libraries, there are third-party packages like https://github.com/go-playground/validator/[*validator*]. With validator, you can include validations for structs or individual fields more easily.
=== 3. Use HTML templates
One critical and common vulnerability is cross-site scripting or XSS. This exploit consists basically of the attacker being able to inject malicious code into the app to modify the output.
Go has the package https://pkg.go.dev/html/template[*html/template*] to encode what the app will return to the user. So, instead of the browser executing an input like <script>alert(Youve Been Hacked!);</script>, popping up an alert message; you could encode the input, and the app will treat the input as a typical HTML code printed in the browser.
There are also third-party libraries you can use when developing web apps in Go. For example, theres https://www.gorillatoolkit.org/[*Gorilla web toolkit*], which includes libraries to help developers to do things like encoding authentication cookie values. Theres also https://github.com/justinas/nosurf/[*nosurf*], which is an HTTP package that helps with the prevention of cross-site request forgery (https://owasp.org/www-community/attacks/csrf/[*CSRF*]).
[source, go]
----
```golang
name := r.FormValue("name")
template := template.Must(template.ParseGlob("xss.html"))
data["Name"] = name
err := template.ExecuteTemplate(w, name, data)
```
----
=== 4. Protect yourself from SQL injections
The first thing you need you to do is make sure a user that connects to the database has limited permissions. A good practice is to also sanitize the users input, as I described in a previous section, or to escape special characters and use https://pkg.go.dev/html/template#HTMLEscapeString/[*HTMLEscapeString*] function from the HTML template package.
But, the most critical piece of code youd need to include is the use of parameterized queries. In Go, you dont prepare a statement in a connection; you prepare it on the DB. Heres an example of how to use parameterized queries:
[source, go]
----
```golang
customerName := r.URL.Query().Get("name")
db.Exec("UPDATE creditcards SET name=? WHERE customerId=?", customerName, 233, 90)
```
----
If using the db.Query() function instead, ensure you sanitize the users input first, as above.
=== 5. Encrypt sensitive information
Go package that includes robust implementations to encrypt information like https://pkg.go.dev/golang.org/x/crypto/[*crypto*].
=== 6. Enforce HTTPS communication
To secure in-transit connection in the system isnt only about the app listening in port 443. You also need to use proper certificates and enforce HTTPS to avoid attackers downgrading the protocol to HTTP.
[source, go]
----
```golang
w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
```
----
You might also want to specify the server name in the TLS configuration, like this:
[source, go]
----
```golang
config := &tls.Config{ServerName: "yourSiteOrServiceName"}
```
----
Of Note: Its always a good practice to implement in-transit encryption even if your application is only for internal communication. Imagine if, for some reason, an attacker could sniff your internal traffic. Whenever you can, its always best to raise the difficulty bar for possible future attackers.
=== 7. Use caution with unsafe and cgo
Package https://pkg.go.dev/unsafe[*unsafe*] provides an escape hatch from Gos type system, enabling interactions with low-level and system call APIs, in a manner similar to C programs. However, unsafe has several rules which must be followed in order to perform these interactions in a sane way. Its easy to make https://github.com/golang/sys/commit/b69606af412f43a225c1cf2044c90e317f41ae09/[*subtle mistakes when writing unsafe code*], but these mistakes can often be avoided.
This blog post: https://blog.gopheracademy.com/advent-2019/safe-use-of-unsafe-pointer/[*Safe-use-of-unsafe-pointer*] will introduce some of the current and upcoming Go tooling that can verify safe usage of the unsafe. Pointer type in your Go programs. If you have not worked with unsafe before, Recommended reading previous https://blog.gopheracademy.com/advent-2017/unsafe-pointer-and-system-calls/[*Gopher Academy Advent series blog*] on the topic.
Go's https://pkg.go.dev/cmd/cgo[*cgo*] system for calling C functions offers a very convenient feature. As outlined in https://relistan.com/cgo-when-and-when-not-to-use-it
Here are some problems with using Cgo in your application:
* It breaks a lot of Gos awesome tooling
* Puts Gos concurrency promise at risk
* Might break your static binary,
* Breaks cross-compiling almost always
* Calls into Cgo are much slower than native Go calls
=== 8. Be mindful with Errors and Logs
Go doesnt have exceptions. This means that youd need to handle errors differently than with other languages. The standard looks like this:
[source, go]
----
```golang
if err != nil {
// handle the error
}
```
----
Also, Go offers a native library to work with logs. The most simple code is like this:
[source, go]
----
```golang
package main
import (
"log"
)
func main() {
log.Print("Logging in Go!")
}
```
----
Finally, make sure you apply all the previous rules like encryption and sanitization of the data you put into the logs.
==== Libraries
* https://github.com/o1egl/paseto[*paseto - Platform-Agnostic Security Tokens implementation in GO (Golang)*]
* https://github.com/StalkR/hsts/[*hsts - Go HTTP Strict Transport Security library*]
* https://github.com/dgrijalva/jwt-go/[*jwt-go - Golang implementation of JSON Web Tokens (JWT)*]
==== Further Reading
* https://github.com/Binject/awesome-go-securityhttps://github.com/Binject/awesome-go-security
* https://owasp.org/www-pdf-archive/Owasp-171123063052.pdf
* https://github.com/securego/gosec
* https://tutorialedge.net/golang/secure-coding-in-go-input-validation/
* https://tour.golang.org/list
* https://snyk.io/blog/go-security-cheatsheet-for-go-developers/
* https://hackernoon.com/security-considerations-in-golang-xo4y3ykk
* https://golang.org/security
* https://github.com/guardrailsio/awesome-golang-security
* https://blog.sqreen.com/top-6-security-best-practices-for-go/
* https://cyral.com/blog/security-as-code-implementing-lint-and-gosec/
* https://github.com/OWASP/Go-SCP
* https://spacetime.dev/memory-security-go
* https://github.com/parsiya/Hacking-with-Go
* https://github.com/denji/golang-tls
* https://checkmarx.com/blog/redos-go/
* https://blog.trailofbits.com/2019/11/07/attacking-go-vr-ttps/
* https://utcc.utoronto.ca/~cks/space/blog/programming/GoCgoErrorReturns