Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit adabd2d

Browse files
committed
add qldoc and customizations module
1 parent c375a0c commit adabd2d

3 files changed

Lines changed: 107 additions & 42 deletions

File tree

javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,59 +11,30 @@
1111
* external/cwe/cwe-116
1212
*/
1313

14-
// TODO: Proper customizations module, Source class Sink class etc. and qldoc.
1514
import javascript
15+
import semmle.javascript.security.dataflow.ImproperCodeSanitization::ImproperCodeSanitization
1616
import DataFlow::PathGraph
1717
private import semmle.javascript.heuristics.HeuristicSinks
1818
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
1919

2020
/**
21-
* A taint-tracking configuration for reasoning about improper code sanitization vulnerabilities.
21+
* Gets a type-tracked instance of `RemoteFlowSource` using type-tracker `t`.
2222
*/
23-
class Configuration extends TaintTracking::Configuration {
24-
Configuration() { this = "ImproperCodeSanitization" }
25-
26-
override predicate isSource(DataFlow::Node source) { source = source() }
27-
28-
override predicate isSink(DataFlow::Node sink) { sink = sink() }
29-
30-
override predicate isSanitizer(DataFlow::Node sanitizer) {
31-
sanitizer instanceof StringReplaceCall // any string-replace that happens after the bad-sanitizer, is assumed to be a good sanitizer.
32-
// TODO: Specialize? This regexp sanitizes: /[<>\b\f\n\r\t\0\u2028\u2029]/g
33-
}
34-
}
35-
36-
private DataFlow::CallNode source() {
37-
result instanceof HtmlSanitizerCall
38-
or
39-
result = DataFlow::globalVarRef("JSON").getAMemberCall("stringify")
40-
}
41-
42-
private StringOps::ConcatenationLeaf sink() {
43-
exists(StringOps::ConcatenationRoot root, int i |
44-
root.getOperand(i) = result and
45-
not exists(result.getStringValue())
46-
|
47-
exists(StringOps::ConcatenationLeaf functionLeaf |
48-
functionLeaf = root.getOperand(any(int j | j < i))
49-
|
50-
functionLeaf
51-
.getStringValue()
52-
.regexpMatch([".*function( )?([a-zA-Z0-9]+)?( )?\\(.*", ".*eval\\(.*",
53-
".*new Function\\(.*", "(^|.*[^a-zA-Z0-9])\\(.*\\)( )?=>.*"])
54-
)
55-
)
56-
}
57-
58-
DataFlow::SourceNode remoteFlow(DataFlow::TypeTracker t) {
23+
private DataFlow::SourceNode remoteFlow(DataFlow::TypeTracker t) {
5924
t.start() and
6025
result instanceof RemoteFlowSource
6126
or
6227
exists(DataFlow::TypeTracker t2 | result = remoteFlow(t2).track(t2, t))
6328
}
6429

65-
DataFlow::SourceNode remoteFlow() { result = remoteFlow(DataFlow::TypeTracker::end()) }
30+
/**
31+
* Gets a type-tracked reference to a `RemoteFlowSource`.
32+
*/
33+
private DataFlow::SourceNode remoteFlow() { result = remoteFlow(DataFlow::TypeTracker::end()) }
6634

35+
/**
36+
* Gets a type-back-tracked instance of a code-injection sink using type-tracker `t`.
37+
*/
6738
private DataFlow::Node endsInCodeInjectionSink(DataFlow::TypeBackTracker t) {
6839
t.start() and
6940
(
@@ -76,9 +47,11 @@ private DataFlow::Node endsInCodeInjectionSink(DataFlow::TypeBackTracker t) {
7647
exists(DataFlow::TypeBackTracker t2 | t = t2.smallstep(result, endsInCodeInjectionSink(t2)))
7748
}
7849

79-
DataFlow::Node endsInCodeInjectionSink() {
80-
result = endsInCodeInjectionSink(DataFlow::TypeBackTracker::end()) and
81-
result.getFile().getBaseName() = "bad-code-sanitization.js" // TODO: TMp
50+
/**
51+
* Gets a reference to to a data-flow node that ends in a code-injection sink.
52+
*/
53+
private DataFlow::Node endsInCodeInjectionSink() {
54+
result = endsInCodeInjectionSink(DataFlow::TypeBackTracker::end())
8255
}
8356

8457
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Provides a taint-tracking configuration for reasoning about improper code
3+
* sanitization.
4+
*
5+
* Note, for performance reasons: only import this file if
6+
* `ImproperCodeSanitization::Configuration` is needed, otherwise
7+
* `ImproperCodeSanitizationCustomizations` should be imported instead.
8+
*/
9+
10+
import javascript
11+
12+
module ImproperCodeSanitization {
13+
import ImproperCodeSanitizationCustomizations::ImproperCodeSanitization
14+
15+
/**
16+
* A taint-tracking configuration for reasoning about improper code sanitization vulnerabilities.
17+
*/
18+
class Configuration extends TaintTracking::Configuration {
19+
Configuration() { this = "ImproperCodeSanitization" }
20+
21+
override predicate isSource(DataFlow::Node source) { source instanceof Source }
22+
23+
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
24+
25+
override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof Sanitizer }
26+
}
27+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for reasoning about
3+
* improper code sanitization, as well as extension points for
4+
* adding your own.
5+
*/
6+
7+
import javascript
8+
9+
module ImproperCodeSanitization {
10+
/**
11+
* A data flow source for improper code sanitization.
12+
*/
13+
abstract class Source extends DataFlow::Node { }
14+
15+
/**
16+
* A data flow sink for improper code sanitization.
17+
*/
18+
abstract class Sink extends DataFlow::Node { }
19+
20+
/**
21+
* A sanitizer for improper code sanitization.
22+
*/
23+
abstract class Sanitizer extends DataFlow::Node { }
24+
25+
/**
26+
* A call to a HTML sanitizer seen as a source for improper code sanitization
27+
*/
28+
class HtmlSanitizerCallAsSource extends Source {
29+
HtmlSanitizerCallAsSource() { this instanceof HtmlSanitizerCall }
30+
}
31+
32+
/**
33+
* A call to `JSON.stringify()` seen as a source for improper code sanitization
34+
*/
35+
class JSONStringifyAsSource extends Source {
36+
JSONStringifyAsSource() { this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") }
37+
}
38+
39+
/**
40+
* A leaf in a string-concatenation, where the string-concatenation constructs code that looks like a function.
41+
*/
42+
class FunctionStringConstruction extends Sink, StringOps::ConcatenationLeaf {
43+
FunctionStringConstruction() {
44+
exists(StringOps::ConcatenationRoot root, int i |
45+
root.getOperand(i) = this and
46+
not exists(this.getStringValue())
47+
|
48+
exists(StringOps::ConcatenationLeaf functionLeaf |
49+
functionLeaf = root.getOperand(any(int j | j < i))
50+
|
51+
functionLeaf
52+
.getStringValue()
53+
.regexpMatch([".*function( )?([a-zA-Z0-9]+)?( )?\\(.*", ".*eval\\(.*",
54+
".*new Function\\(.*", "(^|.*[^a-zA-Z0-9])\\(.*\\)( )?=>.*"])
55+
)
56+
)
57+
}
58+
}
59+
60+
/**
61+
* A call to `String.prototype.replace` seen as a sanitizer for improper code sanitization.
62+
* All calls to replace that happens after the initial improper sanitization is seen as a sanitizer.
63+
*/
64+
class StringReplaceCallAsSanitizer extends Sanitizer, StringReplaceCall { }
65+
}

0 commit comments

Comments
 (0)