From f732bc54bae6df1dedf1bd3da3eec549a6a6dd8c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 4 Dec 2024 20:16:32 +0530 Subject: [PATCH 1/3] openai-hardcoded-secret-python --- .../openai-hardcoded-secret-python.yml | 24 +++++++++++++++++++ ...penai-hardcoded-secret-python-snapshot.yml | 14 +++++++++++ .../openai-hardcoded-secret-python-test.yml | 8 +++++++ 3 files changed, 46 insertions(+) create mode 100644 rules/python/security/openai-hardcoded-secret-python.yml create mode 100644 tests/__snapshots__/openai-hardcoded-secret-python-snapshot.yml create mode 100644 tests/python/openai-hardcoded-secret-python-test.yml diff --git a/rules/python/security/openai-hardcoded-secret-python.yml b/rules/python/security/openai-hardcoded-secret-python.yml new file mode 100644 index 00000000..4218f202 --- /dev/null +++ b/rules/python/security/openai-hardcoded-secret-python.yml @@ -0,0 +1,24 @@ +id: openai-hardcoded-secret-python +language: python +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798]: Use of Hard-coded Credentials + [OWASP A07:2021]: Identification and Authentication Failures + [REFERENCES] + https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + match_api_key: + kind: string_content + regex: \b(sk-[[:alnum:]]{20}T3BlbkFJ[[:alnum:]]{20})\b + inside: + stopBy: end + kind: string +rule: + all: + - matches: match_api_key \ No newline at end of file diff --git a/tests/__snapshots__/openai-hardcoded-secret-python-snapshot.yml b/tests/__snapshots__/openai-hardcoded-secret-python-snapshot.yml new file mode 100644 index 00000000..7be78d4f --- /dev/null +++ b/tests/__snapshots__/openai-hardcoded-secret-python-snapshot.yml @@ -0,0 +1,14 @@ +id: openai-hardcoded-secret-python +snapshots: + ? | + api_key="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" + f = "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" + : labels: + - source: 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 + style: primary + start: 9 + end: 60 + - source: '"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"' + style: secondary + start: 8 + end: 61 diff --git a/tests/python/openai-hardcoded-secret-python-test.yml b/tests/python/openai-hardcoded-secret-python-test.yml new file mode 100644 index 00000000..f98c1b68 --- /dev/null +++ b/tests/python/openai-hardcoded-secret-python-test.yml @@ -0,0 +1,8 @@ +id: openai-hardcoded-secret-python +valid: + - | + openai.api_key="sk-ExamplexT3BlbkFJp6xpvsfpkEsmAJawIm0V" +invalid: + - | + api_key="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" + f = "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" From 7c10c881c22f9b0b1d055699561c91f5394e6631 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 4 Dec 2024 20:29:59 +0530 Subject: [PATCH 2/3] insecure-cipher-algorithm-rc4-python --- .../insecure-cipher-algorithm-rc4-python.yml | 85 ++++++++++ ...e-cipher-algorithm-rc4-python-snapshot.yml | 157 ++++++++++++++++++ ...ecure-cipher-algorithm-rc4-python-test.yml | 26 +++ 3 files changed, 268 insertions(+) create mode 100644 rules/python/security/insecure-cipher-algorithm-rc4-python.yml create mode 100644 tests/__snapshots__/insecure-cipher-algorithm-rc4-python-snapshot.yml create mode 100644 tests/python/insecure-cipher-algorithm-rc4-python-test.yml diff --git a/rules/python/security/insecure-cipher-algorithm-rc4-python.yml b/rules/python/security/insecure-cipher-algorithm-rc4-python.yml new file mode 100644 index 00000000..ac5ff75f --- /dev/null +++ b/rules/python/security/insecure-cipher-algorithm-rc4-python.yml @@ -0,0 +1,85 @@ +id: insecure-cipher-algorithm-rc4-python +severity: warning +language: python +message: >- + Detected ARC4 cipher algorithm which is considered insecure. This + algorithm is not cryptographically secure and can be reversed easily. Use + secure stream ciphers such as ChaCha20, XChaCha20 and Salsa20, or a block + cipher such as AES with a block size of 128 bits. When using a block + cipher, use a modern mode of operation that also provides authentication, + such as GCM. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://cwe.mitre.org/data/definitions/326.html + - https://www.pycryptodome.org/src/cipher/cipher +utils: + MATCH_PATTERN_arc4.new: + kind: call + all: + - has: + stopBy: end + kind: attribute + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $X + - has: + stopBy: neighbor + kind: identifier + regex: '^new$' + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: import_from_statement + all: + - has: + stopBy: neighbor + kind: dotted_name + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^Crypto$|^Cryptodome$' + - has: + stopBy: neighbor + kind: identifier + regex: '^Cipher$' + - has: + stopBy: neighbor + kind: aliased_import + all: + - has: + stopBy: neighbor + kind: dotted_name + has: + stopBy: neighbor + kind: identifier + regex: '^ARC4$' + - has: + stopBy: neighbor + kind: identifier + pattern: $X + +rule: + kind: call + any: + - matches: MATCH_PATTERN_arc4.new + - pattern: Cryptodome.Cipher.ARC4.new($$$) + - pattern: Crypto.Cipher.ARC4.new($$$) + + + + + + + \ No newline at end of file diff --git a/tests/__snapshots__/insecure-cipher-algorithm-rc4-python-snapshot.yml b/tests/__snapshots__/insecure-cipher-algorithm-rc4-python-snapshot.yml new file mode 100644 index 00000000..8ef609ae --- /dev/null +++ b/tests/__snapshots__/insecure-cipher-algorithm-rc4-python-snapshot.yml @@ -0,0 +1,157 @@ +id: insecure-cipher-algorithm-rc4-python +snapshots: + ? | + Crypto.Cipher.ARC4.new() + : labels: + - source: Crypto.Cipher.ARC4.new() + style: primary + start: 0 + end: 24 + ? | + Crypto.Cipher.ARC4.new(adasfdasfs) + : labels: + - source: Crypto.Cipher.ARC4.new(adasfdasfs) + style: primary + start: 0 + end: 34 + ? | + Cryptodome.Cipher.ARC4.new() + : labels: + - source: Cryptodome.Cipher.ARC4.new() + style: primary + start: 0 + end: 28 + Cryptodome.Cipher.ARC4.new(asdsd): + labels: + - source: Cryptodome.Cipher.ARC4.new(asdsd) + style: primary + start: 0 + end: 33 + ? | + from Crypto.Cipher import ARC4 as pycrypto_arc4 + cipher = pycrypto_arc4.new(tempkey) + : labels: + - source: pycrypto_arc4.new(tempkey) + style: primary + start: 57 + end: 83 + - source: pycrypto_arc4 + style: secondary + start: 57 + end: 70 + - source: new + style: secondary + start: 71 + end: 74 + - source: pycrypto_arc4.new + style: secondary + start: 57 + end: 74 + - source: tempkey + style: secondary + start: 75 + end: 82 + - source: (tempkey) + style: secondary + start: 74 + end: 83 + - source: Crypto + style: secondary + start: 5 + end: 11 + - source: Cipher + style: secondary + start: 12 + end: 18 + - source: Crypto.Cipher + style: secondary + start: 5 + end: 18 + - source: ARC4 + style: secondary + start: 26 + end: 30 + - source: ARC4 + style: secondary + start: 26 + end: 30 + - source: pycrypto_arc4 + style: secondary + start: 34 + end: 47 + - source: ARC4 as pycrypto_arc4 + style: secondary + start: 26 + end: 47 + - source: from Crypto.Cipher import ARC4 as pycrypto_arc4 + style: secondary + start: 0 + end: 47 + - source: cipher = pycrypto_arc4.new(tempkey) + style: secondary + start: 48 + end: 83 + ? | + from Cryptodome.Cipher import ARC4 as pycryptodomex_arc4 + cipher = pycryptodomex_arc4.new(tempkey) + : labels: + - source: pycryptodomex_arc4.new(tempkey) + style: primary + start: 66 + end: 97 + - source: pycryptodomex_arc4 + style: secondary + start: 66 + end: 84 + - source: new + style: secondary + start: 85 + end: 88 + - source: pycryptodomex_arc4.new + style: secondary + start: 66 + end: 88 + - source: tempkey + style: secondary + start: 89 + end: 96 + - source: (tempkey) + style: secondary + start: 88 + end: 97 + - source: Cryptodome + style: secondary + start: 5 + end: 15 + - source: Cipher + style: secondary + start: 16 + end: 22 + - source: Cryptodome.Cipher + style: secondary + start: 5 + end: 22 + - source: ARC4 + style: secondary + start: 30 + end: 34 + - source: ARC4 + style: secondary + start: 30 + end: 34 + - source: pycryptodomex_arc4 + style: secondary + start: 38 + end: 56 + - source: ARC4 as pycryptodomex_arc4 + style: secondary + start: 30 + end: 56 + - source: from Cryptodome.Cipher import ARC4 as pycryptodomex_arc4 + style: secondary + start: 0 + end: 56 + - source: cipher = pycryptodomex_arc4.new(tempkey) + style: secondary + start: 57 + end: 97 diff --git a/tests/python/insecure-cipher-algorithm-rc4-python-test.yml b/tests/python/insecure-cipher-algorithm-rc4-python-test.yml new file mode 100644 index 00000000..b9f0870f --- /dev/null +++ b/tests/python/insecure-cipher-algorithm-rc4-python-test.yml @@ -0,0 +1,26 @@ +id: insecure-cipher-algorithm-rc4-python +valid: + - | + cipher = AES.new(key, AES.MODE_EAX, nonce=nonce) + plaintext = cipher.decrypt(ciphertext) + try: + cipher.verify(tag) + print("The message is authentic:", plaintext) + except ValueError: + print("Key incorrect or message corrupted") + +invalid: + - | + from Cryptodome.Cipher import ARC4 as pycryptodomex_arc4 + cipher = pycryptodomex_arc4.new(tempkey) + - | + from Crypto.Cipher import ARC4 as pycrypto_arc4 + cipher = pycrypto_arc4.new(tempkey) + - | + Crypto.Cipher.ARC4.new() + - | + Crypto.Cipher.ARC4.new(adasfdasfs) + - | + Cryptodome.Cipher.ARC4.new() + - | + Cryptodome.Cipher.ARC4.new(asdsd) \ No newline at end of file From 4afc0df15064267bcf6b34dcd0df3da1a19e893e Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 4 Dec 2024 20:37:16 +0530 Subject: [PATCH 3/3] hardcoded-http-auth-in-controller-ruby --- ...hardcoded-http-auth-in-controller-ruby.yml | 59 ++++++++++++++++++ ...-http-auth-in-controller-ruby-snapshot.yml | 62 +++++++++++++++++++ ...oded-http-auth-in-controller-ruby-test.yml | 18 ++++++ 3 files changed, 139 insertions(+) create mode 100644 rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml create mode 100644 tests/__snapshots__/hardcoded-http-auth-in-controller-ruby-snapshot.yml create mode 100644 tests/ruby/hardcoded-http-auth-in-controller-ruby-test.yml diff --git a/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml b/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml new file mode 100644 index 00000000..38329296 --- /dev/null +++ b/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml @@ -0,0 +1,59 @@ +id: hardcoded-http-auth-in-controller-ruby +language: ruby +severity: warning +message: >- + Detected hardcoded password used in basic authentication in a + controller class. Including this password in version control could expose + this credential. Consider refactoring to use environment variables or + configuration files +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + MATCH_PASSWORD_STRING: + kind: string + inside: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + kind: simple_symbol + regex: '^:password$' + - has: + stopBy: neighbor + kind: string + - inside: + stopBy: neighbor + kind: argument_list + inside: + stopBy: end + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^http_basic_authenticate_with$' + - inside: + stopBy: neighbor + kind: body_statement + inside: + stopBy: end + kind: class + all: + - has: + stopBy: neighbor + kind: constant + - has: + stopBy: end + kind: superclass + has: + stopBy: neighbor + kind: constant + regex: '^ApplicationController$' + +rule: + kind: string + matches: MATCH_PASSWORD_STRING + diff --git a/tests/__snapshots__/hardcoded-http-auth-in-controller-ruby-snapshot.yml b/tests/__snapshots__/hardcoded-http-auth-in-controller-ruby-snapshot.yml new file mode 100644 index 00000000..5043b45e --- /dev/null +++ b/tests/__snapshots__/hardcoded-http-auth-in-controller-ruby-snapshot.yml @@ -0,0 +1,62 @@ +id: hardcoded-http-auth-in-controller-ruby +snapshots: + ? |- + class DangerousController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + puts "do more stuff" + end + : labels: + - source: '"secret"' + style: primary + start: 108 + end: 116 + - source: :password + style: secondary + start: 95 + end: 104 + - source: '"secret"' + style: secondary + start: 108 + end: 116 + - source: http_basic_authenticate_with + style: secondary + start: 50 + end: 78 + - source: DangerousController + style: secondary + start: 6 + end: 25 + - source: ApplicationController + style: secondary + start: 28 + end: 49 + - source: < ApplicationController + style: secondary + start: 26 + end: 49 + - source: |- + class DangerousController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + puts "do more stuff" + end + style: secondary + start: 0 + end: 160 + - source: |- + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + puts "do more stuff" + style: secondary + start: 50 + end: 156 + - source: http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + style: secondary + start: 50 + end: 135 + - source: :name => "dhh", :password => "secret", :except => :index + style: secondary + start: 79 + end: 135 + - source: :password => "secret" + style: secondary + start: 95 + end: 116 diff --git a/tests/ruby/hardcoded-http-auth-in-controller-ruby-test.yml b/tests/ruby/hardcoded-http-auth-in-controller-ruby-test.yml new file mode 100644 index 00000000..88232950 --- /dev/null +++ b/tests/ruby/hardcoded-http-auth-in-controller-ruby-test.yml @@ -0,0 +1,18 @@ +id: hardcoded-http-auth-in-controller-ruby +valid: + - | + class OkController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => not_a_string, :except => :index + puts "do more stuff" + end + - | + class OkController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => ads{'not_a_string'}, :except => :index + puts "do more stuff" + end +invalid: + - | + class DangerousController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + puts "do more stuff" + end \ No newline at end of file