-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathGoMicro.qll
More file actions
165 lines (145 loc) · 4.46 KB
/
GoMicro.qll
File metadata and controls
165 lines (145 loc) · 4.46 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/**
* Provides models of the [Go Micro library](https://github.com/go-micro/go-micro).
*/
overlay[local?]
module;
import go
private import semmle.go.security.RequestForgeryCustomizations
/**
* Module for Go Micro framework.
*/
module GoMicro {
/**
* A GoMicro server type.
*/
class GoMicroServerType extends Type {
GoMicroServerType() { this.hasQualifiedName("go-micro.dev/v4/server", "Server") }
}
/**
* A GoMicro client type.
*/
class GoMicroClientType extends Type {
GoMicroClientType() { this.hasQualifiedName("go-micro.dev/v4/client", "Client") }
}
/**
* A file that is generated by the protobuf compiler.
*/
class ProtocGeneratedFile extends File {
ProtocGeneratedFile() { this.getBaseName().regexpMatch(".*\\.pb(\\.micro)?\\.go$") }
}
/**
* A type that is generated by the protobuf compiler.
*/
class ProtocMessageType extends Type {
ProtocMessageType() {
this.getLocation().getFile() instanceof ProtocGeneratedFile and
exists(MethodDecl md |
md.getName() = "ProtoMessage" and
this = md.getReceiverDecl().getTypeExpr().getAChild().(TypeName).getType()
)
}
}
/**
* A Server Interface type.
*/
class ServiceInterfaceType extends InterfaceType {
DefinedType definedType;
ServiceInterfaceType() {
this = definedType.getUnderlyingType() and
definedType.getLocation().getFile() instanceof ProtocGeneratedFile
}
/**
* Gets the name of the interface.
*/
override string getName() { result = definedType.getName() }
/** DEPRECATED: Use `getDefinedType` instead. */
deprecated DefinedType getNamedType() { result = definedType }
/**
* Gets the defined type on top of this interface type.
*/
DefinedType getDefinedType() { result = definedType }
}
/**
* A Service server handler type.
*/
class ServiceServerType extends DefinedType {
ServiceServerType() {
this.implements(any(ServiceInterfaceType i)) and
this.getName().regexpMatch("(?i).*Handler") and
this.getLocation().getFile() instanceof ProtocGeneratedFile
}
}
/**
* A Client server handler type.
*/
class ClientServiceType extends DefinedType {
ClientServiceType() {
this.implements(any(ServiceInterfaceType i)) and
this.getName().regexpMatch("(?i).*Service") and
this.getLocation().getFile() instanceof ProtocGeneratedFile
}
}
/**
* A service register handler.
*/
class ServiceRegisterHandler extends Function {
ServiceRegisterHandler() {
this.getName().regexpMatch("(?i)register" + any(ServiceServerType c).getName()) and
this.getParameterType(0) instanceof GoMicroServerType and
this.getLocation().getFile() instanceof ProtocGeneratedFile
}
}
bindingset[m]
pragma[inline_late]
private predicate implementsServiceType(Method m) {
m.implements(any(ServiceInterfaceType i).getDefinedType().getMethod(_))
}
/**
* A service handler.
*/
class ServiceHandler extends Method {
ServiceHandler() {
exists(DataFlow::CallNode call |
call.getTarget() instanceof ServiceRegisterHandler and
this = call.getArgument(1).getType().getMethod(_) and
implementsServiceType(this)
)
}
}
/**
* A client service function.
*/
class ClientService extends Function {
ClientService() {
this.getName().regexpMatch("(?i)new" + any(ClientServiceType c).getName()) and
this.getParameterType(0) instanceof StringType and
this.getParameterType(1) instanceof GoMicroClientType and
this.getLocation().getFile() instanceof ProtocGeneratedFile
}
}
/**
* An SSRF sink for the Client service function.
*/
class ClientRequestUrlAsSink extends RequestForgery::Sink {
ClientRequestUrlAsSink() {
exists(DataFlow::CallNode call |
call.getArgument(0) = this and
call.getTarget() instanceof ClientService
)
}
override DataFlow::Node getARequest() { result = this }
override string getKind() { result = "URL" }
}
/**
* A set of remote requests from a service handler.
*/
class Request extends RemoteFlowSource::Range instanceof DataFlow::ParameterNode {
Request() {
exists(ServiceHandler handler |
this.asParameter().isParameterOf(handler.getFuncDecl(), 1) and
handler.getParameterType(0).hasQualifiedName("context", "Context") and
this.getType().(PointerType).getBaseType() instanceof ProtocMessageType
)
}
}
}