Skip to content

Commit fe1e47b

Browse files
authored
Merge pull request #8710 from bananabr/dragAndDrop
JS: drag and drop API Xss sources
2 parents 611a412 + b5193d9 commit fe1e47b

File tree

8 files changed

+497
-65
lines changed

8 files changed

+497
-65
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The security queries now recognize drag and drop data as a source, enabling the queries to flag additional alerts.
5+
* The security queries now recognize ClipboardEvent function parameters as a source, enabling the queries to flag additional alerts.

javascript/ql/lib/javascript.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import semmle.javascript.frameworks.ComposedFunctions
7979
import semmle.javascript.frameworks.Classnames
8080
import semmle.javascript.frameworks.ClassValidator
8181
import semmle.javascript.frameworks.ClientRequests
82-
import semmle.javascript.frameworks.Clipboard
8382
import semmle.javascript.frameworks.ClosureLibrary
8483
import semmle.javascript.frameworks.CookieLibraries
8584
import semmle.javascript.frameworks.Credentials
@@ -88,6 +87,7 @@ import semmle.javascript.frameworks.D3
8887
import semmle.javascript.frameworks.data.ModelsAsData
8988
import semmle.javascript.frameworks.DateFunctions
9089
import semmle.javascript.frameworks.DigitalOcean
90+
import semmle.javascript.frameworks.DomEvents
9191
import semmle.javascript.frameworks.Electron
9292
import semmle.javascript.frameworks.EventEmitter
9393
import semmle.javascript.frameworks.Files

javascript/ql/lib/semmle/javascript/frameworks/Clipboard.qll

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Provides predicates for reasoning about events from the DOM that introduce tainted data.
3+
*/
4+
5+
import javascript
6+
7+
/** Gets the name of a DOM event that might introduce tainted data. */
8+
private string getATaintedDomEvent() { result = ["paste", "drop", "beforeinput"] }
9+
10+
/**
11+
* Gets a jQuery event that might introduce tainted data.
12+
* E.g. `e` in `$("#foo").on("paste", function(e) { ... })`.
13+
*/
14+
private DataFlow::SourceNode taintedJQueryEvent(DataFlow::TypeTracker t, string event) {
15+
t.start() and
16+
exists(DataFlow::CallNode call |
17+
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
18+
call.getArgument(0).mayHaveStringValue(event) and
19+
event = getATaintedDomEvent()
20+
|
21+
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
22+
)
23+
or
24+
exists(DataFlow::TypeTracker t2 | result = taintedJQueryEvent(t2, event).track(t2, t))
25+
}
26+
27+
/**
28+
* Gets a DOM event that might introduce tainted data.
29+
* E.g. `e` in `document.addEventListener("paste", e => { ... })`.
30+
*/
31+
private DataFlow::SourceNode taintedEvent(DataFlow::TypeTracker t, string event) {
32+
t.start() and
33+
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
34+
call.getArgument(0).mayHaveStringValue(event) and
35+
event = getATaintedDomEvent() and
36+
result = call.getCallback(1).getParameter(0)
37+
)
38+
or
39+
t.start() and
40+
exists(DataFlow::ParameterNode pn | result = pn |
41+
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent
42+
pn.hasUnderlyingType("ClipboardEvent") and
43+
event = "paste"
44+
or
45+
// https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
46+
pn.hasUnderlyingType("DragEvent") and
47+
event = "drop"
48+
or
49+
// https://developer.mozilla.org/en-US/docs/Web/API/InputEvent
50+
pn.hasUnderlyingType("InputEvent") and
51+
event = "beforeinput"
52+
)
53+
or
54+
t.start() and
55+
exists(DataFlow::PropWrite pw | pw = DOM::domValueRef().getAPropertyWrite("on" + event) |
56+
event = ["paste", "drop"] and // doesn't work for beforeinput, it's just not part of the API
57+
result = pw.getRhs().getABoundFunctionValue(0).getParameter(0)
58+
)
59+
or
60+
t.start() and
61+
result = taintedJQueryEvent(DataFlow::TypeTracker::end(), event).getAPropertyRead("originalEvent")
62+
or
63+
exists(DataFlow::TypeTracker t2 | result = taintedEvent(t2, event).track(t2, t))
64+
}
65+
66+
/**
67+
* Gets a reference to a DataTransfer object.
68+
* https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
69+
*/
70+
private DataFlow::SourceNode taintedDataTransfer(DataFlow::TypeTracker t, string event) {
71+
t.start() and
72+
result = taintedEvent(DataFlow::TypeTracker::end(), event).getAPropertyRead("clipboardData") and
73+
event = "paste"
74+
or
75+
t.start() and
76+
result = taintedEvent(DataFlow::TypeTracker::end(), event).getAPropertyRead("dataTransfer") and
77+
event = ["drop", "beforeinput"]
78+
or
79+
exists(DataFlow::TypeTracker t2 | result = taintedDataTransfer(t2, event).track(t2, t))
80+
}
81+
82+
/**
83+
* A reference to data from a DataTransfer object, which might originate from e.g. the clipboard.
84+
* Seen as a source for DOM-based XSS.
85+
*/
86+
private class TaintedDataTransfer extends RemoteFlowSource {
87+
string event;
88+
89+
TaintedDataTransfer() {
90+
this = taintedDataTransfer(DataFlow::TypeTracker::end(), event).getAMethodCall("getData")
91+
}
92+
93+
override string getSourceType() {
94+
event = "paste" and
95+
result = "Clipboard data"
96+
or
97+
event = "drop" and
98+
result = "Drag&Drop data"
99+
or
100+
event = "beforeinput" and
101+
result = "Input data"
102+
}
103+
}

0 commit comments

Comments
 (0)