Skip to content

Commit d3812f5

Browse files
committed
Ruby: Add another code injection example to qhelp
1 parent d95a4a7 commit d3812f5

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

ruby/ql/src/queries/security/cwe-094/UnsafeCodeConstruction.qhelp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,26 @@ to define the getter method.
6666
<sample src="examples/UnsafeCodeConstruction2Safe.rb" />
6767
</example>
6868

69+
<example>
70+
<p>
71+
This example dynamically registers a method on another class which
72+
forwards its arguments to the registering module. This approach uses
73+
<code>module_eval</code> and string interpolation to construct class variables
74+
and methods.
75+
</p>
76+
77+
<sample src="examples/UnsafeCodeConstruction3.rb" />
78+
79+
<p>
80+
A safer approach is to use <code>class_variable_set</code> and
81+
<code>class_variable_get</code> along with <code>define_method</code>. String
82+
interpolation is still used to construct the class variable name, but this is
83+
safe because <code>class_variable_set<code> is not susceptible to code injection.
84+
</p>
85+
86+
<sample src="examples/UnsafeCodeConstruction3Safe.rb" />
87+
</example>
88+
6989
<references>
7090
<li>
7191
OWASP:
@@ -74,5 +94,11 @@ OWASP:
7494
<li>
7595
Wikipedia: <a href="https://en.wikipedia.org/wiki/Code_injection">Code Injection</a>.
7696
</li>
97+
<li>
98+
Ruby documentation: <a href="https://docs.ruby-lang.org/en/3.2/Module.html#method-i-define_method"><code>define_method</code></a>.
99+
</li>
100+
<li>
101+
Ruby documentation: <a href="https://docs.ruby-lang.org/en/3.2/Module.html#method-i-class_variable_set"><code>class_variable_set</code></a>.
102+
</li>
77103
</references>
78104
</qhelp>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module Invoker
2+
def attach(klass, name)
3+
invoker = self
4+
klass.module_eval <<-CODE
5+
@@#{name} = invoker
6+
7+
def #{name}(*args)
8+
@@#{name}.call(*args)
9+
end
10+
CODE
11+
end
12+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Invoker
2+
def attach(klass, name)
3+
var = :"@@#{name}"
4+
klass.class_variable_set(var, self)
5+
klass.define_method(name) do |*args|
6+
self.class.class_variable_get(var).call(*args)
7+
end
8+
end
9+
end

0 commit comments

Comments
 (0)