diff --git a/rules/c/security/dont-call-system-c.yml b/rules/c/security/dont-call-system-c.yml new file mode 100644 index 00000000..90a7242b --- /dev/null +++ b/rules/c/security/dont-call-system-c.yml @@ -0,0 +1,26 @@ +id: dont-call-system-c +language: c +severity: warning +message: >- + Don't call `system`. It's a high-level wrapper that allows for stacking + multiple commands. Always prefer a more restrictive API such as calling + `execve` from the `exec` family. +note: >- + [CWE-78] Improper Neutralization of Special Elements used in an OS + Command ('OS Command Injection'). + [REFERENCES] + - https://owasp.org/Top10/A03_2021-Injection +utils: + PATTERN_SYSTEM: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^system$" + - has: + stopBy: neighbor + kind: argument_list +rule: + kind: call_expression + matches: PATTERN_SYSTEM diff --git a/rules/cpp/security/dont-call-system-cpp.yml b/rules/cpp/security/dont-call-system-cpp.yml new file mode 100644 index 00000000..96e34119 --- /dev/null +++ b/rules/cpp/security/dont-call-system-cpp.yml @@ -0,0 +1,26 @@ +id: dont-call-system-cpp +language: cpp +severity: warning +message: >- + Don't call `system`. It's a high-level wrapper that allows for stacking + multiple commands. Always prefer a more restrictive API such as calling + `execve` from the `exec` family. +note: >- + [CWE-78] Improper Neutralization of Special Elements used in an OS + Command ('OS Command Injection'). + [REFERENCES] + - https://owasp.org/Top10/A03_2021-Injection +utils: + PATTERN_SYSTEM: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^system$" + - has: + stopBy: neighbor + kind: argument_list +rule: + kind: call_expression + matches: PATTERN_SYSTEM diff --git a/tests/__snapshots__/dont-call-system-c-snapshot.yml b/tests/__snapshots__/dont-call-system-c-snapshot.yml new file mode 100644 index 00000000..6085d5c7 --- /dev/null +++ b/tests/__snapshots__/dont-call-system-c-snapshot.yml @@ -0,0 +1,41 @@ +id: dont-call-system-c +snapshots: + ? | + void test_002(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + system(cmdbuf); + } + void test_001(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + if (len_wanted >= BUFFERSIZE) + { + /* Handle error */ + } + else if (len_wanted < 0) + { + /* Handle error */ + } + else if (system(cmdbuf) == -1) + { + /* Handle error */ + } + } + : labels: + - source: system(cmdbuf) + style: primary + start: 156 + end: 170 + - source: system + style: secondary + start: 156 + end: 162 + - source: (cmdbuf) + style: secondary + start: 162 + end: 170 diff --git a/tests/__snapshots__/dont-call-system-cpp-snapshot.yml b/tests/__snapshots__/dont-call-system-cpp-snapshot.yml new file mode 100644 index 00000000..b26da26d --- /dev/null +++ b/tests/__snapshots__/dont-call-system-cpp-snapshot.yml @@ -0,0 +1,41 @@ +id: dont-call-system-cpp +snapshots: + ? | + void test_002(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + system(cmdbuf); + } + void test_001(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + if (len_wanted >= BUFFERSIZE) + { + /* Handle error */ + } + else if (len_wanted < 0) + { + /* Handle error */ + } + else if (system(cmdbuf) == -1) + { + /* Handle error */ + } + } + : labels: + - source: system(cmdbuf) + style: primary + start: 156 + end: 170 + - source: system + style: secondary + start: 156 + end: 162 + - source: (cmdbuf) + style: secondary + start: 162 + end: 170 diff --git a/tests/c/dont-call-system-c-test.yml b/tests/c/dont-call-system-c-test.yml new file mode 100644 index 00000000..3d482dfc --- /dev/null +++ b/tests/c/dont-call-system-c-test.yml @@ -0,0 +1,34 @@ +id: dont-call-system-c +valid: + - | + void test_003(const char *input) + { + storer->store_binary(Clocks->system()); + } +invalid: + - | + void test_002(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + system(cmdbuf); + } + void test_001(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + if (len_wanted >= BUFFERSIZE) + { + /* Handle error */ + } + else if (len_wanted < 0) + { + /* Handle error */ + } + else if (system(cmdbuf) == -1) + { + /* Handle error */ + } + } diff --git a/tests/cpp/dont-call-system-cpp-test.yml b/tests/cpp/dont-call-system-cpp-test.yml new file mode 100644 index 00000000..acab0c60 --- /dev/null +++ b/tests/cpp/dont-call-system-cpp-test.yml @@ -0,0 +1,34 @@ +id: dont-call-system-cpp +valid: + - | + void test_003(const char *input) + { + storer->store_binary(Clocks->system()); + } +invalid: + - | + void test_002(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + system(cmdbuf); + } + void test_001(const char *input) + { + char cmdbuf[BUFFERSIZE]; + int len_wanted = snprintf(cmdbuf, BUFFERSIZE, + "any_cmd '%s'", input); + if (len_wanted >= BUFFERSIZE) + { + /* Handle error */ + } + else if (len_wanted < 0) + { + /* Handle error */ + } + else if (system(cmdbuf) == -1) + { + /* Handle error */ + } + }