use the TaintedObject library in js/template-object-injection

This commit is contained in:
Erik Krogh Kristensen
2021-02-03 12:26:37 +01:00
parent c6a22844e2
commit a5bde53bfe
3 changed files with 65 additions and 21 deletions

View File

@@ -11,8 +11,8 @@
*/
import javascript
import DataFlow
import PathGraph
import DataFlow::PathGraph
import semmle.javascript.security.TaintedObject
predicate isUsingHbsEngine() {
Express::appCreation().getAMethodCall("set").getArgument(1).mayHaveStringValue("hbs")
@@ -21,19 +21,34 @@ predicate isUsingHbsEngine() {
class HbsLFRTaint extends TaintTracking::Configuration {
HbsLFRTaint() { this = "HbsLFRTaint" }
override predicate isSource(Node node) { node instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(Node node) {
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
TaintedObject::isSource(source, label)
}
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
label = TaintedObject::label() and
exists(MethodCallExpr mc |
Express::isResponse(mc.getReceiver()) and
mc.getMethodName() = "render" and
node.asExpr() = mc.getArgument(1) and
sink.asExpr() = mc.getArgument(1) and
isUsingHbsEngine()
)
}
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
guard instanceof TaintedObject::SanitizerGuard
}
override predicate isAdditionalFlowStep(
DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
) {
TaintedObject::step(src, trg, inlbl, outlbl)
}
}
from HbsLFRTaint cfg, PathNode source, PathNode sink
from HbsLFRTaint cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Template object injection due to $@.", source.getNode(),
"user-provided value"

View File

@@ -4,34 +4,52 @@ nodes
| tst.js:5:25:5:32 | req.body |
| tst.js:5:25:5:46 | req.bod ... rameter |
| tst.js:6:9:6:49 | queryParameter |
| tst.js:6:9:6:49 | queryParameter |
| tst.js:6:26:6:49 | req.que ... rameter |
| tst.js:6:26:6:49 | req.que ... rameter |
| tst.js:6:26:6:49 | req.que ... rameter |
| tst.js:8:28:8:40 | bodyParameter |
| tst.js:8:28:8:40 | bodyParameter |
| tst.js:9:28:9:41 | queryParameter |
| tst.js:9:28:9:41 | queryParameter |
| tst.js:12:32:12:44 | bodyParameter |
| tst.js:12:32:12:44 | bodyParameter |
| tst.js:14:28:14:41 | queryParameter |
| tst.js:14:28:14:46 | queryParameter + "" |
| tst.js:14:28:14:46 | queryParameter + "" |
| tst.js:18:19:18:32 | queryParameter |
| tst.js:18:19:18:32 | queryParameter |
| tst.js:21:24:21:26 | obj |
| tst.js:21:24:21:26 | obj |
| tst.js:22:28:22:30 | obj |
| tst.js:22:28:22:30 | obj |
| tst.js:24:11:24:24 | str |
| tst.js:24:17:24:19 | obj |
| tst.js:24:17:24:24 | obj + "" |
| tst.js:27:28:27:42 | JSON.parse(str) |
| tst.js:27:28:27:42 | JSON.parse(str) |
| tst.js:27:39:27:41 | str |
edges
| tst.js:5:9:5:46 | bodyParameter | tst.js:8:28:8:40 | bodyParameter |
| tst.js:5:9:5:46 | bodyParameter | tst.js:8:28:8:40 | bodyParameter |
| tst.js:5:9:5:46 | bodyParameter | tst.js:12:32:12:44 | bodyParameter |
| tst.js:5:9:5:46 | bodyParameter | tst.js:12:32:12:44 | bodyParameter |
| tst.js:5:25:5:32 | req.body | tst.js:5:25:5:46 | req.bod ... rameter |
| tst.js:5:25:5:32 | req.body | tst.js:5:25:5:46 | req.bod ... rameter |
| tst.js:5:25:5:46 | req.bod ... rameter | tst.js:5:9:5:46 | bodyParameter |
| tst.js:6:9:6:49 | queryParameter | tst.js:9:28:9:41 | queryParameter |
| tst.js:6:9:6:49 | queryParameter | tst.js:9:28:9:41 | queryParameter |
| tst.js:6:9:6:49 | queryParameter | tst.js:14:28:14:41 | queryParameter |
| tst.js:6:9:6:49 | queryParameter | tst.js:18:19:18:32 | queryParameter |
| tst.js:6:9:6:49 | queryParameter | tst.js:18:19:18:32 | queryParameter |
| tst.js:6:26:6:49 | req.que ... rameter | tst.js:6:9:6:49 | queryParameter |
| tst.js:6:26:6:49 | req.que ... rameter | tst.js:6:9:6:49 | queryParameter |
| tst.js:14:28:14:41 | queryParameter | tst.js:14:28:14:46 | queryParameter + "" |
| tst.js:14:28:14:41 | queryParameter | tst.js:14:28:14:46 | queryParameter + "" |
| tst.js:6:26:6:49 | req.que ... rameter | tst.js:6:9:6:49 | queryParameter |
| tst.js:6:26:6:49 | req.que ... rameter | tst.js:6:9:6:49 | queryParameter |
| tst.js:18:19:18:32 | queryParameter | tst.js:21:24:21:26 | obj |
| tst.js:18:19:18:32 | queryParameter | tst.js:21:24:21:26 | obj |
| tst.js:21:24:21:26 | obj | tst.js:22:28:22:30 | obj |
| tst.js:21:24:21:26 | obj | tst.js:22:28:22:30 | obj |
| tst.js:21:24:21:26 | obj | tst.js:24:17:24:19 | obj |
| tst.js:24:11:24:24 | str | tst.js:27:39:27:41 | str |
| tst.js:24:17:24:19 | obj | tst.js:24:17:24:24 | obj + "" |
| tst.js:24:17:24:24 | obj + "" | tst.js:24:11:24:24 | str |
| tst.js:27:39:27:41 | str | tst.js:27:28:27:42 | JSON.parse(str) |
| tst.js:27:39:27:41 | str | tst.js:27:28:27:42 | JSON.parse(str) |
#select
| tst.js:8:28:8:40 | bodyParameter | tst.js:5:25:5:32 | req.body | tst.js:8:28:8:40 | bodyParameter | Template object injection due to $@. | tst.js:5:25:5:32 | req.body | user-provided value |
| tst.js:9:28:9:41 | queryParameter | tst.js:6:26:6:49 | req.que ... rameter | tst.js:9:28:9:41 | queryParameter | Template object injection due to $@. | tst.js:6:26:6:49 | req.que ... rameter | user-provided value |
| tst.js:12:32:12:44 | bodyParameter | tst.js:5:25:5:32 | req.body | tst.js:12:32:12:44 | bodyParameter | Template object injection due to $@. | tst.js:5:25:5:32 | req.body | user-provided value |
| tst.js:14:28:14:46 | queryParameter + "" | tst.js:6:26:6:49 | req.que ... rameter | tst.js:14:28:14:46 | queryParameter + "" | Template object injection due to $@. | tst.js:6:26:6:49 | req.que ... rameter | user-provided value |
| tst.js:22:28:22:30 | obj | tst.js:6:26:6:49 | req.que ... rameter | tst.js:22:28:22:30 | obj | Template object injection due to $@. | tst.js:6:26:6:49 | req.que ... rameter | user-provided value |
| tst.js:27:28:27:42 | JSON.parse(str) | tst.js:6:26:6:49 | req.que ... rameter | tst.js:27:28:27:42 | JSON.parse(str) | Template object injection due to $@. | tst.js:6:26:6:49 | req.que ... rameter | user-provided value |

View File

@@ -9,9 +9,20 @@ app.post('/path', function(req, res) {
res.render('template', queryParameter); // NOT OK
if (typeof bodyParameter === "string") {
res.render('template', bodyParameter); // OK - but still flagged [INCONSISTENCY]
res.render('template', bodyParameter); // OK
}
res.render('template', queryParameter + ""); // OK - but still flagged [INCONSISTENCY]
res.render('template', queryParameter + ""); // OK
res.render('template', {profile: bodyParameter}); // OK
});
indirect(res, queryParameter);
});
function indirect(res, obj) {
res.render("template", obj); // NOT OK
const str = obj + "";
res.render("template", str); // OK
res.render("template", JSON.parse(str)); // NOT OK
}