Skip to content

Commit c9832c3

Browse files
committed
Python: Convert BindToAllInterfaces to path-problem
Now that we're using global data-flow, we might as well make use of the fact that we know where the source is.
1 parent c0ce669 commit c9832c3

File tree

3 files changed

+75
-19
lines changed

3 files changed

+75
-19
lines changed

python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @name Binding a socket to all network interfaces
33
* @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address
44
* and is therefore associated with security risks.
5-
* @kind problem
5+
* @kind path-problem
66
* @tags security
77
* external/cwe/cwe-200
88
* @problem.severity error
@@ -16,6 +16,7 @@ import python
1616
import semmle.python.dataflow.new.DataFlow
1717
import semmle.python.dataflow.new.TaintTracking
1818
private import semmle.python.frameworks.data.ModelsAsData
19+
import BindToAllInterfacesFlow::PathGraph
1920

2021
/** Gets a hostname that can be used to bind to all interfaces. */
2122
private string vulnerableHostname() {
@@ -39,9 +40,10 @@ private module BindToAllInterfacesConfig implements DataFlow::ConfigSig {
3940

4041
private module BindToAllInterfacesFlow = TaintTracking::Global<BindToAllInterfacesConfig>;
4142

42-
from DataFlow::Node source, DataFlow::Node sink, DataFlow::CallCfgNode bindCall, string hostname
43-
where
44-
BindToAllInterfacesFlow::flow(source, sink) and
45-
bindCall.getArg(0) = sink and
46-
hostname = source.asExpr().(StringLiteral).getText()
47-
select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces."
43+
private import BindToAllInterfacesFlow
44+
45+
from PathNode source, PathNode sink
46+
where flowPath(source, sink)
47+
select sink.getNode(), source, sink,
48+
"Binding a socket to all interfaces (using $@) is a security risk.", source.getNode(),
49+
"'" + source.getNode().asExpr().(StringLiteral).getText() + "'"
Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,63 @@
1-
| BindToAllInterfaces_test.py:5:1:5:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
2-
| BindToAllInterfaces_test.py:9:1:9:18 | Attribute() | '' binds a socket to all interfaces. |
3-
| BindToAllInterfaces_test.py:17:1:17:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
4-
| BindToAllInterfaces_test.py:21:1:21:11 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
5-
| BindToAllInterfaces_test.py:26:1:26:20 | Attribute() | '::' binds a socket to all interfaces. |
6-
| BindToAllInterfaces_test.py:39:9:39:43 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
7-
| BindToAllInterfaces_test.py:48:1:48:20 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
8-
| BindToAllInterfaces_test.py:53:1:53:27 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
9-
| BindToAllInterfaces_test.py:58:1:58:27 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
1+
#select
2+
| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | '0.0.0.0' |
3+
| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | '' |
4+
| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' |
5+
| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' |
6+
| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | '::' |
7+
| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | '0.0.0.0' |
8+
| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | '0.0.0.0' |
9+
| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | '0.0.0.0' |
10+
| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | '0.0.0.0' |
11+
edges
12+
| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
13+
| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
14+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
15+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | provenance | |
16+
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | provenance | |
17+
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 |
18+
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
19+
| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | provenance | |
20+
| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | provenance | |
21+
| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | provenance | |
22+
| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | provenance | |
23+
| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | provenance | |
24+
| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
25+
| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
26+
| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
27+
| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | provenance | |
28+
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
29+
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | provenance | |
30+
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | provenance | dict.get |
31+
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
32+
| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
33+
nodes
34+
| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
35+
| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
36+
| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
37+
| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
38+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS |
39+
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
40+
| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
41+
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
42+
| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
43+
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
44+
| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
45+
| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Return] [Attribute bind_addr] |
46+
| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | semmle.label | [post] ControlFlowNode for self [Attribute bind_addr] |
47+
| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
48+
| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] |
49+
| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] |
50+
| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
51+
| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
52+
| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] |
53+
| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | semmle.label | ControlFlowNode for Server() [Attribute bind_addr] |
54+
| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] |
55+
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | semmle.label | ControlFlowNode for host |
56+
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
57+
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
58+
| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
59+
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
60+
| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
61+
| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
62+
| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
63+
subpaths

python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
s.bind(('84.68.10.12', 8080))
1414

1515
# binds to all interfaces, insecure
16-
ALL_LOCALS = "0.0.0.0"
16+
ALL_LOCALS = "0.0.0.0" # $ Source
1717
s.bind((ALL_LOCALS, 9090)) # $ Alert[py/bind-socket-all-network-interfaces]
1818

1919
# binds to all interfaces, insecure
@@ -31,7 +31,7 @@
3131
# Address stored in a class attribute
3232
class Server:
3333
def __init__(self):
34-
self.bind_addr = '0.0.0.0'
34+
self.bind_addr = '0.0.0.0' # $ Source
3535
self.port = 31137
3636

3737
def start(self):
@@ -43,7 +43,7 @@ def start(self):
4343

4444
# os.environ.get with insecure default
4545
import os
46-
host = os.environ.get('APP_HOST', '0.0.0.0')
46+
host = os.environ.get('APP_HOST', '0.0.0.0') # $ Source
4747
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4848
s.bind((host, 8080)) # $ Alert[py/bind-socket-all-network-interfaces]
4949

0 commit comments

Comments
 (0)