Skip to content

Commit 8fc3b26

Browse files
committed
add string concat as a sink for code-construction
1 parent 2e4f4c6 commit 8fc3b26

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,40 @@ module UnsafeCodeConstruction {
9696
override string getSinkType() { result = "string interpolation" }
9797
}
9898

99+
private class AddRoot extends Ast::AddExpr {
100+
AddRoot() { not this.getParent() instanceof Ast::AddExpr }
101+
102+
private Ast::AstNode getALeafOrAdd() {
103+
result = this.getAChild()
104+
or
105+
result = getALeafOrAdd().(Ast::AddExpr).getAChild()
106+
}
107+
108+
Ast::AstNode getALeaf() {
109+
result = getALeafOrAdd() and
110+
not result instanceof Ast::AddExpr
111+
}
112+
}
113+
114+
/**
115+
* A string constructed from a string-concatenation (e.g. `"foo " + sink`),
116+
* where the resulting string ends up being executed as a code.
117+
*/
118+
class StringConcatAsSink extends Sink {
119+
Concepts::CodeExecution s;
120+
121+
StringConcatAsSink() {
122+
exists(AddRoot add |
123+
any(DataFlow::Node n | n.asExpr().getExpr() = add) = getANodeExecutedAsCode(s) and
124+
this.asExpr().getExpr() = add.getALeaf()
125+
)
126+
}
127+
128+
override DataFlow::Node getCodeSink() { result = s }
129+
130+
override string getSinkType() { result = "string concatenation" }
131+
}
132+
99133
import codeql.ruby.security.TaintedFormatStringSpecific as TaintedFormat
100134

101135
/**

ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/UnsafeCodeConstruction.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edges
77
| impl/unsafeCode.rb:37:15:37:15 | x : | impl/unsafeCode.rb:40:10:40:12 | arr |
88
| impl/unsafeCode.rb:37:15:37:15 | x : | impl/unsafeCode.rb:44:10:44:12 | arr |
99
| impl/unsafeCode.rb:47:15:47:15 | x : | impl/unsafeCode.rb:49:9:49:12 | #{...} |
10+
| impl/unsafeCode.rb:54:21:54:21 | x : | impl/unsafeCode.rb:55:22:55:22 | x |
1011
nodes
1112
| impl/unsafeCode.rb:2:12:2:17 | target : | semmle.label | target : |
1213
| impl/unsafeCode.rb:3:17:3:25 | #{...} | semmle.label | #{...} |
@@ -23,6 +24,8 @@ nodes
2324
| impl/unsafeCode.rb:44:10:44:12 | arr | semmle.label | arr |
2425
| impl/unsafeCode.rb:47:15:47:15 | x : | semmle.label | x : |
2526
| impl/unsafeCode.rb:49:9:49:12 | #{...} | semmle.label | #{...} |
27+
| impl/unsafeCode.rb:54:21:54:21 | x : | semmle.label | x : |
28+
| impl/unsafeCode.rb:55:22:55:22 | x | semmle.label | x |
2629
subpaths
2730
#select
2831
| impl/unsafeCode.rb:3:17:3:25 | #{...} | impl/unsafeCode.rb:2:12:2:17 | target : | impl/unsafeCode.rb:3:17:3:25 | #{...} | This string interpolation which depends on $@ is later $@. | impl/unsafeCode.rb:2:12:2:17 | target | library input | impl/unsafeCode.rb:3:5:3:27 | call to eval | interpreted as code |
@@ -33,3 +36,4 @@ subpaths
3336
| impl/unsafeCode.rb:40:10:40:12 | arr | impl/unsafeCode.rb:37:15:37:15 | x : | impl/unsafeCode.rb:40:10:40:12 | arr | This array which depends on $@ is later $@. | impl/unsafeCode.rb:37:15:37:15 | x | library input | impl/unsafeCode.rb:40:5:40:24 | call to eval | interpreted as code |
3437
| impl/unsafeCode.rb:44:10:44:12 | arr | impl/unsafeCode.rb:37:15:37:15 | x : | impl/unsafeCode.rb:44:10:44:12 | arr | This array which depends on $@ is later $@. | impl/unsafeCode.rb:37:15:37:15 | x | library input | impl/unsafeCode.rb:44:5:44:24 | call to eval | interpreted as code |
3538
| impl/unsafeCode.rb:49:9:49:12 | #{...} | impl/unsafeCode.rb:47:15:47:15 | x : | impl/unsafeCode.rb:49:9:49:12 | #{...} | This string interpolation which depends on $@ is later $@. | impl/unsafeCode.rb:47:15:47:15 | x | library input | impl/unsafeCode.rb:51:5:51:13 | call to eval | interpreted as code |
39+
| impl/unsafeCode.rb:55:22:55:22 | x | impl/unsafeCode.rb:54:21:54:21 | x : | impl/unsafeCode.rb:55:22:55:22 | x | This string concatenation which depends on $@ is later $@. | impl/unsafeCode.rb:54:21:54:21 | x | library input | impl/unsafeCode.rb:56:5:56:13 | call to eval | interpreted as code |

ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/impl/unsafeCode.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,9 @@ def hereDoc(x)
5050
HERE
5151
eval(foo) # NOT OK
5252
end
53+
54+
def string_concat(x)
55+
foo = "foo = " + x
56+
eval(foo) # NOT OK
57+
end
5358
end

0 commit comments

Comments
 (0)