JS: address review comments for js/unsafe-jquery-plugin

This commit is contained in:
Esben Sparre Andreasen
2020-01-30 08:32:22 +01:00
parent eaff78b37e
commit c70997febf
5 changed files with 48 additions and 11 deletions

View File

@@ -18,7 +18,7 @@
Otherwise, the plugin may write user input (for example, a URL query
parameter) to a web page without properly sanitizing the input first,
which allows for a cross-site scripting vulnerability in the client
application.
application through dynamic HTML construction.
</p>
</overview>
@@ -26,7 +26,9 @@
<recommendation>
<p>
Document all options that can lead to cross-site scripting attacks.
Document all options that can lead to cross-site scripting
attacks, and guard against unsafe inputs where dynamic HTML
construction is not intended.
</p>
</recommendation>

View File

@@ -36,7 +36,7 @@ module UnsafeJQueryPlugin {
// prefixing prevents forced html/css confusion:
// prefixing through concatenation:
succ.asExpr().(AddExpr).getRightOperand().flow() = pred
StringConcatenation::getFirstOperand(succ) != pred
or
// prefixing through a poor-mans templating system:
exists(DataFlow::MethodCallNode replace |
@@ -49,7 +49,7 @@ module UnsafeJQueryPlugin {
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) {
super.isSanitizerGuard(node) or
node instanceof IsElementSanitizer or
node instanceof PropertyPrecenseSanitizer
node instanceof PropertyPresenceSanitizer
}
}
}

View File

@@ -73,9 +73,9 @@ module UnsafeJQueryPlugin {
}
/**
* Gets an function that is registered as a jQuery plugin method at `def`.
* Gets a node that is registered as a jQuery plugin method at `def`.
*/
private DataFlow::FunctionNode getAJQueryPluginMethod(
private DataFlow::SourceNode getAJQueryPluginMethod(
DataFlow::TypeBackTracker t, DataFlow::Node def
) {
t.start() and
@@ -85,6 +85,13 @@ module UnsafeJQueryPlugin {
exists(DataFlow::TypeBackTracker t2 | result = getAJQueryPluginMethod(t2, def).backtrack(t2, t))
}
/**
* Gets a function that is registered as a jQuery plugin method at `def`.
*/
private DataFlow::FunctionNode getAJQueryPluginMethod(DataFlow::Node def) {
result = getAJQueryPluginMethod(DataFlow::TypeBackTracker::end(), def)
}
/**
* Gets an operand to `extend`.
*/
@@ -95,6 +102,13 @@ module UnsafeJQueryPlugin {
exists(DataFlow::TypeBackTracker t2 | result = getAnExtendOperand(t2, extend).backtrack(t2, t))
}
/**
* Gets an operand to `extend`.
*/
private DataFlow::SourceNode getAnExtendOperand(ExtendCall extend) {
result = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend)
}
/**
* A function that is registered as a jQuery plugin method.
*/
@@ -104,7 +118,7 @@ module UnsafeJQueryPlugin {
JQueryPluginMethod() {
exists(DataFlow::Node def |
jQueryPluginDefinition(pluginName, def) and
this = getAJQueryPluginMethod(DataFlow::TypeBackTracker::end(), def)
this = getAJQueryPluginMethod(def)
)
}
@@ -120,8 +134,8 @@ module UnsafeJQueryPlugin {
private predicate hasDefaultOption(JQueryPluginMethod plugin, DataFlow::PropWrite def) {
exists(ExtendCall extend, JQueryPluginOptions options, DataFlow::SourceNode default |
options.getPlugin() = plugin and
options = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and
default = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and
options = getAnExtendOperand(extend) and
default = getAnExtendOperand(extend) and
default.getAPropertyWrite() = def
)
}
@@ -173,11 +187,11 @@ module UnsafeJQueryPlugin {
/**
* Expression like `typeof x.<?> !== "undefined"` or `x.<?>`, which sanitizes `x`, as it is unlikely to be a string afterwards.
*/
class PropertyPrecenseSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
class PropertyPresenceSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
DataFlow::Node input;
boolean polarity;
PropertyPrecenseSanitizer() {
PropertyPresenceSanitizer() {
exists(DataFlow::PropRead read, string name |
not name = "length" and read.accesses(input, name)
|

View File

@@ -115,6 +115,11 @@ nodes
| unsafe-jquery-plugin.js:165:16:165:29 | options.target |
| unsafe-jquery-plugin.js:170:6:170:11 | target |
| unsafe-jquery-plugin.js:170:6:170:11 | target |
| unsafe-jquery-plugin.js:178:27:178:33 | options |
| unsafe-jquery-plugin.js:178:27:178:33 | options |
| unsafe-jquery-plugin.js:179:5:179:11 | options |
| unsafe-jquery-plugin.js:179:5:179:18 | options.target |
| unsafe-jquery-plugin.js:179:5:179:18 | options.target |
edges
| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options |
| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options |
@@ -228,6 +233,10 @@ edges
| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target |
| unsafe-jquery-plugin.js:165:16:165:22 | options | unsafe-jquery-plugin.js:165:16:165:29 | options.target |
| unsafe-jquery-plugin.js:165:16:165:29 | options.target | unsafe-jquery-plugin.js:165:7:165:29 | target |
| unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:11 | options |
| unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:11 | options |
| unsafe-jquery-plugin.js:179:5:179:11 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target |
| unsafe-jquery-plugin.js:179:5:179:11 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target |
#select
| unsafe-jquery-plugin.js:3:5:3:11 | options | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin |
| unsafe-jquery-plugin.js:5:5:5:18 | options.target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin |
@@ -251,3 +260,4 @@ edges
| unsafe-jquery-plugin.js:156:41:156:54 | options.target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin |
| unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin |
| unsafe-jquery-plugin.js:170:6:170:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:170:6:170:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin |
| unsafe-jquery-plugin.js:179:5:179:18 | options.target | unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:178:18:180:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin |

View File

@@ -171,4 +171,15 @@
}
}
function setupPlugin(o) {
$.fn.my_plugin = o.f
}
setupPlugin({f: function(options) {
$(options.target); // NOT OK
}});
setupPlugin({f:function(options) {
$(document).find(options.target); // OK
}});
});