diff --git a/rules/c/security/return-c-str-c.yml b/rules/c/security/return-c-str-c.yml new file mode 100644 index 00000000..b1a913f3 --- /dev/null +++ b/rules/c/security/return-c-str-c.yml @@ -0,0 +1,203 @@ +id: return-c-str-c +language: c +severity: warning +message: >- + `$FUNC` returns a pointer to the memory owned by `$STR`. This pointer + is invalid after `$STR` goes out of scope, which can trigger a use after + free. +note: >- + [CWE-416] Use After Free + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/DCL30-C.+Declare+objects+with+appropriate+storage+durations + - https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP54-CPP.+Do+not+access+an+object+outside+of+its+lifetime +utils: + MATCH_PATTERN_STR_METHOD_WITH_STD_TWO: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: field_identifier + pattern: $METHOD + - has: + stopBy: end + kind: argument_list + - follows: + stopBy: end + kind: labeled_statement + all: + - has: + stopBy: end + kind: statement_identifier + regex: "^std$" + - has: + stopBy: end + kind: identifier + regex: "^basic_string<$TYPE>|string|wstring$" + - has: + stopBy: end + kind: expression_statement + all: + - has: + stopBy: end + kind: identifier + patttern: $E + - inside: + stopBy: end + kind: compound_statement + not: + follows: + stopBy: end + kind: function_declarator + has: + stopBy: neighbor + kind: identifier + regex: "return.*" + MATCH_PATTERN_STR_METHOD_WITH_STD_THREE: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: field_identifier + pattern: $METHOD + - has: + stopBy: end + kind: argument_list + - inside: + stopBy: end + kind: compound_statement + follows: + stopBy: end + kind: pointer_declarator + has: + stopBy: end + kind: parameter_list + all: + - has: + stopBy: end + kind: type_identifier + regex: "^std$" + - has: + stopBy: end + kind: identifier + regex: "^basic_string<$TYPE>|string|wstring$" + - has: + stopBy: end + kind: identifier + pattern: $E + MATCH_PATTERN_STR_METHOD_WITHOUT_STD_THREE: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: field_identifier + pattern: $METHOD + - has: + stopBy: end + kind: argument_list + - inside: + stopBy: end + kind: compound_statement + follows: + stopBy: end + kind: pointer_declarator + has: + stopBy: end + kind: parameter_list + has: + stopBy: end + kind: parameter_declaration + all: + - has: + stopBy: end + kind: type_identifier + regex: "^basic_string<$TYPE>|string|wstring$" + - has: + stopBy: neighbor + kind: identifier + pattern: $E + MATCH_PATTERN_STR_METHOD_WITHOUT_STD_TWO: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $T + - has: + stopBy: end + kind: field_identifier + pattern: $METHOD + - has: + stopBy: end + kind: argument_list + - follows: + stopBy: end + kind: declaration + all: + - has: + stopBy: neighbor + kind: type_identifier + regex: "^basic_string<$TYPE>|string|wstring$" + - has: + stopBy: neighbor + kind: identifier + pattern: $T +rule: + any: + - pattern: return basic_string<$TYPE>($$$).$METHOD(); + - pattern: return std::basic_string<$TYPE>($$$).$METHOD(); + - pattern: return string($$$).$METHOD(); + - pattern: return std::string($$$).$METHOD(); + - pattern: return wstring($$$).$METHOD(); + - pattern: return std::wstring($$$).$METHOD(); + - matches: MATCH_PATTERN_STR_METHOD_WITH_STD_TWO + - matches: MATCH_PATTERN_STR_METHOD_WITHOUT_STD_TWO + - matches: MATCH_PATTERN_STR_METHOD_WITH_STD_THREE + - matches: MATCH_PATTERN_STR_METHOD_WITHOUT_STD_THREE + +constraints: + METHOD: + regex: "c_str|data" diff --git a/rules/ruby/security/hardcoded-http-auth-in-controller-copy-ruby.yml b/rules/ruby/security/hardcoded-http-auth-in-controller-copy-ruby.yml new file mode 100644 index 00000000..c4d5dbfe --- /dev/null +++ b/rules/ruby/security/hardcoded-http-auth-in-controller-copy-ruby.yml @@ -0,0 +1,55 @@ +id: hardcoded-http-auth-in-controller-copy-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: end + kind: simple_symbol + regex: "^:password$" + - inside: + stopBy: end + 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-copy-ruby-snapshot.yml b/tests/__snapshots__/hardcoded-http-auth-in-controller-copy-ruby-snapshot.yml new file mode 100644 index 00000000..be378ba7 --- /dev/null +++ b/tests/__snapshots__/hardcoded-http-auth-in-controller-copy-ruby-snapshot.yml @@ -0,0 +1,114 @@ +id: hardcoded-http-auth-in-controller-copy-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: 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 + ? | + 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: 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: 161 + - source: |- + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + puts "do more stuff"" + style: secondary + start: 50 + end: 157 + - 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/__snapshots__/return-c-str-c-snapshot.yml b/tests/__snapshots__/return-c-str-c-snapshot.yml new file mode 100644 index 00000000..77f074bf --- /dev/null +++ b/tests/__snapshots__/return-c-str-c-snapshot.yml @@ -0,0 +1,76 @@ +id: return-c-str-c +snapshots: + ? | + char *f(){ + std::string s; + return s.c_str(); + } + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + char *f(std::string s) { + return s.c_str(); + } + class Foo { + char *f() { + std::string s; + return s.c_str(); + } + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + : labels: + - source: return s.c_str(); + style: primary + start: 26 + end: 43 + - source: s + style: secondary + start: 33 + end: 34 + - source: c_str + style: secondary + start: 35 + end: 40 + - source: s.c_str + style: secondary + start: 33 + end: 40 + - source: () + style: secondary + start: 40 + end: 42 + - source: s.c_str() + style: secondary + start: 33 + end: 42 + - source: std + style: secondary + start: 11 + end: 14 + - source: string + style: secondary + start: 16 + end: 22 + - source: s + style: secondary + start: 23 + end: 24 + - source: s; + style: secondary + start: 23 + end: 25 + - source: std::string s; + style: secondary + start: 11 + end: 25 + - source: |- + { + std::string s; + return s.c_str(); + } + style: secondary + start: 9 + end: 45 diff --git a/tests/c/return-c-str-c-test.yml b/tests/c/return-c-str-c-test.yml new file mode 100644 index 00000000..55cbefd3 --- /dev/null +++ b/tests/c/return-c-str-c-test.yml @@ -0,0 +1,29 @@ +id: return-c-str-c +valid: + - | + StringWrapper return_wrapped() { + std::string s = "foo"; + return s.c_str(); + } +invalid: + - | + char *f(){ + std::string s; + return s.c_str(); + } + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + char *f(std::string s) { + return s.c_str(); + } + class Foo { + char *f() { + std::string s; + return s.c_str(); + } + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } diff --git a/tests/ruby/hardcoded-http-auth-in-controller-copy-ruby-test.yml b/tests/ruby/hardcoded-http-auth-in-controller-copy-ruby-test.yml new file mode 100644 index 00000000..778ba1be --- /dev/null +++ b/tests/ruby/hardcoded-http-auth-in-controller-copy-ruby-test.yml @@ -0,0 +1,13 @@ +id: hardcoded-http-auth-in-controller-copy-ruby +valid: + - | + class OkController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => 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