diff --git a/rules/go/gorilla/cookie_missing_http_only.yml b/rules/go/gorilla/cookie_missing_http_only.yml index 3c89e1248..44f9083ec 100644 --- a/rules/go/gorilla/cookie_missing_http_only.yml +++ b/rules/go/gorilla/cookie_missing_http_only.yml @@ -37,52 +37,29 @@ languages: - go metadata: description: Missing HTTP Only option in cookie configuration - remediation_message: | + remediation_message: |- ## Description - When set to "true", the "HttpOnly" attribute protects the cookie value from being accessed by client side JavaScript such as reading the "document.cookie" values. - By enabling this protection, a website that is vulnerable to Cross-Site Scripting (XSS) will be able to block malicious scripts from accessing the cookie value from JavaScript. - - It's essential to configure cookie security options properly, especially when using session management libraries like Gorilla Sessions in Go. + The absence of the "HttpOnly" attribute in cookie settings leaves the cookie vulnerable to being accessed by client-side JavaScript, such as through "document.cookie". This vulnerability is particularly concerning for websites susceptible to Cross-Site Scripting (XSS) attacks, as it allows malicious scripts to read the cookie value. Properly configuring the "HttpOnly" attribute is a critical step in securing cookies, especially for session management. ## Remediations - To ensure that cookies, particularly session cookies, are secure: - - ✅ Configure HttpOnly - - Set the `HttpOnly` attribute to `true` within the Gorilla Sessions cookie store. This prevents client-side scripts from accessing the cookie data, reducing XSS attack risks. - - ```go - import ( - "github.com/gorilla/sessions" - "net/http" - ) - - var store = sessions.NewCookieStore([]byte("your-secret-key")) - - func MyHandler(w http.ResponseWriter, r *http.Request) { - // Get a session. We're ignoring the error resulted from decoding an - // existing session: Get() always returns a session, even if empty. - session, _ := store.Get(r, "session-name") - // Set some session values. - session.Values["foo"] = "bar" - // Set the session to be HttpOnly. - session.Options.HttpOnly = true - // Save changes. - session.Save(r, w) - } - ``` - - ✅ Leverage Gorilla SecureCookie - - Utilize the encoding/decoding capabilities of Gorilla's SecureCookie to securely store session data. - - ✅ Implement Strong Session Management - - Use Gorilla's session management features to create, renew, and expire sessions in a secure manner, preventing session fixation and other session-related attacks. - - ## Resources + - **Do** set the `HttpOnly` attribute to `true` for cookies, especially session cookies, to prevent them from being accessed by client-side scripts. This is a key measure in mitigating the risk of XSS attacks. + ```go + func MyHandler(w http.ResponseWriter, r *http.Request) { + session, _ := store.Get(r, "session-name") + ... + session.Options.HttpOnly = true + session.Save(r, w) + } + ``` + - **Do** use Gorilla SecureCookie for encoding and decoding session data securely. This method provides an additional layer of security for session information. + ```go + var s = sessions.NewCookieStore([]byte("your-secret-key")) + ``` + - **Do** implement robust session management with Gorilla Sessions. Proper session management helps prevent attacks related to session fixation and enhances overall session security. + + ## References - [Gorilla Sessions Documentation](http://www.gorillatoolkit.org/pkg/sessions) - [OWASP Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html) diff --git a/rules/go/gorilla/insecure_cookie.yml b/rules/go/gorilla/insecure_cookie.yml index c0a314461..95ffa367d 100644 --- a/rules/go/gorilla/insecure_cookie.yml +++ b/rules/go/gorilla/insecure_cookie.yml @@ -37,31 +37,29 @@ languages: - go metadata: description: "Missing Secure option in cookie configuration" - remediation_message: | + remediation_message: |- ## Description - When set to "true", the "Secure" attribute ensures that a client will only send the cookie to the server when HTTPS is being used. - This prevents the cookie from being observed by unauthorized third parties. - - It's essential to configure cookie security options properly, especially when using session management libraries like Gorilla Sessions in Go. + The Secure attribute in cookie configuration is crucial for protecting cookies from unauthorized third-party access. When set to "true," it ensures cookies are only sent over HTTPS, safeguarding the data during transmission. ## Remediations - To ensure that cookies, particularly session cookies, are secure: - - ✅ Set Secure Flag - - If your site is served over HTTPS, also set the `Secure` flag on the cookie to ensure it's transmitted over secure channels only. - - ✅ Leverage Gorilla SecureCookie - - Utilize the encoding/decoding capabilities of Gorilla's SecureCookie to securely store session data. - - ✅ Implement Strong Session Management - - Use Gorilla's session management features to create, renew, and expire sessions in a secure manner, preventing session fixation and other session-related attacks. + - **Do** set the Secure flag for cookies if your site uses HTTPS. This action restricts cookies to secure channels, enhancing their security. + ```go + http.SetCookie(w, &http.Cookie{ + Name: "session_token", + Value: sessionToken, + Secure: true, + HttpOnly: true, + }) + ``` + - **Do** use Gorilla SecureCookie for encoding and decoding session data securely. This method provides an additional layer of security for session information. + ```go + var s = sessions.NewCookieStore([]byte("your-secret-key")) + ``` + - **Do** implement robust session management with Gorilla Sessions. Proper session management helps prevent attacks related to session fixation and enhances overall session security. - ## Resources + ## References - [Gorilla Sessions Documentation](http://www.gorillatoolkit.org/pkg/sessions) - [OWASP Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html) diff --git a/rules/go/gosec/blocklist/cgi.yml b/rules/go/gosec/blocklist/cgi.yml index 701910652..6f2df5f3e 100644 --- a/rules/go/gosec/blocklist/cgi.yml +++ b/rules/go/gosec/blocklist/cgi.yml @@ -9,48 +9,23 @@ languages: - go metadata: description: Usage of vulnerable CGI package - remediation_message: | + remediation_message: |- ## Description - Using the `net/http/cgi` package in Go, especially with versions prior to 1.6.3, exposes the application to the Httpoxy attack, a vulnerability identified as CVE-2016-5386. This vulnerability arises from the way CGI and FastCGI protocols handle certain environment variables, which can be manipulated to intercept and redirect outgoing HTTP requests made by the web application. + The `net/http/cgi` package in Go versions before 1.6.3 is vulnerable to the Httpoxy attack. This vulnerability, identified as CVE-2016-5386, occurs because of how CGI and FastCGI protocols manage certain environment variables. Attackers can exploit this to intercept and redirect outgoing HTTP requests from the web application. ## Remediations - ✅ Update Go Version + - **Do** update your Go version to 1.6.3 or later to mitigate this vulnerability. + - **Do** opt for alternative packages, like the standard `net/http` library, for handling HTTP requests that do not use the CGI protocol. + - **Do not** use the `net/http/cgi` package if your Go version is older than 1.6.3, as it is vulnerable to the Httpoxy attack. + ```go + import "net/http/cgi" + ``` + - **Do** ensure that environment variables like `HTTP_PROXY` are not unintentionally exposed, as this can be leveraged for Httpoxy attacks. - Ensure you are using a version of Go that is 1.6.3 or later, where this vulnerability is patched. + ## References - ```sh - # Check Go version and update if necessary - go version - # Follow Go's update instructions if your version is < 1.6.3 - ``` - - ✅ Use Alternative Packages - - Refrain from using CGI where possible. Utilize alternative packages and methods to handle HTTP requests which do not rely on the CGI protocol. - - ```go - // Use the standard net/http package instead - import "net/http" - ``` - - ❌ Don't Use `net/http/cgi` in Older Versions - - Do not use the `net/http/cgi` package if you are operating on Go versions older than 1.6.3 as they are susceptible to the Httpoxy vulnerability. - - ```go - // This import is vulnerable to Httpoxy in Go < 1.6.3 - import "net/http/cgi" - ``` - - ❌ Avoid Exposing Environment Variables - - Ensure that the environment variables such as `HTTP_PROXY` are not being exposed unintentionally, as this can be leveraged for Httpoxy attacks. - - ## Resources - - - [CVE-2016-5386 Detail](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-5386) - [Httpoxy.org](https://httpoxy.org/) cwe_id: diff --git a/rules/go/gosec/blocklist/des.yml b/rules/go/gosec/blocklist/des.yml index b9e2df06b..027a06da4 100644 --- a/rules/go/gosec/blocklist/des.yml +++ b/rules/go/gosec/blocklist/des.yml @@ -9,64 +9,17 @@ languages: - go metadata: description: "Import of weak encryption algorithm (DES)" - remediation_message: | + remediation_message: |- ## Description - The Data Encryption Standard (DES) is an outdated symmetric-key algorithm for encryption. Officially deemed insecure and no longer recommended for use, DES was withdrawn by the National Institute of Standards and Technology (NIST) as a standard in 2005, primarily because of its 56-bit key size, which is vulnerable to brute-force attacks. + The Data Encryption Standard (DES) is an outdated encryption algorithm that is officially considered insecure and is no longer recommended for use. DES was withdrawn as a standard by the National Institute of Standards and Technology (NIST) in 2005 because of its 56-bit key size which makes it susceptible to brute-force attacks. - ## Remediation + ## Remediations - To ensure the confidentiality and integrity of sensitive data, it is crucial to utilize a modern and secure encryption algorithm. The use of Advanced Encryption Standard (AES) with a key size of 256 bits (AES-256) is recommended for its strong security properties and widespread acceptance as a replacement for DES. + - **Do not** use DES for encrypting data. Its known vulnerabilities and insecurities make it an unsuitable choice for protecting sensitive information. + - **Do** implement the Advanced Encryption Standard (AES) with a key size of 256 bits (AES-256) for encryption. AES-256 is recognized for its strong security properties and is widely accepted as a secure replacement for DES. - ✅ Implement AES-256 for Strong Encryption - - ```go - // Use AES-256 for secure encryption by initializing a 32-byte key for AES-256 - key := make([]byte, 32) - if _, err := io.ReadFull(rand.Reader, key); err != nil { - log.Fatal(err) - } - - // Create a new cipher block from the key - blockCipher, err := aes.NewCipher(key) - if err != nil { - log.Fatal(err) - } - - // Use Galois/Counter Mode (GCM) for both encryption and decryption - aead, err := cipher.NewGCM(blockCipher) - if err != nil { - log.Fatal(err) - } - - var encrypted = []byte{} - var nonce = []byte{} - - // Encrypt a message with AES-256 using GCM - { - msg := []byte("Some secret message") - // Ensure nonces are unique for each encryption to maintain security - nonce = make([]byte, 12) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { - log.Fatal(err) - } - encrypted = aead.Seal(nil, nonce, msg, nil) - } - - // Decrypt the message securely - { - msg, err := aead.Open(nil, nonce, encrypted, nil) - if err != nil { - log.Fatal(err) - } - fmt.Printf("Decrypted: %s\n", msg) - } - ``` - - ❌ Do Not Use Deprecated Algorithms - Avoid using deprecated cryptographic algorithms such as DES, as they do not provide adequate security against modern threats and attacks. - - ## Resources + ## References - [NIST Recommendations](https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final) - [AES-256 Encryption](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) diff --git a/rules/go/gosec/blocklist/md5.yml b/rules/go/gosec/blocklist/md5.yml index 79541633b..200107415 100644 --- a/rules/go/gosec/blocklist/md5.yml +++ b/rules/go/gosec/blocklist/md5.yml @@ -9,35 +9,18 @@ languages: - go metadata: description: "Import of weak hashing library (MD5)" - remediation_message: | + remediation_message: |- ## Description - MD5 is a widely used cryptographic hash function that produces a 128-bit (16-byte) hash value. It's commonly used to check the integrity of files. However, MD5 is not collision-resistant; this means that different inputs may produce the same output hash. MD5's vulnerabilities and the feasibility of collision attacks have rendered it obsolete for security-related purposes, particularly digital signatures, SSL certificates, and cryptographic message authentication. + Using a weak hashing library like MD5 increases the risk of data breaches. MD5 is vulnerable to collision attacks, where two different inputs produce the same output, compromising data integrity and security. - ## Remediation + ## Remediations - Given the vulnerabilities of MD5, it is highly recommended to switch to more secure hashing algorithms. For hashing purposes that do not involve passwords, such as verifying file integrity or generating unique identifiers, SHA-3 or BLAKE2 can be used due to their stronger cryptographic properties. + - **Do not** use MD5 for hashing. It is considered a weak hash algorithm and can compromise data security. + - **Do** use stronger hashing algorithms such as SHA-3 or BLAKE2 for general hashing purposes, such as file integrity checks or generating unique identifiers. + - **Do** use recommended algorithms such as bcrypt or Argon2id for password hashing, as these are designed to be slower and therefore more effective against brute-force attacks. - ✅ Use SHA-3 or BLAKE2 for General Hashing Needs - - ```go - // BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, and SHA-2, and as secure as the latest standard SHA-3 - fileContents := []byte("some file contents to create hash for") - blake2bHasher, err := blake2b.New512(nil) - if err != nil { - log.Fatal(err) - } - hashedValue := blake2bHasher.Sum(fileContents) - fmt.Printf("%s\n", hex.EncodeToString(hashedValue)) - ``` - - For password hashing, where the hash functions need to be slow to combat brute-force attacks, bcrypt or Argon2id should be used. These algorithms are designed to be computationally intensive to hash and verify, which helps protect against password cracking attempts. - - ✅ Adopt bcrypt or Argon2id for Password Hashing - - The bcrypt algorithm is a good choice for password hashing as it allows you to adjust the cost (computational complexity) and is widely supported. Argon2id is the winner of the Password Hashing Competition and offers a good balance between resistance to GPU cracking attacks and usability. - - ## Resources + ## References - [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html) diff --git a/rules/go/gosec/blocklist/rc4.yml b/rules/go/gosec/blocklist/rc4.yml index 16f6469cd..e57ad62ee 100644 --- a/rules/go/gosec/blocklist/rc4.yml +++ b/rules/go/gosec/blocklist/rc4.yml @@ -9,60 +9,17 @@ languages: - go metadata: description: "Import of weak encryption algorithm (RCA)" - remediation_message: | + remediation_message: |- ## Description - RC4 is a stream cipher that was once popular for its simplicity and speed in operation. However, extensive research over the years has revealed multiple vulnerabilities, rendering RC4 insecure in most contexts. Its weaknesses in key scheduling and the generation of non-random bytes have led to successful cryptanalysis and practical attacks, making it unsuitable for securing data. + The RC4 encryption algorithm is outdated and vulnerable. It has been found to have significant security flaws, including predictable key generation and weak randomization, which have been exploited in various attacks. These vulnerabilities make RC4 unsuitable for secure data encryption. - ## Remediation + ## Remediations - With the known vulnerabilities of RC4, it's essential to move to a more secure cipher. AES (Advanced Encryption Standard) is the recommended replacement because it has undergone extensive scrutiny and is considered secure against cryptanalysis. + - **Do not** use RC4 for encrypting data. Its vulnerabilities to cryptanalysis and practical attacks compromise data security. + - **Do** switch to AES-256 for encryption. AES-256 is a secure and widely accepted standard that provides strong protection against attacks. Using AES-256 ensures compliance with current security standards and provides a robust defense against known cryptographic attacks. - ✅ Switch to AES-256 for Robust Encryption - - ```go - // 32 byte keys will set up AES-256, which is a secure block cipher that has become the industry standard for encryption. - key := make([]byte, 32) - if _, err := io.ReadFull(rand.Reader, key); err != nil { - log.Fatal(err) - } - - blockCipher, err := aes.NewCipher(key) - if err != nil { - log.Fatal(err) - } - - aead, err := cipher.NewGCM(blockCipher) - if err != nil { - log.Fatal(err) - } - - var encrypted = []byte{} - var nonce = []byte{} - // Encryption routine - { - msg := []byte("Some secret message") - // Note that the key must be rotated after every 2^32 uses of a single nonce-value to avoid cipher text repetition. - nonce = make([]byte, 12) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { - log.Fatal(err) - } - encrypted = aead.Seal(nil, nonce, msg, nil) - } - - // Decryption routine - { - msg, err := aead.Open(nil, nonce, encrypted, nil) - if err != nil { - log.Fatal(err) - } - fmt.Printf("Decrypted: %s\n", msg) - } - ``` - - Using AES-256 ensures that your encryption mechanism meets current security standards and is robust against known attacks. AES has been widely adopted across various industries and has proven its reliability over time. - - ## Resources + ## References - [NIST Guidelines on Cryptography](https://csrc.nist.gov/publications/detail/sp/800-38a/final) cwe_id: diff --git a/rules/go/gosec/blocklist/sha1.yml b/rules/go/gosec/blocklist/sha1.yml index 41e4d650e..b9f798d3d 100644 --- a/rules/go/gosec/blocklist/sha1.yml +++ b/rules/go/gosec/blocklist/sha1.yml @@ -9,30 +9,18 @@ languages: - go metadata: description: "Import of weak hashing library (SHA-1)" - remediation_message: | + remediation_message: |- ## Description - The SHA-1 hashing algorithm is no longer considered secure against well-funded attackers. It is vulnerable to collision attacks, which means it's possible to generate two different inputs that result in the same SHA-1 hash, undermining the hash's uniqueness and security. Due to these vulnerabilities, it is advised to discontinue using SHA-1 for cryptographic security. + The SHA-1 hashing algorithm is outdated and vulnerable to collision attacks, where two distinct inputs produce the same output hash. This flaw compromises the algorithm's ability to securely verify data integrity and authenticity, making it unsuitable for cryptographic security. - ## Remediation + ## Remediations - When choosing a hashing algorithm for cryptographic purposes, it's important to select one that is resistant to collisions and other attack vectors. SHA-3 and BLAKE2 are both excellent choices for non-password-based hashing requirements due to their strong cryptographic properties. + - **Do not** use SHA-1 for cryptographic purposes or to ensure data integrity. Its susceptibility to collision attacks poses a significant security risk. + - **Do** use stronger hashing algorithms such as SHA-3 or BLAKE2 for general hashing purposes, such as file integrity checks or generating unique identifiers. + - **Do** use recommended algorithms such as bcrypt or Argon2id for password hashing, as these are designed to be slower and therefore more effective against brute-force attacks. - ✅ For General Hashing Needs, Use SHA-3 or BLAKE2 - - Choose SHA-3 or BLAKE2 for their resistance to known hash attack vectors, ensuring the integrity and uniqueness of your data fingerprints. - - ✅ For Password Hashing, Prefer bcrypt or Argon2id - - For password hashing specifically, bcrypt or Argon2id are recommended. These algorithms are designed to be computationally intensive, which helps protect against brute-force attacks. - - ❌ Discontinue Using SHA-1 for Security Purposes - - Given its vulnerabilities, avoid using SHA-1 in any security context to prevent potential collision attacks. - - The code snippet provided is unrelated to the hashing algorithms and seems to be a continuation of the previous examples for encryption with AES-256. Ensure your hashing and encryption strategies are correctly implemented as per their intended use-cases. - - ## Resources + ## References - [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html) - [NIST Policy on Hash Functions](https://csrc.nist.gov/projects/hash-functions) diff --git a/rules/go/gosec/crypto/bad_tls_settings.yml b/rules/go/gosec/crypto/bad_tls_settings.yml index 5d5cf734c..1aebec758 100644 --- a/rules/go/gosec/crypto/bad_tls_settings.yml +++ b/rules/go/gosec/crypto/bad_tls_settings.yml @@ -39,34 +39,23 @@ languages: - go metadata: description: "Usage of insecure cipher" - remediation_message: | + remediation_message: |- ## Description - A security concern arises when a cryptographically insecure cipher suite is used in an application. Such cipher suites may be vulnerable to various types of attacks, reducing the security of the communication channel. + Using an insecure cipher suite in your application introduces a significant security risk. These weak cipher suites are susceptible to various attacks, compromising the security of your communications. - ## Remediation + ## Remediations - To enhance the security of TLS connections, it is crucial to use up-to-date and secure cipher suites and protocols. Here are the recommended steps to ensure the use of secure ciphers: + - **Do** use modern, secure cipher suites that offer Perfect Forward Secrecy (PFS), such as ECDHE-RSA-AES256-GCM-SHA384 or ECDHE-RSA-CHACHA20-POLY1305. PFS ensures that even if future private keys are compromised, past communications remain secure. + - **Do** adopt TLS 1.3 whenever possible, as it includes enhancements that offer better security against various attacks. The Go standard library, for instance, automatically prefers the most secure protocol and cipher suite available. + ```go + cfg := &tls.Config{ + MinVersion: tls.VersionTLS13, + } + ``` + - **Do not** use obsolete or insecure cipher suites. Avoid any cipher suites that lack support for modern security standards or have known vulnerabilities. - ✅ Use Modern, Secure Cipher Suites - - Select cipher suites that are known to be secure and have properties such as Perfect Forward Secrecy (PFS), which protects past communications even if future private keys are compromised. - - ✅ Adopt TLS 1.3 Where Possible - - TLS 1.3 should be the preferred protocol as it includes improvements over previous versions, making it more secure against various attacks. Go's standard library will automatically prefer the most secure protocol and cipher suite available during the TLS handshake. - - ✅ Configure TLS Properly If Using TLS 1.0-1.2 - - In cases where TLS 1.3 is not an option and you must use TLS 1.0-1.2, ensure to configure the cipher suites to use those that support PFS, as listed below. - - ❌ Avoid Using Obsolete or Insecure Cipher Suites - - Avoid any cipher suites that do not support modern security standards, including those without PFS or with known vulnerabilities. - - The provided Go code examples demonstrate how to configure the `tls.Config` struct for a Go server to use TLS 1.3 or to specify a list of secure cipher suites when using TLS 1.0-1.2. - - ## Resources + ## References - [Mozilla's SSL Configuration Generator](https://ssl-config.mozilla.org/) - [OWASP TLS Cipher String Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/TLS_Cipher_String_Cheat_Sheet.html) diff --git a/rules/go/gosec/crypto/insecure_ignore_host_key.yml b/rules/go/gosec/crypto/insecure_ignore_host_key.yml index 0b01ef710..90aeecefe 100644 --- a/rules/go/gosec/crypto/insecure_ignore_host_key.yml +++ b/rules/go/gosec/crypto/insecure_ignore_host_key.yml @@ -4,30 +4,18 @@ languages: - go metadata: description: "Missing verification of host keys" - remediation_message: | + remediation_message: |- ## Description - The security vulnerability identified pertains to the application neglecting the verification of host keys during SSH connections. Host keys are crucial for confirming the server's identity, preventing Man-in-the-Middle (MitM) attacks where an attacker could impersonate the server. When these keys are ignored, the client cannot guarantee the authenticity of the server it connects to. + Lacking verification of host key during SSH connections compromises the security of your application. Host keys are essential for verifying the server's identity to prevent Man-in-the-Middle (MitM) attacks, where an attacker could pose as the server. Without this verification, there's no way to ensure the server's authenticity. - ## Remediation + ## Remediations - To mitigate this risk, it is essential to implement proper host key checking: + - **Do not** use `ssh.InsecureIgnoreHostKey` as a `HostKeyCallback` function. This method bypasses any form of host validation, making your application vulnerable to attacks. + - **Do** implement host key verification. For example, use the `knownhosts` package from Go's `x/crypto/ssh` to check server keys against a list of known hosts, similar to OpenSSH's approach. + - **Do not** disable host key checking in your production code. While it might seem convenient for development or testing environments, it significantly increases the risk of security breaches. - ✅ Implement Host Key Verification - - Use the `knownhosts` package from Go's `x/crypto/ssh` to validate server keys against known hosts. This mirrors the functionality found in OpenSSH. - - ✅ Avoid Disabling Host Key Checking - - Never disable host key checking in production code. While it might be convenient for testing, it opens up security vulnerabilities. - - ❌ Do Not Use `InsecureIgnoreHostKey` - - Although available, using `ssh.InsecureIgnoreHostKey` as a `HostKeyCallback` function should be strictly avoided as it does not offer any form of host validation. - - Below is a code snippet showing how to set up an SSH `ClientConfig` in Go to use the `knownhosts` callback for server verification: - - ## Resources + ## References - [GoDoc for x/crypto/ssh](https://pkg.go.dev/golang.org/x/crypto/ssh) - [Secure use of SSH - OpenSSH](https://www.openssh.com/) diff --git a/rules/go/gosec/crypto/weak_crypto.yml b/rules/go/gosec/crypto/weak_crypto.yml index 466138259..368645ce6 100644 --- a/rules/go/gosec/crypto/weak_crypto.yml +++ b/rules/go/gosec/crypto/weak_crypto.yml @@ -10,32 +10,19 @@ languages: - go metadata: description: "Usage of weak hashing library" - remediation_message: | + remediation_message: |- ## Description - The issue identified indicates the use of a cryptographic algorithm that is no longer considered secure by current standards. Such algorithms can compromise data confidentiality and integrity, making it vulnerable to decryption and tampering by unauthorized parties. + Your code uses a weak hashing library, which means it relies on cryptographic algorithms that are no longer secure. This vulnerability can lead to compromised data confidentiality and integrity, as it makes the data susceptible to unauthorized decryption and tampering. - ## Remediation + ## Remediations - To ensure the security of the data, adhere to the following guidelines: + - **Do** replace weak or outdated algorithms with strong, modern alternatives. For encryption, use AES (Advanced Encryption Standard), and for hashing, opt for SHA-256 or higher. + - **Do** always use the latest versions of cryptographic libraries. These versions are more likely to use secure algorithms and settings by default. + - **Do not** use cryptographic algorithms that have been deprecated due to known vulnerabilities. Avoid MD5, SHA-1, or DES for any cryptographic operations. + - **Do not** attempt to create custom cryptographic solutions. Instead use well-reviewed and tested standard cryptographic libraries to ensure security. - ✅ Employ Strong Cryptographic Algorithms - - Replace deprecated or weak algorithms with strong, modern alternatives such as AES (Advanced Encryption Standard) for encryption, and SHA-256 or higher for hashing. - - ✅ Keep Libraries Updated - - Use the latest versions of cryptographic libraries, as they are more likely to default to secure algorithms and settings. - - ❌ Avoid Deprecated Algorithms - - Do not use cryptographic algorithms that have been deprecated due to vulnerabilities, such as MD5, SHA-1, or DES. - - ❌ Do Not Reinvent Cryptography - - Avoid custom cryptographic implementations as they are more susceptible to errors. Instead, rely on well-reviewed and tested standard cryptographic libraries. - - ## Resources + ## References - [NIST Cryptographic Standards and Guidelines](https://csrc.nist.gov/publications/sp) - [Cryptography Coding Standard](https://cryptocoding.net/index.php/Coding_rules) diff --git a/rules/go/gosec/crypto/weak_key_strength.yml b/rules/go/gosec/crypto/weak_key_strength.yml index 8bacf172e..0f472b55a 100644 --- a/rules/go/gosec/crypto/weak_key_strength.yml +++ b/rules/go/gosec/crypto/weak_key_strength.yml @@ -7,46 +7,20 @@ languages: - go metadata: description: "Usage of inadequate encryption strength" - remediation_message: | + remediation_message: |- ## Description - The application generates an RSA key with a bit length that is shorter than the current recommended minimum of 2048 bits. Keys shorter than 2048 bits are considered insecure due to advancements in computational power which could potentially allow them to be factored, thereby breaking the encryption. + Your application uses RSA encryption with a key length shorter than the recommended 2048 bits. Keys under 2048 bits are vulnerable because of the increasing power of modern computers, which could break the encryption by factoring the key. - ## Remediation + ## Remediations - To ensure the security of RSA keys, follow these guidelines: + - **Do** generate RSA keys with a minimum of 2048 bits. This meets NIST recommendations and protects against the risk of keys being compromised by advancements in computing power. Keys shorter than 2048 bits do not provide adequate protection against brute-force attacks. + ```go + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + ``` + - **Do** adhere to industry standards and guidelines for cryptographic practices to ensure the security of your data. - ✅ Use Sufficient Key Length - - Generate RSA keys with a minimum length of 2048 bits to align with NIST recommendations and safeguard against future advancements in computing power that could compromise keys of shorter lengths. - - ```go - // Example of generating a secure RSA key with 2048 bits - import ( - "crypto/rand" - "crypto/rsa" - "log" - ) - - func generateSecureKey() { - // Use at least 2048 bits for secure RSA keys - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - log.Fatalf("Error generating RSA key: %v", err) - } - // privateKey can now be used for secure cryptographic operations - } - ``` - - ❌ Avoid Short Keys - - Do not use RSA keys that are less than 2048 bits in length, as they do not offer sufficient protection against brute-force attacks. - - ❌ Don't Ignore Industry Standards - - Always follow industry standards and guidelines for cryptographic practices to maintain the integrity and confidentiality of data. - - ## Resources + ## References - [NIST Special Publication 800-57 Part 1](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final) cwe_id: diff --git a/rules/go/gosec/crypto/weak_random.yml b/rules/go/gosec/crypto/weak_random.yml index b19eb6b0f..30b346099 100644 --- a/rules/go/gosec/crypto/weak_random.yml +++ b/rules/go/gosec/crypto/weak_random.yml @@ -40,49 +40,18 @@ languages: - go metadata: description: "Usage of weak Pseudo-Random Number Generator (PRNG)" - remediation_message: | + remediation_message: |- ## Description - The `math/rand` package in Go is designed for generating pseudorandom numbers, which are not secure for cryptographic purposes. These numbers are predictable if the seed is known, which could compromise the security of applications using them for secrets, tokens, or other security-sensitive features. + The `math/rand` package in Go generates pseudorandom numbers that are not secure for cryptographic purposes. These numbers can be predicted if the seed is known, posing a risk to the security of applications that use them for generating secrets, tokens, or other security-sensitive elements. ## Remediations - To securely generate random numbers in a security-sensitive context, implement the following measures: + - **Do** use `crypto/rand` instead of `math/rand` for generating random numbers in contexts where security is crucial. This ensures the randomness is cryptographically secure and unpredictable. + - **Do not** use `math/rand` for generating random numbers in cryptographic applications, including but not limited to key generation, authentication tokens, or security challenges. + - **Do not** initialize `math/rand` with predictable seeds, such as timestamps or other easily guessable values, if it is required to use `math/rand`. - ✅ Use Cryptographically Secure Randomness - - Replace the use of `math/rand` with `crypto/rand` to ensure that the random numbers generated are suitable for cryptographic use and are not predictable. - - ```go - import ( - "crypto/rand" - "log" - "math/big" - ) - - func generateSecureRandomNumber() *big.Int { - // Generate a cryptographically secure random number - randomNumber, err := rand.Int(rand.Reader, big.NewInt(1<<62)) - if err != nil { - log.Fatalf("Failed to generate a secure random number: %v", err) - } - return randomNumber - } - ``` - - ✅ Audit Existing Code - - Review your codebase for instances where `math/rand` is used in security-sensitive contexts and update them to use `crypto/rand`. - - ❌ Do Not Use Predictable Seeds - - Avoid initializing `math/rand` with predictable seeds, such as timestamps or other easily guessable values, especially in a security context. - - ❌ Don't Use for Security Purposes - - Never rely on `math/rand` for generating random numbers in cryptographic applications, like key generation, authentication tokens, or any form of security challenge. - - ## Resources + ## References - [crypto/rand package documentation](https://pkg.go.dev/crypto/rand) diff --git a/rules/go/gosec/crypto/weak_tls_version.yml b/rules/go/gosec/crypto/weak_tls_version.yml index df4c20b4d..34464fac1 100644 --- a/rules/go/gosec/crypto/weak_tls_version.yml +++ b/rules/go/gosec/crypto/weak_tls_version.yml @@ -5,67 +5,25 @@ languages: - go metadata: description: "Usage of deprecated TLS version" - remediation_message: | + remediation_message: |- ## Description - TLS (Transport Layer Security) versions 1.1 and 1.0 have been deprecated due to known security vulnerabilities that can expose sensitive data to interception and attacks. Using these versions can put data transmissions at risk. + TLS (Transport Layer Security) versions 1.0 and 1.1 have known vulnerabilities and using them introduces security risks to your application. These outdated TLS versions can lead to the interception and compromise of sensitive data during transmission. ## Remediations - To ensure secure data transmission, you should enforce the use of TLS 1.3, which includes security enhancements over its predecessors. The following steps can be taken: - - ✅ Enforce TLS 1.3 - - Update your server configuration to support and prefer TLS 1.3, which includes modern security features and mitigates known vulnerabilities found in older versions. - - ✅ Configure Go’s TLS Library - - Set `MinVersion` in the `tls.Config` struct to `tls.VersionTLS13` to ensure that the server only accepts TLS 1.3 connections. - - ```go - import ( - "crypto/tls" - "log" - "net/http" - "time" - ) - - func main() { - cert, err := tls.LoadX509KeyPair("server.crt", "server.key") - if err != nil { - log.Fatalf("failed to load key pair: %s", err) - } - - cfg := &tls.Config{ - Certificates: []tls.Certificate{cert}, - MinVersion: tls.VersionTLS13, // Enforce TLS 1.3 - } - - srv := &http.Server{ - Addr: ":8999", // Listen on port 8999 - TLSConfig: cfg, - ReadTimeout: time.Minute, - WriteTimeout: time.Minute, - } - - log.Printf("Server is starting...") - log.Fatal(srv.ListenAndServeTLS("", "")) // TLS cert and key are already provided in the TLSConfig - } - ``` - - ✅ Perfect Forward Secrecy (PFS) - - TLS 1.3 configurations ensure PFS by default, which protects past communications even if future session keys are compromised. - - ✅ Regularly Update Dependencies - - Keep your Go version and dependencies up-to-date to benefit from the latest security fixes and improvements. - - ❌ Do Not Use Deprecated TLS Versions - - Avoid configuring your server to accept TLS 1.0 or 1.1. Remove these options from your TLS configuration to prevent downgrade attacks. - - ## Resources + - **Do** enforce the use of TLS 1.3 when configuring Go's TLS library. TLS 1.3 offers significant security improvements, helping to protect data from known vulnerabilities present in older versions. + ```go + cfg := &tls.Config{ + MinVersion: tls.VersionTLS13, + ... + } + ``` + - **Do** utilize configurations that support Perfect Forward Secrecy (PFS) with TLS 1.3. PFS enhances security by ensuring that past communications remain secure even if future session keys are compromised. + - **Do** regularly update your Go version and dependencies to incorporate the latest security fixes and improvements. + - **Do not** configure your server to accept TLS versions 1.0 or 1.1. Removing these options from your TLS configuration is crucial to prevent downgrade attacks. + + ## References - [IETF's Deprecation of TLS 1.0 and 1.1](https://tools.ietf.org/html/rfc8996) - [OWASP TLS Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html) diff --git a/rules/go/gosec/file_permissions/file_perm.yml b/rules/go/gosec/file_permissions/file_perm.yml index 74c788bfd..8c6a51f35 100644 --- a/rules/go/gosec/file_permissions/file_perm.yml +++ b/rules/go/gosec/file_permissions/file_perm.yml @@ -26,58 +26,26 @@ languages: - go metadata: description: "Permissive file assignment" - remediation_message: | + remediation_message: |- ## Description - When creating or updating files, ensuring proper file permissions is crucial to maintain security. Overly permissive file settings can allow unauthorized users to read, modify, or execute files, which could lead to information disclosure, data tampering, or compromise of the system. + Setting overly permissive file permissions exposes your system to risks such as unauthorized access, data tampering, and potential system compromise. This vulnerability arises when files are created or updated without adequately restrictive permissions, allowing unauthorized users to read, modify, or execute files. ## Remediations - To prevent unauthorized access, it's important to set restrictive file permissions, particularly when sensitive data is involved. Here's how to manage file permissions in Go: - - ✅ Restrict File Permissions - - Set file permissions to allow only the necessary access level for the application. Avoid using permissions like `0777`, which allows read, write, and execute permissions for all users. - - ✅ Use Go’s `os` Package - - Utilize the `os.OpenFile` function with the appropriate file permission flags. - - ✅ Recommended File Permissions - - - `0400` grants read-only access to the file's owner. - - `0200` grants write-only access to the file's owner. - - `0600` grants read and write access to the file's owner and is commonly used for files that need to be both read from and written to by the application. - - ```go - import ( - "log" - "os" - ) - - func main() { - // Use os.OpenFile to create a file with restricted permissions - // 0600 permission: Read and write for the owner, no permissions for others - f, err := os.OpenFile("file.txt", os.O_CREATE|os.O_WRONLY, 0600) - if err != nil { - log.Fatalf("failed to create file: %s", err) - } - defer f.Close() - // Continue to work with the file here - } - ``` - - ✅ Verify File Permissions - - After file creation, check the file permissions to ensure they are set correctly. - - ✅ Secure Default Permissions - - If you are developing an application that creates multiple files, consider setting umask in your application to a secure default. - - ✅ Review File Permission Settings - - Regularly audit file permissions to ensure they adhere to the principle of least privilege. + - **Do not** use overly permissive file permissions, such as `0777`, which grants read, write, and execute permissions to all users. + - **Do** set file permissions to restrict access appropriately: + - `0400` for read-only access by the file's owner. + - `0200` for write-only access by the file's owner. + - `0600` for read and write access by the file's owner, suitable for files that the application needs to read from and write to. + - **Do** use Go's `os` package to manage file permissions effectively. For example, use `os.OpenFile` with appropriate permission flags such as 0600. + ```go + f, err := os.OpenFile("file.txt", os.O_CREATE|os.O_WRONLY, 0600) + ... + ``` + - **Do** verify file permissions after creation or update to ensure they are set as intended. + - **Do** consider setting umask to a secure default, if your application creates multiple files, to ensure that files are created with safe default permissions. + - **Do** regularly review and audit file permissions in your system to ensure they adhere to the principle of least privilege, minimizing the access level to what is strictly necessary for operational functionality. cwe_id: - 276 diff --git a/rules/go/gosec/file_permissions/mkdir.yml b/rules/go/gosec/file_permissions/mkdir.yml index 24174d158..ccfb1225f 100644 --- a/rules/go/gosec/file_permissions/mkdir.yml +++ b/rules/go/gosec/file_permissions/mkdir.yml @@ -20,56 +20,26 @@ languages: - go metadata: description: "Permissive folder creation" - remediation_message: | + remediation_message: |- ## Description - Setting correct directory permissions is critical to maintaining the security of a system. Directories with overly permissive access rights can become a vector for security breaches, allowing unauthorized users to add, remove, or change files, potentially leading to the execution of malicious code, data leaks, or system compromise. + Incorrect directory permissions can severely compromise system security.Directories with overly permissive access rights can allow unauthorized users to manipulate files, potentially leading to malicious code execution, data breaches, or full system compromise. ## Remediations - When creating directories, apply the principle of least privilege to ensure users have only the permissions necessary for their role: - - ✅ Restrict Directory Permissions - - Use permissions that restrict access to what is strictly necessary for the operation of the application. Avoid overly permissive settings such as `0777`, which allow all users to read, write, and execute. - - ✅ Use Go’s `os` Package - - Leverage the `os.Mkdir` or `os.MkdirAll` function with appropriate permission flags to create directories. - - ✅ Recommended Directory Permissions - - - `0700` gives the owner read, write, and execute permissions, with no access for group and others, suitable for private user data. - - `0750` gives the owner full permissions, the group read and execute permissions, and no permissions for others, which is commonly used for directories that need to be shared within a group. - - ```go - import ( - "log" - "os" - ) - - func main() { - // Use os.Mkdir to create a directory with restricted permissions - // 0700 permission: Full control for the owner, no permissions for group and others - err := os.Mkdir("secure_directory", 0700) - if err != nil { - log.Fatalf("failed to create directory: %s", err) - } - // Continue setting up the directory here - } - ``` - - ✅ Verify Directory Permissions - - After creating a directory, confirm the permissions to ensure they have been set correctly. - - ✅ Set Secure Umask - - Consider setting a secure umask in your application or user profile to ensure that all newly created files and directories have restrictive permissions by default. - - ✅ Regular Auditing - - Implement regular checks of directory permissions as part of your security auditing procedures to identify and correct any permissions that are too broad. + - **Do not** use overly broad permissions like `0777` for directories, as this allows all users to read, write, and execute files, posing a significant security risk. + ```go + os.Mkdir("example_directory", 0777) // unsafe + ``` + - **Do** set directory permissions to: + - `0700` for private user data, granting full control to the owner only. + - `0750` for directories requiring group access, granting full control to the owner and read/execute to the group. + ```go + os.Mkdir("secure_directory", 0700) + ``` + - **Do** verify file permissions after creation or update to ensure they are set as intended. + - **Do** consider setting umask to a secure default, if your application creates multiple files, to ensure that files are created with safe default permissions. + - **Do** regularly review and audit file permissions in your system to ensure they adhere to the principle of least privilege, minimizing the access level to what is strictly necessary for operational functionality. cwe_id: - 276 diff --git a/rules/go/gosec/filesystem/decompression_bomb.yml b/rules/go/gosec/filesystem/decompression_bomb.yml index 88e06f767..bf05449c4 100644 --- a/rules/go/gosec/filesystem/decompression_bomb.yml +++ b/rules/go/gosec/filesystem/decompression_bomb.yml @@ -44,74 +44,23 @@ languages: - go metadata: description: "Missing configuration against decompression bomb" - remediation_message: | + remediation_message: |- ## Description - Decompression bombs are a form of attack against an application or service that processes compressed files. The attacker crafts a compressed file that is small in size, but when decompressed, expands to a much larger size that is disproportionate to the original. This can exhaust system resources like CPU, memory, or disk space, leading to a Denial of Service (DoS). + Decompression bombs pose a risk by exploiting applications that process compressed files. These attacks involve a compressed file that is small in size but expands to a significantly larger size when decompressed. This can overwhelm system resources such as CPU, memory, or disk space, causing a Denial of Service (DoS). ## Remediations - Implement measures to mitigate the impact of decompression bombs: - - ✅ Limit Decompression Size - - Use `io.LimitReader` to restrict the amount of data that a reader will decompress. This prevents the decompression of large files that could fill up memory or disk space. - - ✅ Monitor Resource Usage - - Implement resource monitoring to watch for unexpected spikes in CPU, memory, or disk usage, which could indicate an attempted decompression bomb attack. - - ✅ Input Validation - - Validate the size and type of the input before decompressing. If possible, reject files that do not meet expected criteria. - - ✅ Fail Safely - - Ensure that your application can handle errors from the decompression process safely, without crashing or becoming unresponsive. - - ✅ Regular Updates - - Keep compression libraries up to date with the latest security patches to protect against known vulnerabilities. - - ✅ User Education - - Educate users about the risks of decompression bombs if they are able to upload compressed files. - - ```go - import ( - "compress/gzip" - "io" - "log" - "os" - ) - - func main() { - // Open the gzip file - f, err := os.Open("example.gz") - if err != nil { - log.Fatal(err) - } - defer f.Close() - - // Create a gzip reader on the file - r, err := gzip.NewReader(f) - if err != nil { - log.Fatal(err) - } - defer r.Close() - - // Define a limit for decompression + - **Do** limit the decompression size. Use `io.LimitReader`, for example, to restrict the amount of data that a reader will decompress. This prevents the decompression of large files that could fill up memory or disk space. + ```go const maxDecompressSize = 10 * 1024 * 1024 // 10 MB - - // Limit the size of the reader limitedReader := io.LimitReader(r, maxDecompressSize) - - // Use the limited reader to decompress, preventing the decompression bomb from expanding fully - if _, err := io.Copy(os.Stdout, limitedReader); err != nil { - log.Fatal(err) - } - } - ``` + ``` + - **Do** monitor resource usage to detect unexpected increases in CPU, memory, or disk usage, which may indicate an attack. + - **Do** validate the size and type of input files before decompression. Reject files that do not meet predefined criteria to avoid processing potentially harmful data. + - **Do** ensure your application fails safely. It should handle decompression errors without crashing or becoming unresponsive. + - **Do** regularly update your compression libraries to incorporate the latest security patches and protect against known vulnerabilities. + - **Do** educate users about the risks associated with decompression bombs, especially if they have the ability to upload compressed files. cwe_id: - 409 diff --git a/rules/go/gosec/filesystem/dirtraversal.yml b/rules/go/gosec/filesystem/dirtraversal.yml index ae1b75647..4415f379b 100644 --- a/rules/go/gosec/filesystem/dirtraversal.yml +++ b/rules/go/gosec/filesystem/dirtraversal.yml @@ -17,57 +17,21 @@ languages: - go metadata: description: "Usage of Root directory mounting" - remediation_message: | + remediation_message: |- ## Description - Mounting the root directory (`/`) in an HTTP server is a significant security risk. It potentially allows anyone with access to the HTTP service to browse and access system files, which can lead to information disclosure, data breaches, or further exploitation of the system. + Mounting the root directory (`/`) on an HTTP server exposes a significant security risk. This setup could allow unauthorized individuals to access and browse system files, potentially leading to information disclosure, data breaches, or further system exploitation. ## Remediations - Implement the following measures to prevent exposing the entire filesystem through your web server: + - **Do not** mount the root directory as the web server's root. Doing so would make the entire filesystem accessible over the web. + - **Do** serve files from a specific directory designed for public access. Ensure this directory only contains files intended for public viewing. + - **Do** apply strict permissions to the directory being served. This ensures the server process accesses only the files it's meant to serve. + - **Do** utilize server configuration files, such as `.htaccess` for Apache HTTP Server, to control access to directories if your server supports it. + - **Do** consider isolating your server environment using containerization or virtualization techniques. This limits potential damage in case of a security breach by enforcing strict access controls. + - **Do** conduct regular audits of your filesystem and the files your server is hosting. This helps ensure no sensitive information is accidentally exposed. - ✅ Serve Specific Directory - - Change the `http.Dir` to serve files from a specific, safe directory intended for public access rather than the root directory. Ensure this directory contains only the files that are meant to be publicly accessible. - - ✅ Access Control - - Apply appropriate permissions to the directory being served to ensure that the server process can only access the files that it's supposed to serve. - - ✅ Use of Configuration Files - - If supported, use configuration files like `.htaccess` (for Apache HTTP Server) or equivalent server configuration to control access to directories. - - ✅ Isolate Environment - - Consider running your server in a containerized or virtualized environment with strict access controls to limit the potential damage in case of a security breach. - - ✅ Regular Audits - - Perform regular audits of the filesystem and the files being served to ensure that no sensitive information is being unintentionally exposed. - - ```go - import ( - "net/http" - "log" - ) - - func main() { - // Define the specific path to a directory to be served - const safePath = "/var/www/html/public" - - // Create a new file server handler that serves files from the safePath - fs := http.FileServer(http.Dir(safePath)) - - // Configure the server to handle requests to the root with the file server handler - http.Handle("/", http.StripPrefix("/", fs)) - - // Start the server - log.Fatal(http.ListenAndServe(":9000", nil)) - } - ``` - - ## Resources + ## References - [Go Documentation: http package](https://pkg.go.dev/net/http) - [OWASP: Securing File Uploads](https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload) diff --git a/rules/go/gosec/filesystem/filereadtaint.yml b/rules/go/gosec/filesystem/filereadtaint.yml index 7f7f583af..43dcddc98 100644 --- a/rules/go/gosec/filesystem/filereadtaint.yml +++ b/rules/go/gosec/filesystem/filereadtaint.yml @@ -43,84 +43,22 @@ languages: - go metadata: description: "Unsanitized user input in file path" - remediation_message: | + remediation_message: |- ## Description - Constructing file or path information dynamically, especially from user input, poses a significant security risk. If not handled correctly, attackers could manipulate these paths to access or manipulate sensitive files, leading to data breaches or system compromise. It is crucial to ensure that user input is not used directly to interact with the file system, as this can be exploited to perform path traversal attacks. + Using user input to dynamically construct file paths without proper sanitization introduces a high security risk. This practice can allow attackers to manipulate file paths to access or alter sensitive files, potentially leading to data breaches or system compromise. It is essential to sanitize user input before using it in file system operations to prevent path traversal attacks. ## Remediations - To mitigate the risks associated with dynamic file path construction from user inputs, apply the following best practices: + - **Do not** use unsanitized user input directly in file path construction. This can lead to path traversal vulnerabilities. + - **Do** hash or replace user input with a system-generated unique identifier when constructing file paths. This approach minimizes the risk of path manipulation. + - **Do** use `filepath.Base` to extract the filename from a path, discarding any directory information. This helps prevent directory traversal attacks. + ```go + safeFilename := filepath.Base(userInput) + ``` + - **Do** validate paths before accessing files to ensure they are within the intended directory. This validation acts as a safeguard against unauthorized file access. - ✅ Hash or Replace User Input - - When dealing with user input for file operations, hash the input or replace it with a system-generated unique identifier to prevent path manipulation. - - ✅ Use `filepath.Base` - - Extract only the filename from the path, ignoring any directory information, to avoid directory traversal vulnerabilities. - - ✅ Validate Paths Before Use - - Always perform validation on the resolved paths before accessing files to ensure they are within the expected directory. - - ```go - import ( - "crypto/rand" - "encoding/hex" - "io" - "log" - "path/filepath" - "strings" - ) - - // userData struct holds user-related data with a unique ID for file operations - type userData struct { - id string // Unique identifier for the filename - userFilename string // Original filename from the user, kept for reference - } - - // newUserData constructs a new userData instance with a random file ID - func newUserData(userFilename string) userData { - return userData{ - id: randomFileID(), // Use a random ID instead of user-provided filename - userFilename: userFilename, - } - } - - // randomFileID generates a secure random ID to be used as a filename - func randomFileID() string { - id := make([]byte, 16) - if _, err := io.ReadFull(rand.Reader, id); err != nil { - log.Fatal(err) - } - return hex.EncodeToString(id) - } - - func main() { - // Simulated user input, which may be malicious - data := newUserData("../../possibly/malicious") - - // Define a safe base path for file operations - const basePath = "/tmp/" - - // Resolve the full path using the safe base path and the random ID - resolvedPath, err := filepath.Join(basePath, filepath.Base(data.id)) - if err != nil { - log.Fatal(err) - } - - // Ensure the resolved path is within our designated base path - if !strings.HasPrefix(resolvedPath, basePath) { - log.Fatal("The resolved path does not start with the expected base path") - } - - // The file can now be safely accessed using resolvedPath - // Further file processing code would go here - } - ``` - - ## Resources + ## References - [OWASP Guide to Preventing Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal) cwe_id: diff --git a/rules/go/gosec/filesystem/poor_write_permissions.yml b/rules/go/gosec/filesystem/poor_write_permissions.yml index 97de323f2..1ca10298f 100644 --- a/rules/go/gosec/filesystem/poor_write_permissions.yml +++ b/rules/go/gosec/filesystem/poor_write_permissions.yml @@ -21,50 +21,21 @@ languages: - go metadata: description: "Permissive file creation" - remediation_message: | + remediation_message: |- ## Description - The application has been detected setting file permissions that are too permissive. This configuration could allow unauthorized users to read, write, or execute files, potentially leading to information disclosure or other security vulnerabilities. + Your application sets file permissions that are overly permissive. This oversight could let unauthorized individuals read, write, or execute files, which could lead to the exposure of sensitive information or other security risks. ## Remediations - To enhance security, file permissions should be set to more restrictive values, especially when the files contain sensitive information: + - **Do** use restrictive file permissions. Assign file permissions that strictly limit access, aligning with what your application genuinely needs: + - `0400` for read-only access by the file's owner. + - `0200` for write-only access by the file's owner. + - `0600` for read and write access by the file's owner, suitable for files that the application needs to read from and write to. + - **Do** set the correct permissions when you create or modify files. This step is crucial to prevent unauthorized access right from the start. + - **Do** regularly review and audit file permissions in your system to ensure they adhere to the principle of least privilege, minimizing the access level to what is strictly necessary for operational functionality. - ✅ Use Restrictive File Permissions - - Assign file permissions to limit access appropriately based on the application's requirements. - - - `0400`: Grants read-only access to the file for the owner. - - `0200`: Grants write-only access to the file for the owner. - - `0600`: Grants read and write access to the file for the owner. - - ✅ Apply Permissions During File Creation - - When creating or modifying files, set the appropriate permissions to prevent unauthorized access. - - ```go - import ( - "os" - "log" - ) - - func main() { - // Data to be written to the file - dat := []byte("sensitive data") - - // Write the data to 'file.txt' with read and write permissions for the owner only - if err := os.WriteFile("file.txt", dat, 0600); err != nil { - log.Fatalf("failed to write file: %s", err) - } - // File is now safely written with restricted permissions - } - ``` - - ✅ Review File Permission Settings - - Regularly audit the permissions of files to ensure they conform to the principle of least privilege. - - ## Resources + ## References - [Go Documentation for os Package](https://pkg.go.dev/os) - [Linux 'chmod' Command](https://linux.die.net/man/1/chmod) diff --git a/rules/go/gosec/filesystem/tempfile.yml b/rules/go/gosec/filesystem/tempfile.yml index 26ce04930..ab124946d 100644 --- a/rules/go/gosec/filesystem/tempfile.yml +++ b/rules/go/gosec/filesystem/tempfile.yml @@ -26,53 +26,21 @@ languages: - go metadata: description: "Permissive temporary file creation" - remediation_message: | + remediation_message: |- ## Description - The application has been observed creating files in shared system temporary directories, such as `/tmp` or `/var/tmp`, without the use of secure functions like `os.CreateTemp`. This practice is insecure because it opens up the possibility of symlink attacks, where an attacker could anticipate the temporary file name and create a symlink to a target file, leading to unauthorized file creation or overwriting when the application writes to what it believes is a temporary file. + Your application creates temporary files in shared system directories like `/tmp` or `/var/tmp` without using secure functions such as `os.CreateTemp`. This method is risky as it could lead to symlink attacks. In such attacks, an attacker predicts the name of the temporary file and creates a symlink to a target file. Consequently, when your application writes to the supposed temporary file, it could unintentionally overwrite or create unauthorized files. ## Remediations - To prevent symlink attacks and other vulnerabilities associated with the use of shared temporary directories: + - **Do** use `os.CreateTemp` for creating temporary files. This function helps in securely generating temporary files within a directory that only your application can access, significantly reducing the risk of symlink attacks. + ```go + f, err := os.CreateTemp(restrictedDir, "temp-*.txt") + ``` + - **Do not** use shared temporary directories for operations that involve sensitive data or require secure file handling. + - **Do** ensure temporary files are removed after their intended use to avoid accumulation and potential security risks. - ✅ Use Secure Temporary File Creation - - Implement `os.CreateTemp` to safely create temporary files within a directory that's restricted to the application. This reduces the risk of symlink attacks and ensures that temporary files are handled securely. - - ```go - import ( - "os" - "log" - ) - - func main() { - // Ensure the application-restricted directory exists with appropriate permissions - restrictedDir := "/opt/appdir/restricted" - if err := os.MkdirAll(restrictedDir, 0700); err != nil { - log.Fatalf("failed to create restricted directory: %s", err) - } - - // Securely create a temporary file within the restricted directory - f, err := os.CreateTemp(restrictedDir, "temp-*.txt") - if err != nil { - log.Fatalf("failed to create temporary file: %s", err) - } - defer f.Close() // Ensure the file is closed when no longer needed - - defer os.Remove(f.Name()) // Clean up the file upon exit - // Continue working with the temporary file - } - ``` - - ✅ Avoid Shared Temporary Directories for Sensitive Operations - - Do not use common temporary directories for storing sensitive information or for operations that require secure handling of files. - - ✅ Clean Up After Use - - Always remove temporary files after their use to prevent accumulation and potential misuse. - - ## Resources + ## References - [Go Documentation: os.CreateTemp](https://pkg.go.dev/os#CreateTemp) cwe_id: diff --git a/rules/go/gosec/filesystem/ziparchive.yml b/rules/go/gosec/filesystem/ziparchive.yml index 2ffe3e6de..43c64cbd2 100644 --- a/rules/go/gosec/filesystem/ziparchive.yml +++ b/rules/go/gosec/filesystem/ziparchive.yml @@ -38,102 +38,28 @@ languages: - go metadata: description: "Missing protection against 'Zip Slip' path traversal" - remediation_message: | + remediation_message: |- ## Description - The application is at risk of a path traversal vulnerability, commonly known as 'Zip Slip', when extracting files from untrusted archives. Maliciously crafted archive files can contain relative path specifications that lead to writing files outside the intended directory when extracted, potentially overwriting system files or placing unauthorized files in critical paths. + Your application is vulnerable to a 'Zip Slip' path traversal attack when it extracts files from archives that are not trusted. This occurs because malicious archives may contain files with relative paths aiming to escape the intended directory. As a result, these files could overwrite important system files or be placed in sensitive locations, leading to security breaches. ## Remediations - To safeguard against 'Zip Slip' and related exploitation techniques, follow these security practices: - - ✅ Limit Archive Size - - Implement checks to ensure the zip archive's size does not exceed a maximum threshold, preventing 'Zip Bombs'—archives that decompress to disproportionately large sizes. - - ✅ Generate Unique Filenames - - Avoid using the original filenames from the archive. If necessary, use only the base name after sanitizing or, better yet, generate a unique name to prevent intentional overwrites. - - ✅ Validate Extraction Paths - - Confirm that extracted files are written to a specified, trusted directory and do not traverse outside of this directory. - - ✅ Disallow Symbolic Links - - Only process regular files. Exclude symbolic links to prevent indirect file read/write vulnerabilities. - - ```go - import ( - "archive/zip" - "io" - "log" - "os" - "path/filepath" - "strings" - ) - - func main() { - // Open the zip file for reading - r, err := zip.OpenReader("trusted.zip") - if err != nil { - log.Fatal(err) - } - defer r.Close() - - // Set up restrictions and base path - const ( - expectedFileCount = 10 - totalAllowedSize = 10 * 1024 * 1024 // 10MB - maxFileSize = 1024 * 1024 // 1MB - basePath = "/var/restricted/" - ) - - // Calculate total size of uncompressed files - var totalSize uint64 - for _, f := range r.File { - totalSize += f.UncompressedSize64 - } - - // Check if total size exceeds the limit - if totalSize > totalAllowedSize { - log.Fatalf("archive exceeds total allowed size: %d\n", totalSize) + - **Do** implement checks to limit the zip archive's size. This prevents 'Zip Bombs', which are archives that decompress into sizes much larger than expected. For example, use `file.UncompressedSize64` to check the size of a file within a ZIP file. + - **Do** generate unique filenames for extracted files or sanitize the original filenames to avoid overwriting files intentionally. You can use `filepath.Base`, for example, to extract the filename from a path and discard any directory information. + ```go + name := filepath.Base(file.Name) + ``` + - **Do** validate the paths of extracted files to ensure they are written to a specified, trusted directory without traversing outside of it. + - **Do** process only regular files. Exclude symbolic links to prevent indirect file read/write vulnerabilities. + ```go + if !file.Mode().IsRegular() { + log.Fatal("non-regular file: %s\n", file.Name) } + ``` + - **Do** ensure directories within the zip archive are processed securely by cleaning the path and strictly validating it against the base path. - // Process files in the archive - for _, f := range r.File { - // Skip overlarge files - if f.UncompressedSize64 > maxFileSize { - log.Printf("skipping file as it exceeds maxFileSize: %s\n", f.Name) - continue - } - - // Skip if not a regular file - if !f.Mode().IsRegular() { - log.Printf("skipping non-regular file: %s\n", f.Name) - continue - } - - // Securely resolve the file path - name := filepath.Base(f.Name) - resolvedPath, err := filepath.Join(basePath, name) - if err != nil { - log.Fatal(err) - } - - // Ensure the file does not traverse outside the base path - if !strings.HasPrefix(resolvedPath, basePath) { - log.Fatal("path does not start with basePath") - } - - // Extract and process the file (omitted for brevity) - } - } - ``` - - For processing directories within the zip archive, ensure to clean the path and validate it strictly against the base path. - - ## Resources + ## References - [Go Documentation: archive/zip package](https://pkg.go.dev/archive/zip) diff --git a/rules/go/gosec/http/http_serve.yml b/rules/go/gosec/http/http_serve.yml index 39a56bd2c..44fbda939 100644 --- a/rules/go/gosec/http/http_serve.yml +++ b/rules/go/gosec/http/http_serve.yml @@ -27,50 +27,30 @@ languages: - go metadata: description: "Usage of vulnerable 'serve' function" - remediation_message: | + remediation_message: |- ## Description - The `net/http` serve functions in Go, when used with default settings, are vulnerable to resource consumption attacks. Attackers can exploit this by creating numerous connections to the server, intentionally not completing data transfers or leaving connections open, which can exhaust the server's resources and prevent it from accepting new legitimate connections. + The default `serve` functions in Go's `net/http` package are susceptible to resource consumption attacks. This vulnerability arises when attackers flood the server with incomplete or persistent connections, depleting its resources and blocking new legitimate connections. ## Remediations - To mitigate such attacks, specific server configurations are necessary: - - ❌ Avoid Default Serve Functions for Production - - Functions like `http.ListenAndServe` and `http.Serve` should not be used in a production setting as they do not allow for timeout configurations. - - ✅ Configure Timeouts on Custom `http.Server` Object - - Create a custom `http.Server` object and set appropriate timeouts to prevent resource exhaustion. - - ```go - import ( - "net/http" - "time" - "log" - ) - - func main() { - srv := &http.Server{ - Addr: "localhost:8000", - ReadHeaderTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - WriteTimeout: 10 * time.Second, - IdleTimeout: 30 * time.Second, - } - - if err := srv.ListenAndServe(); err != nil { - log.Fatal(err) - } - } - ``` - - ✅ Use `http.TimeoutHandler` for Per Request Timeouts - - To set timeouts for individual requests, use the `http.TimeoutHandler` wrapper on your handlers. This ensures that the server does not wait indefinitely for a request to complete. - - ## Resources + - **Do not** use default serve functions like `http.ListenAndServe` and `http.Serve` in production environments. You cannot set timeouts for these functions, making the server vulnerable to attacks. + ```go + http.ListenAndServe(":8080", nil) // unsafe + ``` + - **Do** create a custom `http.Server` object with configured timeouts to safeguard against resource exhaustion. Set `ReadHeaderTimeout`, `ReadTimeout`, `WriteTimeout`, and `IdleTimeout` to appropriate values. + ```go + myServer := &http.Server{ + Addr: "localhost:8000", + ReadHeaderTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 30 * time.Second, + } + ``` + - **Do** enforce timeouts on individual requests using `http.TimeoutHandler`. This wrapper ensures that the server does not indefinitely wait for a request to finish, preventing potential denial of service. + + ## References - [http.Server Timeouts Documentation](https://pkg.go.dev/net/http#Server) - [Guide to Setting Request-Based Timeouts](https://pkg.go.dev/net/http#TimeoutHandler) diff --git a/rules/go/gosec/http/http_slowloris.yml b/rules/go/gosec/http/http_slowloris.yml index 6c4144f8c..a7133b15f 100644 --- a/rules/go/gosec/http/http_slowloris.yml +++ b/rules/go/gosec/http/http_slowloris.yml @@ -93,50 +93,29 @@ languages: - go metadata: description: "Missing protection against 'Slowloris' attack" - remediation_message: | + remediation_message: |- ## Description - The server configuration lacks a `ReadHeaderTimeout`, making it vulnerable to a Slowloris attack. This type of attack occurs when an attacker opens multiple connections to the server but sends only partial requests. The server keeps each connection open, waiting for the headers to be completed, ultimately leading to resource exhaustion. + Your server configuration is missing the `ReadHeaderTimeout` setting, making it vulnerable to a type of Distributed Denial of Service (DDoS) attack known as a Slowloris attack. In such an attack, a hacker initiates many connections to your server, sending incomplete requests. Your server then keeps each connection open, waiting for the headers to be completed. This can lead to resource exhaustion, where your server cannot handle additional (legitimate) requests. ## Remediations - To protect against such attacks, the following steps should be taken: + - **Do not** use default serve functions like `http.ListenAndServe` and `http.Serve` in production environments. You cannot set timeouts for these functions, making the server vulnerable to attacks. + ```go + http.ListenAndServe(":8080", nil) // unsafe + ``` + - **Do** create a custom `http.Server` object with configured timeouts to safeguard against resource exhaustion. For Slowloris attacks in particular, set `ReadHeaderTimeout` to an appropriate value to ensure that connections do not remain open indefinitely. + ```go + myServer := &http.Server{ + Addr: "localhost:8000", + ReadHeaderTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 30 * time.Second, + } + ``` - ❌ Avoid Default Serve Functions for Production - - Do not use `http.ListenAndServe` and `http.Serve` in a production environment, as they do not support timeout settings. - - ✅ Configure `http.Server` with Timeouts - - Establish a custom `http.Server` instance with appropriate timeouts to prevent attackers from exploiting the lack of `ReadHeaderTimeout`. - - ```go - import ( - "net/http" - "time" - "log" - ) - - func main() { - srv := &http.Server{ - Addr: "localhost:8000", - ReadHeaderTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - WriteTimeout: 10 * time.Second, - IdleTimeout: 30 * time.Second, - } - - if err := srv.ListenAndServe(); err != nil { - log.Fatal(err) - } - } - ``` - - ✅ Enforce Request Timeouts - - Implement `http.TimeoutHandler` to apply timeouts to individual HTTP handlers, which starts counting down only after the headers have been read. - - ## Resources + ## References - [Configuring Timeouts in http.Server](https://pkg.go.dev/net/http#Server) - [How to Set Request-Based Timeouts](https://pkg.go.dev/net/http#TimeoutHandler) diff --git a/rules/go/gosec/injection/ssrf_injection.yml b/rules/go/gosec/injection/ssrf_injection.yml index c70f6cc2c..78d6cccc9 100644 --- a/rules/go/gosec/injection/ssrf_injection.yml +++ b/rules/go/gosec/injection/ssrf_injection.yml @@ -25,100 +25,32 @@ languages: - go metadata: description: "Unsanitized user input in HTTP request (SSRF)" - remediation_message: | + remediation_message: |- ## Description - Server-Side Request Forgery (SSRF) is a security vulnerability that occurs when a server-side application makes HTTP requests to arbitrary URLs controlled by the user. SSRF can be exploited by attackers to target internal systems behind firewalls that are otherwise inaccessible from the external network, by tricking the server into making requests to these systems. + Including unsanitized user input in HTTP requests puts your application at risk of Server-Side Request Forgery (SSRF). This is a security vulnerability that occurs when a server-side application makes HTTP requests to arbitrary URLs controlled by the user. SSRF can be exploited by attackers to target internal systems behind firewalls that are otherwise inaccessible from the external network, by tricking the server into making requests to these systems. ## Remediations - To mitigate SSRF vulnerabilities, follow these guidelines: - - ✅ Validate User Input - - Avoid using direct user input to construct URLs for backend requests. If you must use user input, validate or sanitize it rigorously. - - ✅ Restrict URLs to Known Safe Domains - - Where possible, limit requests to a predefined set of safe URLs or domains. This can be done using server-side mapping from user-supplied keys to URLs. - - ✅ Implement IP Safelists and Blocklists - - Use an HTTP client that allows customizing and blocking specific IP ranges, such as private network addresses and other non-routable IP ranges. - - ✅ Use Network-Level Security - - If the HTTP client doesn't support IP range blocking, consider running it with restricted system permissions, or within a secure network where firewall rules can block dangerous addresses. - - ✅ Leverage a Secure HTTP Proxy - - As a last resort, route all backend HTTP requests through a secure proxy that can filter out and block requests to potentially harmful addresses. - - ```go - import ( - "context" - "crypto/tls" - "errors" - "net" - "net/http" - "time" - ) - - // IsDisallowedIP checks if an IP address falls within a range of disallowed IPs. - func IsDisallowedIP(hostIP string) bool { - ip := net.ParseIP(hostIP) - // Add more checks as necessary - return ip.IsMulticast() || ip.IsUnspecified() || ip.IsLoopback() || ip.IsPrivate() - } - - // SafeTransport defines a custom transport that filters out disallowed IP addresses. - func SafeTransport(timeout time.Duration) *http.Transport { - return &http.Transport{ - DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { - c, err := net.DialTimeout(network, addr, timeout) - if err != nil { - return nil, err - } - ip, _, _ := net.SplitHostPort(c.RemoteAddr().String()) - if IsDisallowedIP(ip) { - c.Close() - return nil, errors.New("ip address is not allowed") - } - return c, err - }, - DialTLS: func(network, addr string) (net.Conn, error) { - dialer := &net.Dialer{Timeout: timeout} - c, err := tls.DialWithDialer(dialer, network, addr, &tls.Config{}) - if err != nil { - return nil, err - } - ip, _, _ := net.SplitHostPort(c.RemoteAddr().String()) - if IsDisallowedIP(ip) { - c.Close() - return nil, errors.New("ip address is not allowed") - } - return c, c.Handshake() - }, - TLSHandshakeTimeout: timeout, - } - } - - // httpRequest performs a secure HTTP request, filtering out disallowed IPs. - func httpRequest(requestUrl string) { - const clientConnectTimeout = time.Second * 10 - httpClient := &http.Client{ - Transport: SafeTransport(clientConnectTimeout), - } - resp, err := httpClient.Get(requestUrl) - if err != nil { - log.Fatal(err) - } - defer resp.Body.Close() - // Process response - } - ``` - - ## Resources + - **Do not** use direct user input to construct URLs for backend requests. If user input is necessary, ensure it is strictly validated or sanitized to prevent malicious manipulation. + - **Do** use a safelist or predefined mapping when incorporating user input in URLs. This ensures that your application only redirects users to safe and intended destinations. + ```go + safeURLs := map[string]string{ + "key1": "https://safe-domain1.com", + "key2": "https://safe-domain2.com", + } + requestedKey := getUserInput() + if url, ok := safeURLs[requestedKey]; ok { + // continue with request + } else { + log.Fatal("Requested URL is not allowed") + } + ``` + - **Do** implement IP safelists and blocklists to customize and block specific IP ranges, especially those that are private, loopback, or otherwise non-routable. + - **Do** use network-level security measures. If your HTTP client does not support IP range blocking, run it with restricted system permissions or within a network environment where firewall rules can effectively block requests to dangerous addresses. + - **Do** consider using a secure HTTP proxy to route all backend HTTP requests. This proxy can serve as a filter to block requests to potentially harmful addresses, acting as an additional layer of security. + + ## References - [OWASP SSRF Prevention Cheat Sheet](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) diff --git a/rules/go/gosec/injection/subproc_injection.yml b/rules/go/gosec/injection/subproc_injection.yml index 223f59402..7c334af26 100644 --- a/rules/go/gosec/injection/subproc_injection.yml +++ b/rules/go/gosec/injection/subproc_injection.yml @@ -26,72 +26,30 @@ languages: severity: critical metadata: description: Unsanitized dynamic input in OS command - remediation_message: | + remediation_message: |- ## Description - OS command injection is a severe security vulnerability that occurs when an application incorrectly processes external input. This flaw can allow attackers to execute arbitrary commands on the host operating system, potentially leading to a full system compromise. + Using unsanitized dynamic or external input in an OS command is a critical security flaw that can enable attackers to execute unauthorized commands on the host operating system, potentially leading to a complete system takeover. ## Remediations - Prevent OS command injection by adhering to the following practices: - - ❌ Avoid Direct External Input - - Do not use externally-supplied information for constructing OS commands or command-line arguments, as this can lead to command injection vulnerabilities. - - ✅ Implement Input Validation - - Ensure that any external input is validated against a set of strict rules to ensure it does not contain malicious characters or patterns. - - ✅ Use Hardcoded Arguments - - When invoking OS commands, use a hardcoded set of arguments to ensure that external input cannot alter the command's behavior. - - ✅ Utilize Temporary Files Securely - - When dealing with files, create temporary files in a restricted directory, avoiding the use of user-supplied filenames. - - ✅ Employ Native Libraries - - Where possible, use native libraries or features of the programming language instead of invoking shell commands, which can be safer and more efficient. - - ```go - import ( - "io/ioutil" - "os/exec" - "log" - ) - - func main() { - userData := []byte("user data") - - // Create a temporary file in a secure, application-specific directory - f, err := ioutil.TempFile("/var/app/restricted", "temp-*.dat") - if err != nil { - log.Fatal(err) - } - - // Write user data to the temporary file - if _, err := f.Write(userData); err != nil { - f.Close() - log.Fatal(err) - } - - // Close the file handle - if err := f.Close(); err != nil { - log.Fatal(err) - } - - // Execute a command using the temporary file, avoiding direct external input for filenames - out, err := exec.Command("/bin/cat", f.Name()).Output() - if err != nil { - log.Fatal(err) - } - // Output can be used for further processing - } - ``` - - ## Resources + - **Do not** construct OS commands or command-line arguments using externally-supplied information. This practice can introduce command injection vulnerabilities. + ```go + cmd := exec.Command("bash", "-c", "echo " + externalInput) // unsafe + ``` + - **Do** validate all external input against a strict set of rules to ensure it does not include harmful characters or patterns. + ```go + if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(externalInput) { + log.Fatal("Invalid input") + } + ``` + - **Do** use hardcoded arguments when invoking OS commands to prevent external input from altering the command's execution. + ```go + cmd := exec.Command("ls", "-l", "/var/log") + ``` + - **Do** prefer native libraries or programming language features over invoking shell commands for enhanced security and efficiency. + + ## References - [OWASP OS Command Injection Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html) cwe_id: diff --git a/rules/go/gosec/injection/template_injection.yml b/rules/go/gosec/injection/template_injection.yml index dff35d512..e26aefebb 100644 --- a/rules/go/gosec/injection/template_injection.yml +++ b/rules/go/gosec/injection/template_injection.yml @@ -21,73 +21,27 @@ languages: - go metadata: description: "Unsanitized user input in web page generation (XSS)" - remediation_message: | + remediation_message: |- ## Description Cross-Site Scripting (XSS) is a vulnerability that allows attackers to run malicious scripts in the context of a trusted web application. This can happen when an application includes untrusted data without proper validation or escaping. There are several contexts where XSS can occur, each requiring specific encoding strategies to mitigate the risk. ## Remediations - To defend against XSS attacks, consider the following measures: + - **Do** encode user input based on the context it is used in, such as HTML content, HTML attributes, JavaScript, and CSS contexts. This helps prevent malicious scripts from being executed. + ```go + html.EscapeString(userInput) + ``` + - **Do** use templating engines like `html/template` that automatically encode data based on its context. + - **Do** sanitize data using libraries or functions specifically designed for this purpose, especially when inserting content into a web page. + - **Do** separate data from code by avoiding inline scripting and event handlers. Use separate JavaScript files for event handling to minimize script injection risks. + - **Do not** mix server-side and client-side templating systems, as server-side systems may not escape output safely for client-side use. + - **Do not** encode user input before storing it in a database. Any encoding should be applied when the data is output, not before storage, to ensure that it is encoded appropriately for its context. - ✅ Encode Based on Context - - When user input is reflected back in HTML, ensure it is encoded based on the context in which it is used (e.g., HTML content, HTML attributes, JavaScript context, CSS context, etc.). - - ✅ Template Safely - - Utilize templating engines that automatically encode data based on context, and be cautious not to override these safeguards. - - ✅ Sanitize Data - - Use libraries or functions designed to sanitize user input, particularly when inserting content into a web page. - - ✅ Separate Data from Code - - Avoid inline scripting and event handlers, and instead use separate JavaScript files to handle events. This reduces the risk of script injection through event attributes. - - ✅ Avoid Mixing Templating Systems - - Do not mix server-side and client-side templating systems, as server-side systems may not escape output in a way that is safe for client-side use. - - ❌ Do Not Encode Before Storing - - Avoid encoding user input before storing it in a database. The encoding should be applied when the data is output, not before storage, to ensure that it is encoded appropriately for its context. - - Here's an example of using Go’s `html/template` package to safely render HTML content: - - ```go - import ( - "html/template" - "os" - "log" - ) - - func main() { - // Define a template with a function to safely render HTML - testTemplate, err := template.New("testTemplate").Funcs(template.FuncMap{ - "SafeHTML": func() template.HTML { - const safeHTML = "