From 1cade3ec56af75f28c2091139fefd5dc0efa734d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Fabianski?= Date: Mon, 19 Feb 2024 17:54:15 +0100 Subject: [PATCH] feat(golang): add cwe 330 --- .../go/lang/insufficiently_random_values.yml | 56 +++++++++++++++++++ .../lang/insufficiently_random_values/test.js | 18 ++++++ .../testdata/main.go | 42 ++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 rules/go/lang/insufficiently_random_values.yml create mode 100644 tests/go/lang/insufficiently_random_values/test.js create mode 100644 tests/go/lang/insufficiently_random_values/testdata/main.go diff --git a/rules/go/lang/insufficiently_random_values.yml b/rules/go/lang/insufficiently_random_values.yml new file mode 100644 index 000000000..2adcec51e --- /dev/null +++ b/rules/go/lang/insufficiently_random_values.yml @@ -0,0 +1,56 @@ +patterns: + - pattern: | + $.Seed() + filters: + - variable: MATH + detection: go_lang_insufficiently_random_values_init + scope: cursor +auxiliary: + - id: go_lang_insufficiently_random_values_init + patterns: + - import $"math/rand" + - | + import ( + $"math/rand" + ) +languages: + - go +metadata: + description: "Usage of insufficient random value" + remediation_message: | + ## Description + + Using predictable random values makes our application vulnerable to attacks, + especially if these values are used for security purposes. + + ## Remediations + + ✅ Use a stronger library when generating random values + + ```go + import ( + "crypto/rand" + "encoding/base64" + "fmt" + ) + + func generateSecureToken(length int) (string, error) { + bytes := make([]byte, length) + _, err := rand.Read(bytes) + if err != nil { + return "", err + } + + // Encode the binary data to a string for easier use + return base64.URLEncoding.EncodeToString(bytes), nil + } + ``` + + ## Resources + + [Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html) + + cwe_id: + - 330 + id: go_lang_insufficiently_random_values + documentation_url: https://docs.bearer.com/reference/rules/go_lang_insufficiently_random_values diff --git a/tests/go/lang/insufficiently_random_values/test.js b/tests/go/lang/insufficiently_random_values/test.js new file mode 100644 index 000000000..b582cbf85 --- /dev/null +++ b/tests/go/lang/insufficiently_random_values/test.js @@ -0,0 +1,18 @@ +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") +const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) + +describe(ruleId, () => { + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("insufficiently_random_values", () => { + const testCase = "main.go" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) +}) \ No newline at end of file diff --git a/tests/go/lang/insufficiently_random_values/testdata/main.go b/tests/go/lang/insufficiently_random_values/testdata/main.go new file mode 100644 index 000000000..aa0e6ff18 --- /dev/null +++ b/tests/go/lang/insufficiently_random_values/testdata/main.go @@ -0,0 +1,42 @@ +// Use of bearer:expected go_lang_insufficiently_random_values to flag expected findings + +package main + +import ( + "encoding/base64" + "fmt" + "math/rand" + "time" + + crypto "crypto/rand" +) + +func generateSecureToken(length int) (string, error) { + bytes := make([]byte, length) + _, err := crypto.Read(bytes) + if err != nil { + return "", err // Don't ignore errors! + } + + // Encode the binary data to a string for easier use + return base64.URLEncoding.EncodeToString(bytes), nil +} + +func generateToken() string { + // Seed the random number generator with the current time + // bearer:expected go_lang_insufficiently_random_values + rand.Seed(time.Now().UnixNano()) + + // Generate a token using a non-cryptographically secure random generator + token := "" + for i := 0; i < 10; i++ { + token += string(rand.Intn(26) + 'a') + } + return token +} + +func main() { + // Generate and print a "random" token + fmt.Println("Generated Token:", generateToken()) + fmt.Println("Generated Secure Token:", generateSecureToken()) +}