Skip to content

Commit a562568

Browse files
committed
add string concat as a sink for command-construction
1 parent 9d9de18 commit a562568

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

ruby/ql/lib/codeql/ruby/security/UnsafeShellCommandConstructionCustomizations.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,26 @@ module UnsafeShellCommandConstruction {
8181
override DataFlow::Node getStringConstruction() { result.asExpr().getExpr() = lit }
8282
}
8383

84+
/**
85+
* A string constructed from a string-concatenation (e.g. `"foo " + sink`),
86+
* where the resulting string ends up being executed as a shell command.
87+
*/
88+
class StringConcatAsSink extends Sink {
89+
Concepts::SystemCommandExecution s;
90+
Ast::AddExprRoot add;
91+
92+
StringConcatAsSink() {
93+
isUsedAsShellCommand(any(DataFlow::Node n | n.asExpr().getExpr() = add), s) and
94+
this.asExpr().getExpr() = add.getALeaf()
95+
}
96+
97+
override DataFlow::Node getCommandExecution() { result = s }
98+
99+
override string describe() { result = "string concatenation" }
100+
101+
override DataFlow::Node getStringConstruction() { result.asExpr().getExpr() = add }
102+
}
103+
84104
/**
85105
* A string constructed using a `.join(" ")` call, where the resulting string ends up being executed as a shell command.
86106
*/

ruby/ql/test/query-tests/security/cwe-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ edges
1111
| impl/unsafeShell.rb:47:16:47:21 | target : | impl/unsafeShell.rb:48:19:48:27 | #{...} |
1212
| impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:52:14:52:14 | x |
1313
| impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:54:29:54:29 | x |
14+
| impl/unsafeShell.rb:57:21:57:21 | x : | impl/unsafeShell.rb:58:23:58:23 | x |
1415
nodes
1516
| impl/sub/notImported.rb:2:12:2:17 | target : | semmle.label | target : |
1617
| impl/sub/notImported.rb:3:19:3:27 | #{...} | semmle.label | #{...} |
@@ -35,6 +36,8 @@ nodes
3536
| impl/unsafeShell.rb:51:17:51:17 | x : | semmle.label | x : |
3637
| impl/unsafeShell.rb:52:14:52:14 | x | semmle.label | x |
3738
| impl/unsafeShell.rb:54:29:54:29 | x | semmle.label | x |
39+
| impl/unsafeShell.rb:57:21:57:21 | x : | semmle.label | x : |
40+
| impl/unsafeShell.rb:58:23:58:23 | x | semmle.label | x |
3841
subpaths
3942
#select
4043
| impl/sub/notImported.rb:3:14:3:28 | "cat #{...}" | impl/sub/notImported.rb:2:12:2:17 | target : | impl/sub/notImported.rb:3:19:3:27 | #{...} | This string construction which depends on $@ is later used in a $@. | impl/sub/notImported.rb:2:12:2:17 | target | library input | impl/sub/notImported.rb:3:5:3:34 | call to popen | shell command |
@@ -49,3 +52,4 @@ subpaths
4952
| impl/unsafeShell.rb:48:14:48:28 | "cat #{...}" | impl/unsafeShell.rb:47:16:47:21 | target : | impl/unsafeShell.rb:48:19:48:27 | #{...} | This string construction which depends on $@ is later used in a $@. | impl/unsafeShell.rb:47:16:47:21 | target | library input | impl/unsafeShell.rb:48:5:48:34 | call to popen | shell command |
5053
| impl/unsafeShell.rb:52:14:52:24 | call to join | impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:52:14:52:14 | x | This array which depends on $@ is later used in a $@. | impl/unsafeShell.rb:51:17:51:17 | x | library input | impl/unsafeShell.rb:52:5:52:30 | call to popen | shell command |
5154
| impl/unsafeShell.rb:54:14:54:40 | call to join | impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:54:29:54:29 | x | This array which depends on $@ is later used in a $@. | impl/unsafeShell.rb:51:17:51:17 | x | library input | impl/unsafeShell.rb:54:5:54:46 | call to popen | shell command |
55+
| impl/unsafeShell.rb:58:14:58:23 | ... + ... | impl/unsafeShell.rb:57:21:57:21 | x : | impl/unsafeShell.rb:58:23:58:23 | x | This string concatenation which depends on $@ is later used in a $@. | impl/unsafeShell.rb:57:21:57:21 | x | library input | impl/unsafeShell.rb:58:5:58:29 | call to popen | shell command |

ruby/ql/test/query-tests/security/cwe-078/UnsafeShellCommandConstruction/impl/unsafeShell.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,8 @@ def arrayJoin(x)
5353

5454
IO.popen(["foo", "bar", x].join(' '), "w") # NOT OK
5555
end
56+
57+
def string_concat(x)
58+
IO.popen("cat " + x, "w") # NOT OK
59+
end
5660
end

0 commit comments

Comments
 (0)