Skip to content

Commit 6dc3ce3

Browse files
committed
make rb/stored-xss track ActiveRecord db accesses
1 parent f6dd6bb commit 6dc3ce3

1 file changed

Lines changed: 41 additions & 12 deletions

File tree

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

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
private import ruby
66
private import codeql.ruby.DataFlow
7+
private import codeql.ruby.DataFlow2
78
private import codeql.ruby.CFG
89
private import codeql.ruby.Concepts
910
private import codeql.ruby.Frameworks
1011
private import codeql.ruby.frameworks.ActionController
1112
private import codeql.ruby.frameworks.ActionView
13+
private import codeql.ruby.frameworks.ActiveRecord
1214
private import codeql.ruby.dataflow.RemoteFlowSources
1315
private import codeql.ruby.dataflow.BarrierGuards
1416
private import codeql.ruby.dataflow.internal.DataFlowDispatch
@@ -122,9 +124,9 @@ private module Shared {
122124
}
123125

124126
/**
125-
* An additional step that is taint-preserving in the context of reflected XSS.
127+
* An additional step that is preserves dataflow in the context of reflected XSS.
126128
*/
127-
predicate isAdditionalXSSTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
129+
predicate isAdditionalXSSFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
128130
// node1 is a `locals` argument to a render call...
129131
exists(RenderCall call, Pair kvPair, string hashKey |
130132
call.getLocals().getAKeyValuePair() = kvPair and
@@ -229,19 +231,38 @@ module ReflectedXSS {
229231
}
230232

231233
// Consider all arbitrary XSS taint steps to be reflected XSS taint steps
232-
predicate isAdditionalXSSTaintStep = Shared::isAdditionalXSSTaintStep/2;
234+
predicate isAdditionalXSSTaintStep = Shared::isAdditionalXSSFlowStep/2;
233235

234236
/**
235237
* A source of remote user input, considered as a flow source.
236238
*/
237239
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
238240
}
239241

240-
/**
241-
* Provides default sources, sinks and sanitizers for detecting
242-
* "stored server-side cross-site scripting" vulnerabilities, as well as
243-
* extension points for adding your own.
244-
*/
242+
private module OrmTracking {
243+
/**
244+
* A data flow configuration to track flow from finder calls to field accesses.
245+
*/
246+
class Configuration extends DataFlow2::Configuration {
247+
Configuration() { this = "OrmTracking" }
248+
249+
// TODO: abstract to ORMFinderCall concept
250+
override predicate isSource(DataFlow2::Node source) {
251+
source instanceof ActiveRecordModelInstantiation
252+
}
253+
254+
// Select any call node and narrow down later
255+
override predicate isSink(DataFlow2::Node sink) { sink instanceof DataFlow2::CallNode }
256+
257+
override predicate isAdditionalFlowStep(DataFlow2::Node node1, DataFlow2::Node node2) {
258+
Shared::isAdditionalXSSFlowStep(node1, node2)
259+
or
260+
// Propagate flow through arbitrary method calls
261+
node2.(DataFlow2::CallNode).getReceiver() = node1
262+
}
263+
}
264+
}
265+
245266
module StoredXSS {
246267
/** A data flow source for stored XSS vulnerabilities. */
247268
abstract class Source extends Shared::Source { }
@@ -268,11 +289,19 @@ module StoredXSS {
268289
}
269290
}
270291

271-
// Consider all arbitrary XSS taint steps to be stored XSS taint steps
272-
predicate isAdditionalXSSTaintStep = Shared::isAdditionalXSSTaintStep/2;
292+
predicate isAdditionalXSSTaintStep = Shared::isAdditionalXSSFlowStep/2;
293+
294+
private class ActiveRecordModelFieldAccessAsSource extends Source {
295+
ActiveRecordModelFieldAccessAsSource() {
296+
exists(OrmTracking::Configuration subConfig, DataFlow2::Node subSrc |
297+
subConfig.hasFlow(subSrc, this) and
298+
activeRecordMethodMayAccessField(subSrc.(ActiveRecordModelInstantiation).getClass(),
299+
this.asExpr().getExpr())
300+
)
301+
}
302+
}
273303

274304
/** A file read, considered as a flow source for stored XSS. */
275-
class FileSystemReadAccessAsSource extends Source instanceof FileSystemReadAccess { }
305+
private class FileSystemReadAccessAsSource extends Source instanceof FileSystemReadAccess { }
276306
// TODO: Consider `FileNameSource` flowing to script tag `src` attributes and similar
277-
// TODO: ORM database reads as sources
278307
}

0 commit comments

Comments
 (0)