From e1776c62cb991805a85a97b7b2aff409b56c0c3c Mon Sep 17 00:00:00 2001 From: Sakshis Date: Sat, 7 Dec 2024 04:51:24 +0000 Subject: [PATCH 1/3] hardcoded-connection-password-java --- .../hardcoded-connection-password-java.yml | 360 ++++++++++++++++++ ...oded-connection-password-java-snapshot.yml | 312 +++++++++++++++ ...ardcoded-connection-password-java-test.yml | 34 ++ 3 files changed, 706 insertions(+) create mode 100644 rules/java/security/hardcoded-connection-password-java.yml create mode 100644 tests/__snapshots__/hardcoded-connection-password-java-snapshot.yml create mode 100644 tests/java/hardcoded-connection-password-java-test.yml diff --git a/rules/java/security/hardcoded-connection-password-java.yml b/rules/java/security/hardcoded-connection-password-java.yml new file mode 100644 index 00000000..d6ca78cc --- /dev/null +++ b/rules/java/security/hardcoded-connection-password-java.yml @@ -0,0 +1,360 @@ +id: hardcoded-connection-password-java +severity: warning +language: java +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. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + - https://db.apache.org/jdo/api30/apidocs/javax/jdo/PersistenceManagerFactory.html +utils: + PATTERN_1: + # (PersistenceManagerFactory $JDO) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: type_identifier + regex: '^PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + any: + - pattern: import javax.jdo.PersistenceManagerFactory; + - pattern: import javax.jdo.*; + PATTERN_2: + # (PersistenceManagerFactory $JDO with instance) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: type_identifier + regex: '^PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + any: + - pattern: import javax.jdo.PersistenceManagerFactory; + - pattern: import javax.jdo.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_3: + # (jdo.PersistenceManagerFactory $JDO) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^jdo.PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import javax.*; + PATTERN_4: + # (jdo.PersistenceManagerFactory $JDO with instance) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^jdo.PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import javax.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_5: + # (PersistenceManagerFactory $JDO) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^javax.jdo.PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + PATTERN_6: + # (PersistenceManagerFactory $JDO with instance) + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: field_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^javax.jdo.PersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C +rule: + kind: identifier + any: + - matches: PATTERN_1 + - matches: PATTERN_2 + - matches: PATTERN_3 + - matches: PATTERN_4 + - matches: PATTERN_5 + - matches: PATTERN_6 +constraints: + B: + regex: '^setConnectionPassword$' + C: + kind: string_literal + not: + regex: ^""$ diff --git a/tests/__snapshots__/hardcoded-connection-password-java-snapshot.yml b/tests/__snapshots__/hardcoded-connection-password-java-snapshot.yml new file mode 100644 index 00000000..905a934c --- /dev/null +++ b/tests/__snapshots__/hardcoded-connection-password-java-snapshot.yml @@ -0,0 +1,312 @@ +id: hardcoded-connection-password-java +snapshots: + ? | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + } + } + : labels: + - source: setConnectionPassword + style: primary + start: 143 + end: 164 + - source: pmf + style: secondary + start: 139 + end: 142 + - source: setConnectionPassword + style: secondary + start: 143 + end: 164 + - source: pw + style: secondary + start: 165 + end: 167 + - source: (pw) + style: secondary + start: 164 + end: 168 + - source: pmf.setConnectionPassword(pw) + style: secondary + start: 139 + end: 168 + - source: pmf.setConnectionPassword(pw); + style: secondary + start: 139 + end: 169 + - source: PersistenceManagerFactory + style: secondary + start: 78 + end: 103 + - source: pmf + style: secondary + start: 104 + end: 107 + - source: private PersistenceManagerFactory pmf; + style: secondary + start: 70 + end: 108 + - source: |- + public class PeopleTest { + private PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + } + } + style: secondary + start: 44 + end: 173 + - source: import javax.jdo.PersistenceManagerFactory; + style: secondary + start: 0 + end: 43 + - source: | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + } + } + style: secondary + start: 0 + end: 174 + - source: pw + style: secondary + start: 124 + end: 126 + - source: '"asdf"' + style: secondary + start: 129 + end: 135 + - source: pw = "asdf" + style: secondary + start: 124 + end: 135 + - source: |- + public class PeopleTest { + private PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + } + } + style: secondary + start: 44 + end: 173 + ? | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("pw"); + } + } + : labels: + - source: setConnectionPassword + style: primary + start: 115 + end: 136 + - source: pmf + style: secondary + start: 111 + end: 114 + - source: setConnectionPassword + style: secondary + start: 115 + end: 136 + - source: '"pw"' + style: secondary + start: 137 + end: 141 + - source: ("pw") + style: secondary + start: 136 + end: 142 + - source: pmf.setConnectionPassword("pw") + style: secondary + start: 111 + end: 142 + - source: pmf.setConnectionPassword("pw"); + style: secondary + start: 111 + end: 143 + - source: PersistenceManagerFactory + style: secondary + start: 78 + end: 103 + - source: pmf + style: secondary + start: 104 + end: 107 + - source: private PersistenceManagerFactory pmf; + style: secondary + start: 70 + end: 108 + - source: |- + public class PeopleTest { + private PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("pw"); + } + } + style: secondary + start: 44 + end: 147 + - source: import javax.jdo.PersistenceManagerFactory; + style: secondary + start: 0 + end: 43 + - source: | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("pw"); + } + } + style: secondary + start: 0 + end: 148 + ? | + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + }} + : labels: + - source: setConnectionPassword + style: primary + start: 109 + end: 130 + - source: pmf + style: secondary + start: 105 + end: 108 + - source: setConnectionPassword + style: secondary + start: 109 + end: 130 + - source: pw + style: secondary + start: 131 + end: 133 + - source: (pw) + style: secondary + start: 130 + end: 134 + - source: pmf.setConnectionPassword(pw) + style: secondary + start: 105 + end: 134 + - source: pmf.setConnectionPassword(pw); + style: secondary + start: 105 + end: 135 + - source: javax.jdo.PersistenceManagerFactory + style: secondary + start: 34 + end: 69 + - source: pmf + style: secondary + start: 70 + end: 73 + - source: private javax.jdo.PersistenceManagerFactory pmf; + style: secondary + start: 26 + end: 74 + - source: |- + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + }} + style: secondary + start: 0 + end: 138 + - source: pw + style: secondary + start: 90 + end: 92 + - source: '"asdf"' + style: secondary + start: 95 + end: 101 + - source: pw = "asdf" + style: secondary + start: 90 + end: 101 + - source: |- + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + }} + style: secondary + start: 0 + end: 138 + ? | + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("asdf"); + }} + : labels: + - source: setConnectionPassword + style: primary + start: 81 + end: 102 + - source: pmf + style: secondary + start: 77 + end: 80 + - source: setConnectionPassword + style: secondary + start: 81 + end: 102 + - source: '"asdf"' + style: secondary + start: 103 + end: 109 + - source: ("asdf") + style: secondary + start: 102 + end: 110 + - source: pmf.setConnectionPassword("asdf") + style: secondary + start: 77 + end: 110 + - source: pmf.setConnectionPassword("asdf"); + style: secondary + start: 77 + end: 111 + - source: javax.jdo.PersistenceManagerFactory + style: secondary + start: 34 + end: 69 + - source: pmf + style: secondary + start: 70 + end: 73 + - source: private javax.jdo.PersistenceManagerFactory pmf; + style: secondary + start: 26 + end: 74 + - source: |- + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("asdf"); + }} + style: secondary + start: 0 + end: 114 diff --git a/tests/java/hardcoded-connection-password-java-test.yml b/tests/java/hardcoded-connection-password-java-test.yml new file mode 100644 index 00000000..3e9e942c --- /dev/null +++ b/tests/java/hardcoded-connection-password-java-test.yml @@ -0,0 +1,34 @@ +id: hardcoded-connection-password-java +valid: + - | +invalid: + - | + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("asdf"); + }} + - | + public class PeopleTest { + private javax.jdo.PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + }} + - | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + private String pw = "asdf"; + { + pmf.setConnectionPassword(pw); + } + } + - | + import javax.jdo.PersistenceManagerFactory; + public class PeopleTest { + private PersistenceManagerFactory pmf; + { + pmf.setConnectionPassword("pw"); + } + } From a11dcc829305955f1fd8fce89456765edb45fdf0 Mon Sep 17 00:00:00 2001 From: Sakshis Date: Sat, 7 Dec 2024 04:55:06 +0000 Subject: [PATCH 2/3] datanucleus-hardcoded-connection-password-java --- ...eus-hardcoded-connection-password-java.yml | 576 ++++++++++++++++++ ...oded-connection-password-java-snapshot.yml | 169 +++++ ...ardcoded-connection-password-java-test.yml | 25 + 3 files changed, 770 insertions(+) create mode 100644 rules/java/security/datanucleus-hardcoded-connection-password-java.yml create mode 100644 tests/__snapshots__/datanucleus-hardcoded-connection-password-java-snapshot.yml create mode 100644 tests/java/datanucleus-hardcoded-connection-password-java-test.yml diff --git a/rules/java/security/datanucleus-hardcoded-connection-password-java.yml b/rules/java/security/datanucleus-hardcoded-connection-password-java.yml new file mode 100644 index 00000000..a6f04d7d --- /dev/null +++ b/rules/java/security/datanucleus-hardcoded-connection-password-java.yml @@ -0,0 +1,576 @@ +id: datanucleus-hardcoded-connection-password-java +severity: warning +language: java +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. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + - https://www.datanucleus.org/javadocs/api.jdo/5.0/org/datanucleus/api/jdo/JDOPersistenceManagerFactory.html +utils: + PATTERN_1: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^datanucleus.api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.*; + PATTERN_2: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^datanucleus.api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_3: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.*; + PATTERN_4: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_5: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^org.datanucleus.api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + PATTERN_6: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^org.datanucleus.api.jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_7: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.api.*; + PATTERN_8: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: scoped_type_identifier + regex: '^jdo.JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.api.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C + PATTERN_9: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + pattern: $C + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: type_identifier + regex: '^JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.api.jdo.*; + PATTERN_10: + kind: identifier + pattern: $B + all: + - inside: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: method_invocation + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $A + - has: + stopBy: neighbor + kind: identifier + pattern: $B + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $D + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: local_variable_declaration + all: + - has: + stopBy: end + kind: type_identifier + regex: '^JDOPersistenceManagerFactory$' + - has: + stopBy: end + kind: identifier + pattern: $A + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: import_declaration + pattern: import org.datanucleus.api.jdo.*; + - inside: + stopBy: end + kind: class_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $D + - has: + stopBy: neighbor + kind: string_literal + pattern: $C +rule: + kind: identifier + any: + - matches: PATTERN_1 + - matches: PATTERN_2 + - matches: PATTERN_3 + - matches: PATTERN_4 + - matches: PATTERN_5 + - matches: PATTERN_6 + - matches: PATTERN_7 + - matches: PATTERN_8 + - matches: PATTERN_9 + - matches: PATTERN_10 +constraints: + B: + regex: '^setConnectionPassword$' + C: + kind: string_literal + not: + regex: ^""$ diff --git a/tests/__snapshots__/datanucleus-hardcoded-connection-password-java-snapshot.yml b/tests/__snapshots__/datanucleus-hardcoded-connection-password-java-snapshot.yml new file mode 100644 index 00000000..e7fb33bb --- /dev/null +++ b/tests/__snapshots__/datanucleus-hardcoded-connection-password-java-snapshot.yml @@ -0,0 +1,169 @@ +id: datanucleus-hardcoded-connection-password-java +snapshots: + ? | + import org.datanucleus.api.jdo.*; + public class test { + private String password = "asdf"; + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } + : labels: + - source: setConnectionPassword + style: primary + start: 213 + end: 234 + - source: pmf + style: secondary + start: 209 + end: 212 + - source: setConnectionPassword + style: secondary + start: 213 + end: 234 + - source: password + style: secondary + start: 235 + end: 243 + - source: (password) + style: secondary + start: 234 + end: 244 + - source: pmf.setConnectionPassword(password) + style: secondary + start: 209 + end: 244 + - source: pmf.setConnectionPassword(password); + style: secondary + start: 209 + end: 245 + - source: JDOPersistenceManagerFactory + style: secondary + start: 130 + end: 158 + - source: pmf + style: secondary + start: 162 + end: 165 + - source: JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + style: secondary + start: 130 + end: 208 + - source: |- + public class test { + private String password = "asdf"; + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } + style: secondary + start: 34 + end: 247 + - source: import org.datanucleus.api.jdo.*; + style: secondary + start: 0 + end: 33 + - source: | + import org.datanucleus.api.jdo.*; + public class test { + private String password = "asdf"; + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } + style: secondary + start: 0 + end: 248 + - source: password + style: secondary + start: 69 + end: 77 + - source: '"asdf"' + style: secondary + start: 80 + end: 86 + - source: password = "asdf" + style: secondary + start: 69 + end: 86 + - source: |- + public class test { + private String password = "asdf"; + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } + style: secondary + start: 34 + end: 247 + ? | + import org.datanucleus.api.jdo.*; + public class test { + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword("password"); + } + : labels: + - source: setConnectionPassword + style: primary + start: 179 + end: 200 + - source: pmf + style: secondary + start: 175 + end: 178 + - source: setConnectionPassword + style: secondary + start: 179 + end: 200 + - source: '"password"' + style: secondary + start: 201 + end: 211 + - source: ("password") + style: secondary + start: 200 + end: 212 + - source: pmf.setConnectionPassword("password") + style: secondary + start: 175 + end: 212 + - source: pmf.setConnectionPassword("password"); + style: secondary + start: 175 + end: 213 + - source: JDOPersistenceManagerFactory + style: secondary + start: 96 + end: 124 + - source: pmf + style: secondary + start: 128 + end: 131 + - source: JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + style: secondary + start: 96 + end: 174 + - source: |- + public class test { + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword("password"); + } + style: secondary + start: 34 + end: 215 + - source: import org.datanucleus.api.jdo.*; + style: secondary + start: 0 + end: 33 + - source: | + import org.datanucleus.api.jdo.*; + public class test { + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword("password"); + } + style: secondary + start: 0 + end: 216 diff --git a/tests/java/datanucleus-hardcoded-connection-password-java-test.yml b/tests/java/datanucleus-hardcoded-connection-password-java-test.yml new file mode 100644 index 00000000..67312ee3 --- /dev/null +++ b/tests/java/datanucleus-hardcoded-connection-password-java-test.yml @@ -0,0 +1,25 @@ +id: datanucleus-hardcoded-connection-password-java +valid: + - | + import org.datanucleus.api.jdo.*; + public class test { + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } +invalid: + - | + import org.datanucleus.api.jdo.*; + public class test { + private String password = "asdf"; + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword(password); + } + - | + import org.datanucleus.api.jdo.*; + public class test { + public void setUp() throws SQLException { + JDOPersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(props); + pmf.setConnectionPassword("password"); + } From 7a9443b1f9db203c3645eeb63064bd22fbdc2b9b Mon Sep 17 00:00:00 2001 From: Sakshis Date: Sat, 7 Dec 2024 04:57:42 +0000 Subject: [PATCH 3/3] python-redis-empty-password-python --- .../python-redis-empty-password-python.yml | 173 +++++++++++++ ...n-redis-empty-password-python-snapshot.yml | 241 ++++++++++++++++++ ...ython-redis-empty-password-python-test.yml | 34 +++ 3 files changed, 448 insertions(+) create mode 100644 rules/python/security/python-redis-empty-password-python.yml create mode 100644 tests/__snapshots__/python-redis-empty-password-python-snapshot.yml create mode 100644 tests/python/python-redis-empty-password-python-test.yml diff --git a/rules/python/security/python-redis-empty-password-python.yml b/rules/python/security/python-redis-empty-password-python.yml new file mode 100644 index 00000000..a9f8e621 --- /dev/null +++ b/rules/python/security/python-redis-empty-password-python.yml @@ -0,0 +1,173 @@ +id: python-redis-empty-password-python +severity: warning +language: python +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + redis.Redis(..., password="",...): + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + pattern: redis.Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content + redis.Redis(..., password="",...)_with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + pattern: redis.Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $P + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: end + kind: identifier + paatern: $P + - has: + stopBy: neighbor + kind: string + not: + has: + stopby: end + kind: string_content + Redis(..., password="",...): + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + pattern: Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from redis import Redis + Redis(..., password="",...)_with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + pattern: Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $S + nthChild: 2 + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: end + kind: identifier + pattern: $S + - has: + stopBy: neighbor + kind: string + not: + has: + stopby: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from redis import Redis +rule: + kind: call + any: + - matches: redis.Redis(..., password="",...) + - matches: redis.Redis(..., password="",...)_with_instance + - matches: Redis(..., password="",...) + - matches: Redis(..., password="",...)_with_instance diff --git a/tests/__snapshots__/python-redis-empty-password-python-snapshot.yml b/tests/__snapshots__/python-redis-empty-password-python-snapshot.yml new file mode 100644 index 00000000..41faac87 --- /dev/null +++ b/tests/__snapshots__/python-redis-empty-password-python-snapshot.yml @@ -0,0 +1,241 @@ +id: python-redis-empty-password-python +snapshots: + ? | + foobar = '' + redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + : labels: + - source: redis.Redis(host='1.2.3.4', password=foobar, port=6379) + style: primary + start: 27 + end: 82 + - source: redis.Redis + style: secondary + start: 27 + end: 38 + - source: password + style: secondary + start: 55 + end: 63 + - source: password + style: secondary + start: 55 + end: 63 + - source: password=foobar + style: secondary + start: 55 + end: 70 + - source: (host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 38 + end: 82 + - source: foobar + style: secondary + start: 0 + end: 6 + - source: '''''' + style: secondary + start: 9 + end: 11 + - source: foobar = '' + style: secondary + start: 0 + end: 11 + - source: foobar = '' + style: secondary + start: 0 + end: 11 + - source: redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 12 + end: 82 + ? | + from redis import Redis + foobar = '' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + : labels: + - source: Redis(host='1.2.3.4', password=foobar, port=6379) + style: primary + start: 51 + end: 100 + - source: Redis + style: secondary + start: 51 + end: 56 + - source: password + style: secondary + start: 73 + end: 81 + - source: foobar + style: secondary + start: 82 + end: 88 + - source: password=foobar + style: secondary + start: 73 + end: 88 + - source: (host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 56 + end: 100 + - source: foobar + style: secondary + start: 24 + end: 30 + - source: '''''' + style: secondary + start: 33 + end: 35 + - source: foobar = '' + style: secondary + start: 24 + end: 35 + - source: foobar = '' + style: secondary + start: 24 + end: 35 + - source: redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 36 + end: 100 + - source: from redis import Redis + style: secondary + start: 0 + end: 23 + - source: | + from redis import Redis + foobar = '' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 0 + end: 101 + ? | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + : labels: + - source: |- + Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + style: primary + start: 39 + end: 107 + - source: Redis + style: secondary + start: 39 + end: 44 + - source: password + style: secondary + start: 88 + end: 96 + - source: '''''' + style: secondary + start: 97 + end: 99 + - source: password='' + style: secondary + start: 88 + end: 99 + - source: |- + ( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + style: secondary + start: 44 + end: 107 + - source: from redis import Redis + style: secondary + start: 0 + end: 23 + - source: | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + style: secondary + start: 0 + end: 108 + ? | + redis_client = redis.Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + : labels: + - source: |- + redis.Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + style: primary + start: 15 + end: 89 + - source: redis.Redis + style: secondary + start: 15 + end: 26 + - source: password + style: secondary + start: 70 + end: 78 + - source: '''''' + style: secondary + start: 79 + end: 81 + - source: password='' + style: secondary + start: 70 + end: 81 + - source: |- + ( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + style: secondary + start: 26 + end: 89 + ? | + redis_client = redis.Redis(host='10.0.0.1', port=6379, password="") + : labels: + - source: redis.Redis(host='10.0.0.1', port=6379, password="") + style: primary + start: 15 + end: 67 + - source: redis.Redis + style: secondary + start: 15 + end: 26 + - source: password + style: secondary + start: 55 + end: 63 + - source: '""' + style: secondary + start: 64 + end: 66 + - source: password="" + style: secondary + start: 55 + end: 66 + - source: (host='10.0.0.1', port=6379, password="") + style: secondary + start: 26 + end: 67 diff --git a/tests/python/python-redis-empty-password-python-test.yml b/tests/python/python-redis-empty-password-python-test.yml new file mode 100644 index 00000000..91f40279 --- /dev/null +++ b/tests/python/python-redis-empty-password-python-test.yml @@ -0,0 +1,34 @@ +id: python-redis-empty-password-python +valid: + - | + redis_client = Redis( + host='localhost', + port=6379, + password=os.getenv('REDIS_PASSWORD', ''), + db=5 + ) +invalid: + - | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + - | + redis_client = redis.Redis( + host='prod.redis.example.com', + port=6379, + password='', + db=3 + ) + - | + redis_client = redis.Redis(host='10.0.0.1', port=6379, password="") + - | + foobar = '' + redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + - | + from redis import Redis + foobar = '' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379)