Skip to content

Commit 0f1582f

Browse files
author
bananabr
committed
included JavaScript drag and drop API Xss sources
1 parent 626770a commit 0f1582f

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

javascript/ql/lib/javascript.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import semmle.javascript.frameworks.D3
8888
import semmle.javascript.frameworks.data.ModelsAsData
8989
import semmle.javascript.frameworks.DateFunctions
9090
import semmle.javascript.frameworks.DigitalOcean
91+
import semmle.javascript.frameworks.DragAndDrop
9192
import semmle.javascript.frameworks.Electron
9293
import semmle.javascript.frameworks.EventEmitter
9394
import semmle.javascript.frameworks.Files
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Provides predicates for reasoning about dragAndDrop data.
3+
*/
4+
5+
import javascript
6+
7+
/**
8+
* Gets a jQuery "drop" event.
9+
* E.g. `e` in `$("#foo").on("drop", function(e) { ... })`.
10+
*/
11+
private DataFlow::SourceNode jQueryDropEvent(DataFlow::TypeTracker t) {
12+
t.start() and
13+
exists(DataFlow::CallNode call |
14+
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
15+
call.getArgument(0).mayHaveStringValue("drop")
16+
|
17+
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
18+
)
19+
or
20+
exists(DataFlow::TypeTracker t2 | result = jQueryDropEvent(t2).track(t2, t))
21+
}
22+
23+
/**
24+
* Gets a DOM "drop" event.
25+
* E.g. `e` in `document.addEventListener("drop", e => { ... })`.
26+
*/
27+
private DataFlow::SourceNode dropEvent(DataFlow::TypeTracker t) {
28+
t.start() and
29+
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
30+
call.getArgument(0).mayHaveStringValue("drop") and
31+
result = call.getCallback(1).getParameter(0)
32+
)
33+
or
34+
t.start() and
35+
result = jQueryDropEvent(DataFlow::TypeTracker::end()).getAPropertyRead("originalEvent")
36+
or
37+
exists(DataFlow::TypeTracker t2 | result = dropEvent(t2).track(t2, t))
38+
}
39+
40+
/**
41+
* Gets a reference to the dragAndDropData DataTransfer object.
42+
* https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API
43+
*/
44+
private DataFlow::SourceNode dragAndDropDataTransferSource(DataFlow::TypeTracker t) {
45+
t.start() and
46+
exists(DataFlow::PropRead read | read = result |
47+
read.getPropertyName() = "dataTransfer" and
48+
read.getBase().getALocalSource() = dropEvent(DataFlow::TypeTracker::end())
49+
)
50+
or
51+
exists(DataFlow::TypeTracker t2 | result = dragAndDropDataTransferSource(t2).track(t2, t))
52+
}
53+
54+
/**
55+
* A reference to data from the dragAndDrop. Seen as a source for DOM-based XSS.
56+
*/
57+
private class DragAndDropSource extends RemoteFlowSource {
58+
DragAndDropSource() {
59+
this = dragAndDropDataTransferSource(DataFlow::TypeTracker::end()).getAMethodCall("getData")
60+
}
61+
62+
override string getSourceType() { result = "DragAndDrop data" }
63+
}

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,26 @@ nodes
295295
| dates.js:61:42:61:86 | dayjs.s ... (taint) |
296296
| dates.js:61:81:61:85 | taint |
297297
| dates.js:61:81:61:85 | taint |
298+
| dragAndDrop.ts:8:11:8:50 | html |
299+
| dragAndDrop.ts:8:11:8:50 | html |
300+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
301+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
302+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
303+
| dragAndDrop.ts:15:25:15:28 | html |
304+
| dragAndDrop.ts:15:25:15:28 | html |
305+
| dragAndDrop.ts:15:25:15:28 | html |
306+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
307+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
308+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
309+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
310+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
311+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
312+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
313+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
314+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
315+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
316+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
317+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
298318
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
299319
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
300320
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
@@ -1318,6 +1338,17 @@ edges
13181338
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
13191339
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
13201340
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
1341+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1342+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1343+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1344+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1345+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1346+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1347+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1348+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1349+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
1350+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
1351+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
13211352
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
13221353
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
13231354
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
@@ -2082,6 +2113,10 @@ edges
20822113
| dates.js:57:31:57:101 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:57:31:57:101 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
20832114
| dates.js:59:31:59:87 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:59:31:59:87 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
20842115
| dates.js:61:31:61:88 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:61:31:61:88 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
2116+
| dragAndDrop.ts:15:25:15:28 | html | dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:15:25:15:28 | html | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | user-provided value |
2117+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | user-provided value |
2118+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | user-provided value |
2119+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | Cross-site scripting vulnerability due to $@. | dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | user-provided value |
20852120
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | Cross-site scripting vulnerability due to $@. | event-handler-receiver.js:2:49:2:61 | location.href | user-provided value |
20862121
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | Cross-site scripting vulnerability due to $@. | express.js:7:15:7:33 | req.param("wobble") | user-provided value |
20872122
| jquery.js:7:5:7:34 | "<div i ... + "\\">" | jquery.js:2:17:2:40 | documen ... .search | jquery.js:7:5:7:34 | "<div i ... + "\\">" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,26 @@ nodes
295295
| dates.js:61:42:61:86 | dayjs.s ... (taint) |
296296
| dates.js:61:81:61:85 | taint |
297297
| dates.js:61:81:61:85 | taint |
298+
| dragAndDrop.ts:8:11:8:50 | html |
299+
| dragAndDrop.ts:8:11:8:50 | html |
300+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
301+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
302+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') |
303+
| dragAndDrop.ts:15:25:15:28 | html |
304+
| dragAndDrop.ts:15:25:15:28 | html |
305+
| dragAndDrop.ts:15:25:15:28 | html |
306+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
307+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
308+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
309+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
310+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
311+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
312+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
313+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
314+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
315+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
316+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
317+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
298318
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
299319
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
300320
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
@@ -1368,6 +1388,17 @@ edges
13681388
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
13691389
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
13701390
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
1391+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1392+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1393+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1394+
| dragAndDrop.ts:8:11:8:50 | html | dragAndDrop.ts:15:25:15:28 | html |
1395+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1396+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1397+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1398+
| dragAndDrop.ts:8:18:8:50 | dataTra ... /html') | dragAndDrop.ts:8:11:8:50 | html |
1399+
| dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') | dragAndDrop.ts:24:23:24:57 | e.dataT ... /html') |
1400+
| dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') | dragAndDrop.ts:29:19:29:53 | e.dataT ... /html') |
1401+
| dragAndDrop.ts:33:19:33:67 | e.origi ... /html') | dragAndDrop.ts:33:19:33:67 | e.origi ... /html') |
13711402
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
13721403
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
13731404
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
$("#foo").on("drop", drop);
2+
3+
function drop(e) {
4+
const { dataTransfer } = e.originalEvent;
5+
if (!dataTransfer) return;
6+
7+
const text = dataTransfer.getData('text/plain');
8+
const html = dataTransfer.getData('text/html');
9+
if (!text && !html) return;
10+
11+
e.preventDefault();
12+
13+
const div = document.createElement('div');
14+
if (html) {
15+
div.innerHTML = html; // NOT OK
16+
} else {
17+
div.textContent = text;
18+
}
19+
document.body.append(div);
20+
}
21+
22+
export function install(el: HTMLElement): void {
23+
el.addEventListener('drop', (e) => {
24+
$("#id").html(e.dataTransfer.getData('text/html')); // NOT OK
25+
})
26+
}
27+
28+
document.addEventListener('drop', (e) => {
29+
$("#id").html(e.dataTransfer.getData('text/html')); // NOT OK
30+
});
31+
32+
$("#foo").bind('drop', (e) => {
33+
$("#id").html(e.originalEvent.dataTransfer.getData('text/html')); // NOT OK
34+
});

0 commit comments

Comments
 (0)