-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathWebsockets.qll
More file actions
84 lines (70 loc) · 3.31 KB
/
Websockets.qll
File metadata and controls
84 lines (70 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* Provides definitions and modeling for the `websockets` PyPI package.
*
* See https://websockets.readthedocs.io/en/stable/
*/
private import python
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.frameworks.internal.PoorMansFunctionResolution
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
/**
* Provides models for the `websockets` PyPI package.
* See https://websockets.readthedocs.io/en/stable/
*/
module Websockets {
private class HandlerArg extends DataFlow::Node {
HandlerArg() {
exists(DataFlow::CallCfgNode c |
c =
API::moduleImport("websockets")
.getMember(["asyncio", "sync"])
.getMember("server")
.getMember(["serve", "unix_serve"])
.getACall()
|
(this = c.getArg(0) or this = c.getArgByName("handler"))
)
}
}
/** A websocket handler that is passed to `serve`. */
// TODO: handlers defined via route maps, e.g. through `websockets.asyncio.router.route`, are more complex to handle.
class WebSocketHandler extends Http::Server::RequestHandler::Range {
WebSocketHandler() { poorMansFunctionTracker(this) = any(HandlerArg a) }
override Parameter getARoutedParameter() { result = this.getAnArg() }
override string getFramework() { result = "websockets" }
}
/** Provides taint models for instances of `ServerConnection` objects passed to websocket handlers. */
module ServerConnection {
/**
* A source of instances of `websockets.asyncio.ServerConnection` and `websockets.sync.ServerConnection`, extend this class to model new instances.
*
* This can include instantiations of the class, return values from function
* calls, or a special parameter that will be set when functions are called by an external
* library.
*
* Use the predicate `ServerConnection::instance()` to get references to instances of `websockets.asyncio.ServerConnection` and `websockets.sync.ServerConnection`.
*/
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
/** Gets a reference to an instance of `websockets.asyncio.ServerConnection` or `websockets.sync.ServerConnection`. */
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
t.start() and
result instanceof InstanceSource
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `websockets.asyncio.ServerConnection` or `websockets.sync.ServerConnection`. */
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
private class HandlerParam extends DataFlow::Node, InstanceSource {
HandlerParam() { exists(WebSocketHandler h | this = DataFlow::parameterNode(h.getArg(0))) }
}
private class InstanceTaintSteps extends InstanceTaintStepsHelper {
InstanceTaintSteps() { this = "websockets.asyncio.ServerConnection" }
override DataFlow::Node getInstance() { result = instance() }
override string getAttributeName() { none() }
override string getAsyncMethodName() { result = ["recv", "recv_streaming"] }
override string getMethodName() { result = ["recv", "recv_streaming"] }
}
}
}