-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathBindToAllInterfaces.ql
More file actions
70 lines (62 loc) · 2.6 KB
/
BindToAllInterfaces.ql
File metadata and controls
70 lines (62 loc) · 2.6 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
/**
* @name Binding a socket to all network interfaces
* @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address
* and is therefore associated with security risks.
* @kind problem
* @tags security
* external/cwe/cwe-200
* @problem.severity error
* @security-severity 6.5
* @sub-severity low
* @precision high
* @id py/bind-socket-all-network-interfaces
*/
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
/** Gets a hostname that can be used to bind to all interfaces. */
private string vulnerableHostname() {
result in [
// IPv4
"0.0.0.0", "",
// IPv6
"::", "::0"
]
}
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
private DataFlow::TypeTrackingNode vulnerableHostnameRef(DataFlow::TypeTracker t, string hostname) {
t.start() and
exists(StringLiteral allInterfacesStringLiteral | hostname = vulnerableHostname() |
allInterfacesStringLiteral.getText() = hostname and
result.asExpr() = allInterfacesStringLiteral
)
or
exists(DataFlow::TypeTracker t2 | result = vulnerableHostnameRef(t2, hostname).track(t2, t))
}
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
DataFlow::Node vulnerableHostnameRef(string hostname) {
vulnerableHostnameRef(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
}
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
private DataFlow::TypeTrackingNode vulnerableAddressTuple(DataFlow::TypeTracker t, string hostname) {
t.start() and
result.asExpr() = any(Tuple tup | tup.getElt(0) = vulnerableHostnameRef(hostname).asExpr())
or
exists(DataFlow::TypeTracker t2 | result = vulnerableAddressTuple(t2, hostname).track(t2, t))
}
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
DataFlow::Node vulnerableAddressTuple(string hostname) {
vulnerableAddressTuple(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
}
/**
* Gets an instance of `socket.socket` using _some_ address family.
*
* See https://docs.python.org/3/library/socket.html
*/
API::Node socketInstance() { result = API::moduleImport("socket").getMember("socket").getReturn() }
from DataFlow::CallCfgNode bindCall, DataFlow::Node addressArg, string hostname
where
bindCall = socketInstance().getMember("bind").getACall() and
addressArg = bindCall.getArg(0) and
addressArg = vulnerableAddressTuple(hostname)
select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces."