mirror of
https://github.com/github/codeql.git
synced 2025-12-18 01:33:15 +01:00
use the TaintedObject library in js/template-object-injection
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user