5 Secure Coding Tips in Go
Secure / Defensive coding is a deep concept. This post only aims to give a different perspective and a set of useful tools to the developers who are interested in the Go programming language .
OWASP Secure Coding Principles is a good resource to dive deep.
Compare strings on a constant time
Regular string comparison is done byte by byte. When running this code,
b := "abcd123" == "abcx123"
firstly the a
runes are compared, and then the b
and so on. If the comparison fails at some point, in that case on the 4th character, it just returns false immediately and does not go on any further bytes.
The longer the string, the more time spent on comparisons, and this might give a clue to the brute-force attacker. When an attacker is trying to match a hash/token with a brute force attack, she can tell how many bytes it took by looking at the time it took to get the response.
Using ConstantTimeCompare function when comparing these kind of strings, trades off a little bit performance with security.
These kind of timing attacks may also be done when searching for a table with a secret data / having a loop dependent on it etc.
Avoiding being dependent on secret data for time-taking processes might be a good practice to apply on.
Disable Directory Listing
Go’s default file server comes with directory listing open. So, when you want to serve a file, placed in a path like /some/directory/file.txt
and a client sends a request to the /some/directory/
she can list the files and directories below.
https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Directory_Indexing
Disable directory listing if it is not a valid use case on your product.
Unindexed library and other possible middlewares for different frameworks can be easily applied to the wound :)
Use Rate Limiters on APIs
DDoS and overloading bandwidth attacks can easily create throttles on applications. So limiting with a maximum number of requests per second or else is a good way to secure your application.
Uber’s Rate Limiter or a simple Limiter as a middleware are both useful. You may also want to take a loot at the time/rate source code.
Use a Security Perspective Linter
Especially coding with teams, changing code frequently creates leakes on different levels of the application. Adding linters to the CI/CD pipelines automatically can make things easier to early detection.
Static code analysis is a good start to remember security concerns when developing. Take a look at; GoSec, GoMetaLinter.
Since security is generally not the first priority when creating a program, these linters help a lot to remember important concerns.
Be Sceptical When Logging & Error Handling
When handling errors or logging programs’ default flow, be sceptical with the data being logged. Any critical information may have been logged as plaintext, especially dealing with generic panic
s with recover
s.
It is very easy to log sensitive data inside a struct that looks innocent. Using Stringer
s for these structs or creating sensitive data remover functions may be useful to catch these things. For teams, having a checklist when doing a code review is also a good practice to prevent these kind of leaks.
Also, be careful with the use of log.Fatal
it exits the program with os.Exit(1)
which means, no defer statements will be executed, temporary files & directories will not be cleaned and so on. It differs from panic with these.
Awesome Go Security, Awesome Golang Security, are good resources to check on more libraries / resources.
Thanks for reading. Please feel free to add any other tips on below comments :)