Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 186db7f

Browse files
committed
Python: factor into modules and files
1 parent 7ed018a commit 186db7f

5 files changed

Lines changed: 315 additions & 266 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import python
2+
import TlsLibraryModel
3+
4+
class InsecureContextConfiguration extends DataFlow::Configuration {
5+
TlsLibrary library;
6+
7+
InsecureContextConfiguration() { this = library + ["AllowsTLSv1", "AllowsTLSv1_1"] }
8+
9+
override predicate isSource(DataFlow::Node source) {
10+
source = library.unspecific_context_creation()
11+
}
12+
13+
override predicate isSink(DataFlow::Node sink) {
14+
sink = library.connection_creation().getContext()
15+
}
16+
17+
abstract string flag();
18+
19+
override predicate isBarrierOut(DataFlow::Node node) {
20+
exists(ProtocolRestriction r |
21+
r = library.protocol_restriction() and
22+
node = r.getContext() and
23+
r.getRestriction() = flag()
24+
)
25+
}
26+
}
27+
28+
class AllowsTLSv1 extends InsecureContextConfiguration {
29+
AllowsTLSv1() { this = library + "AllowsTLSv1" }
30+
31+
override string flag() { result = "TLSv1" }
32+
}
33+
34+
class AllowsTLSv1_1 extends InsecureContextConfiguration {
35+
AllowsTLSv1_1() { this = library + "AllowsTLSv1_1" }
36+
37+
override string flag() { result = "TLSv1_1" }
38+
}
39+
40+
predicate unsafe_connection_creation(DataFlow::Node node, ProtocolVersion insecure_version) {
41+
exists(AllowsTLSv1 c | c.hasFlowTo(node)) and
42+
insecure_version = "TLSv1"
43+
or
44+
exists(AllowsTLSv1_1 c | c.hasFlowTo(node)) and
45+
insecure_version = "TLSv1_1"
46+
or
47+
exists(TlsLibrary l | l.insecure_connection_creation(insecure_version) = node)
48+
}
49+
50+
predicate unsafe_context_creation(DataFlow::Node node, string insecure_version) {
51+
exists(TlsLibrary l, ContextCreation cc | cc = l.insecure_context_creation(insecure_version) |
52+
cc = node
53+
)
54+
}

python/ql/src/Security/CWE-327/InsecureProtocol.ql

Lines changed: 2 additions & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -10,277 +10,13 @@
1010
*/
1111

1212
import python
13-
import semmle.python.ApiGraphs
13+
import FluentApiModel
1414

15+
// string foo(ProtocolRestriction r) { result = r.getRestriction() }
1516
// The idea is to track flow from the creation of an insecure context to a use
1617
// such as `wrap_socket`. There should be a data-flow path for each insecure version
1718
// and each path should have a version specific sanitizer. This will allow fluent api
1819
// style code to block the paths one by one.
19-
//
20-
// class InsecureContextCreation extends DataFlow::CfgNode {
21-
// override CallNode node;
22-
// InsecureContextCreation() {
23-
// this = API::moduleImport("ssl").getMember("SSLContext").getACall() and
24-
// insecure_version().asCfgNode() in [node.getArg(0), node.getArgByName("protocol")]
25-
// }
26-
// }
27-
// class InsecureSSLContextCreation extends DataFlow::CfgNode {
28-
// override CallNode node;
29-
// InsecureSSLContextCreation() {
30-
// this = API::moduleImport("ssl").getMember("create_default_context").getACall()
31-
// or
32-
// this = API::moduleImport("ssl").getMember("SSLContext").getACall() and
33-
// API::moduleImport("ssl").getMember("PROTOCOL_TLS").getAUse().asCfgNode() in [
34-
// node.getArg(0), node.getArgByName("protocol")
35-
// ]
36-
// }
37-
// }
38-
abstract class ContextCreation extends DataFlow::CfgNode {
39-
abstract DataFlow::CfgNode getProtocol();
40-
}
41-
42-
abstract class ConnectionCreation extends DataFlow::CfgNode {
43-
abstract DataFlow::CfgNode getContext();
44-
}
45-
46-
class ProtocolRestriction extends DataFlow::CfgNode {
47-
abstract DataFlow::CfgNode getContext();
48-
49-
abstract string getRestriction();
50-
}
51-
52-
abstract class TlsLibrary extends string {
53-
TlsLibrary() { this in ["ssl", "pyOpenSSL"] }
54-
55-
abstract string specific_insecure_version_name();
56-
57-
abstract string unspecific_version_name();
58-
59-
abstract API::Node version_constants();
60-
61-
DataFlow::Node insecure_version() {
62-
result = version_constants().getMember(specific_insecure_version_name()).getAUse()
63-
}
64-
65-
DataFlow::Node unspecific_version() {
66-
result = version_constants().getMember(unspecific_version_name()).getAUse()
67-
}
68-
69-
abstract DataFlow::CfgNode default_context_creation();
70-
71-
abstract ContextCreation specific_context_creation();
72-
73-
ContextCreation insecure_context_creation() {
74-
result = specific_context_creation() and
75-
result.getProtocol() = insecure_version()
76-
}
77-
78-
DataFlow::CfgNode unspecific_context_creation() {
79-
result = default_context_creation()
80-
or
81-
result = specific_context_creation() and
82-
result.(ContextCreation).getProtocol() = unspecific_version()
83-
}
84-
85-
/** A connection is created in an outright insecure manner. */
86-
abstract DataFlow::CfgNode insecure_connection_creation();
87-
88-
/** A connection is created from a context. */
89-
abstract ConnectionCreation connection_creation();
90-
91-
abstract ProtocolRestriction protocol_restriction();
92-
}
93-
94-
module ssl {
95-
class SSLContextCreation extends ContextCreation {
96-
override CallNode node;
97-
98-
SSLContextCreation() { this = API::moduleImport("ssl").getMember("SSLContext").getACall() }
99-
100-
override DataFlow::CfgNode getProtocol() {
101-
result.getNode() in [node.getArg(0), node.getArgByName("protocol")]
102-
}
103-
}
104-
105-
class WrapSocketCall extends ConnectionCreation {
106-
override CallNode node;
107-
108-
WrapSocketCall() { node.getFunction().(AttrNode).getName() = "wrap_socket" }
109-
110-
override DataFlow::CfgNode getContext() {
111-
result.getNode() = node.getFunction().(AttrNode).getObject()
112-
}
113-
}
114-
115-
class OptionsAugOr extends ProtocolRestriction {
116-
string restriction;
117-
118-
OptionsAugOr() {
119-
exists(AugAssign aa, AttrNode attr |
120-
aa.getOperation().getOp() instanceof BitOr and
121-
aa.getTarget() = attr.getNode() and
122-
attr.getName() = "options" and
123-
attr.getObject() = node and
124-
aa.getValue() = API::moduleImport("ssl").getMember(restriction).getAUse().asExpr()
125-
)
126-
}
127-
128-
override DataFlow::CfgNode getContext() { result = this }
129-
130-
override string getRestriction() { result = restriction }
131-
}
132-
133-
class Ssl extends TlsLibrary {
134-
Ssl() { this = "ssl" }
135-
136-
override string specific_insecure_version_name() {
137-
result in [
138-
"PROTOCOL_SSLv2", "PROTOCOL_SSLv3", "PROTOCOL_SSLv23", "PROTOCOL_TLSv1",
139-
"PROTOCOL_TLSv1_1"
140-
]
141-
}
142-
143-
override string unspecific_version_name() { result = "PROTOCOL_TLS" }
144-
145-
override API::Node version_constants() { result = API::moduleImport("ssl") }
146-
147-
override DataFlow::CfgNode default_context_creation() {
148-
result = API::moduleImport("ssl").getMember("create_default_context").getACall()
149-
}
150-
151-
override ContextCreation specific_context_creation() { result instanceof SSLContextCreation }
152-
153-
override DataFlow::CfgNode insecure_connection_creation() {
154-
result = API::moduleImport("ssl").getMember("wrap_socket").getACall()
155-
}
156-
157-
override ConnectionCreation connection_creation() { result instanceof WrapSocketCall }
158-
159-
override ProtocolRestriction protocol_restriction() { result instanceof OptionsAugOr }
160-
}
161-
}
162-
163-
module pyOpenSSL {
164-
class PyOpenSSLContextCreation extends ContextCreation {
165-
override CallNode node;
166-
167-
PyOpenSSLContextCreation() {
168-
this = API::moduleImport("pyOpenSSL").getMember("SSL").getMember("Context").getACall()
169-
}
170-
171-
override DataFlow::CfgNode getProtocol() {
172-
result.getNode() in [node.getArg(0), node.getArgByName("method")]
173-
}
174-
}
175-
176-
class ConnectionCall extends ConnectionCreation {
177-
override CallNode node;
178-
179-
ConnectionCall() {
180-
this = API::moduleImport("pyOpenSSL").getMember("SSL").getMember("Connection").getACall()
181-
}
182-
183-
override DataFlow::CfgNode getContext() {
184-
result.getNode() in [node.getArg(0), node.getArgByName("context")]
185-
}
186-
}
187-
188-
class SetOptionsCall extends ProtocolRestriction {
189-
override CallNode node;
190-
191-
SetOptionsCall() { node.getFunction().(AttrNode).getName() = "set_options" }
192-
193-
override DataFlow::CfgNode getContext() {
194-
result.getNode() = node.getFunction().(AttrNode).getObject()
195-
}
196-
197-
override string getRestriction() {
198-
API::moduleImport("PyOpenSSL").getMember("SSL").getMember(result).getAUse().asCfgNode() in [
199-
node.getArg(0), node.getArgByName("options")
200-
]
201-
}
202-
}
203-
204-
class PyOpenSSL extends TlsLibrary {
205-
PyOpenSSL() { this = "pyOpenSSL" }
206-
207-
override string specific_insecure_version_name() {
208-
result in ["SSLv2_METHOD", "SSLv23_METHOD", "SSLv3_METHOD", "TLSv1_METHOD", "TLSv1_1_METHOD"]
209-
}
210-
211-
override string unspecific_version_name() { result = "TLS_METHOD" }
212-
213-
override API::Node version_constants() {
214-
result = API::moduleImport("pyOpenSSL").getMember("SSL")
215-
}
216-
217-
override DataFlow::CfgNode default_context_creation() { none() }
218-
219-
override ContextCreation specific_context_creation() {
220-
result instanceof PyOpenSSLContextCreation
221-
}
222-
223-
override DataFlow::CfgNode insecure_connection_creation() { none() }
224-
225-
override ConnectionCreation connection_creation() { result instanceof ConnectionCall }
226-
227-
override ProtocolRestriction protocol_restriction() { result instanceof SetOptionsCall }
228-
}
229-
}
230-
231-
class InsecureContextConfiguration extends DataFlow::Configuration {
232-
TlsLibrary library;
233-
234-
InsecureContextConfiguration() { this = library + ["AllowsTLSv1", "AllowsTLSv1_1"] }
235-
236-
override predicate isSource(DataFlow::Node source) {
237-
source = library.unspecific_context_creation()
238-
}
239-
240-
override predicate isSink(DataFlow::Node sink) {
241-
sink = library.connection_creation().getContext()
242-
}
243-
244-
abstract string flag();
245-
246-
override predicate isBarrierOut(DataFlow::Node node) {
247-
exists(ProtocolRestriction r |
248-
r = library.protocol_restriction() and
249-
node = r.getContext() and
250-
r.getRestriction() = flag()
251-
)
252-
}
253-
}
254-
255-
class AllowsTLSv1 extends InsecureContextConfiguration {
256-
AllowsTLSv1() { this = library + "AllowsTLSv1" }
257-
258-
override string flag() { result = "OP_NO_TLSv1" }
259-
}
260-
261-
class AllowsTLSv1_1 extends InsecureContextConfiguration {
262-
AllowsTLSv1_1() { this = library + "AllowsTLSv1_1" }
263-
264-
override string flag() { result = "OP_NO_TLSv1_1" }
265-
}
266-
267-
predicate unsafe_connection_creation(DataFlow::Node node, string insecure_version) {
268-
exists(AllowsTLSv1 c | c.hasFlowTo(node)) and
269-
insecure_version = "TLSv1"
270-
or
271-
exists(AllowsTLSv1_1 c | c.hasFlowTo(node)) and
272-
insecure_version = "TLSv1"
273-
or
274-
exists(TlsLibrary l | l.insecure_connection_creation() = node) and
275-
insecure_version = "[multiple]"
276-
}
277-
278-
predicate unsafe_context_creation(DataFlow::Node node, string insecure_version) {
279-
exists(TlsLibrary l, ContextCreation cc | cc = l.insecure_context_creation() |
280-
cc = node and insecure_version = cc.getProtocol().toString()
281-
)
282-
}
283-
28420
from DataFlow::Node node, string insecure_version
28521
where
28622
unsafe_connection_creation(node, insecure_version)

0 commit comments

Comments
 (0)