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

Skip to content

Commit 20d5454

Browse files
committed
python: move log injection out of experimental
- move from custom concept `LogOutput` to standard concept `Logging` - remove `Log.qll` from experimental frameworks - fold models into standard models (naively for now) - stdlib: - make Logger module public - broaden definition of instance - add `extra` keyword as possible source - flak: add app.logger as logger instance - django: `add django.utils.log.request_logger` as logger instance (should we add the rest?) - remove LogOutput from experimental concepts
1 parent bb2feda commit 20d5454

16 files changed

Lines changed: 66 additions & 178 deletions

File tree

python/ql/lib/semmle/python/frameworks/Django.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,4 +2295,17 @@ module PrivateDjango {
22952295

22962296
override string getMimetypeDefault() { none() }
22972297
}
2298+
2299+
// ---------------------------------------------------------------------------
2300+
// Logging
2301+
// ---------------------------------------------------------------------------
2302+
/**
2303+
* Django provides a standard Python logger.
2304+
*/
2305+
private class DjangoLogger extends Stdlib::Logger::LoggerInstance {
2306+
DjangoLogger() {
2307+
this =
2308+
API::moduleImport("django").getMember("utils").getMember("log").getMember("request_logger")
2309+
}
2310+
}
22982311
}

python/ql/lib/semmle/python/frameworks/Flask.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ private import semmle.python.dataflow.new.RemoteFlowSources
99
private import semmle.python.dataflow.new.TaintTracking
1010
private import semmle.python.Concepts
1111
private import semmle.python.frameworks.Werkzeug
12+
private import semmle.python.frameworks.Stdlib
1213
private import semmle.python.ApiGraphs
1314
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
1415
private import semmle.python.security.dataflow.PathInjectionCustomizations
@@ -569,4 +570,14 @@ module Flask {
569570
result in [this.getArg(0), this.getArgByName("filename_or_fp")]
570571
}
571572
}
573+
574+
// ---------------------------------------------------------------------------
575+
// Logging
576+
// ---------------------------------------------------------------------------
577+
/**
578+
* The attribute `logger` on a Flask application is a standard Python logger.
579+
*/
580+
private class FlaskLogger extends Stdlib::Logger::LoggerInstance {
581+
FlaskLogger() { this = FlaskApp::instance().getMember("logger") }
582+
}
572583
}

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,42 @@ module Stdlib {
237237
}
238238
}
239239
}
240+
241+
// ---------------------------------------------------------------------------
242+
// logging
243+
// ---------------------------------------------------------------------------
244+
/**
245+
* Provides models for the `logging.Logger` class and subclasses.
246+
*
247+
* See https://docs.python.org/3.9/library/logging.html#logging.Logger.
248+
*/
249+
module Logger {
250+
/**
251+
* An instance of `logging.Logger`. Extend this class to model new instances.
252+
* Most major frameworks will provide a logger instance as a class attribute.
253+
*/
254+
abstract class LoggerInstance extends API::Node {
255+
override string toString() { result = "logger" }
256+
}
257+
258+
/** Gets a reference to the `logging.Logger` class or any subclass. */
259+
API::Node subclassRef() {
260+
result = API::moduleImport("logging").getMember("Logger").getASubclass*()
261+
}
262+
263+
/** Gets a reference to an instance of `logging.Logger` or any subclass. */
264+
API::Node instance() {
265+
result instanceof LoggerInstance
266+
or
267+
result = subclassRef().getReturn()
268+
or
269+
result = API::moduleImport("logging")
270+
or
271+
result = API::moduleImport("logging").getMember("root")
272+
or
273+
result = API::moduleImport("logging").getMember("getLogger").getReturn()
274+
}
275+
}
240276
}
241277

242278
/**
@@ -2642,27 +2678,6 @@ private module StdlibPrivate {
26422678
// ---------------------------------------------------------------------------
26432679
// logging
26442680
// ---------------------------------------------------------------------------
2645-
/**
2646-
* Provides models for the `logging.Logger` class and subclasses.
2647-
*
2648-
* See https://docs.python.org/3.9/library/logging.html#logging.Logger.
2649-
*/
2650-
module Logger {
2651-
/** Gets a reference to the `logging.Logger` class or any subclass. */
2652-
API::Node subclassRef() {
2653-
result = API::moduleImport("logging").getMember("Logger").getASubclass*()
2654-
}
2655-
2656-
/** Gets a reference to an instance of `logging.Logger` or any subclass. */
2657-
API::Node instance() {
2658-
result = subclassRef().getReturn()
2659-
or
2660-
result = API::moduleImport("logging").getMember("root")
2661-
or
2662-
result = API::moduleImport("logging").getMember("getLogger").getReturn()
2663-
}
2664-
}
2665-
26662681
/**
26672682
* A call to one of the logging methods from `logging` or on a `logging.Logger`
26682683
* subclass.
@@ -2683,14 +2698,12 @@ private module StdlibPrivate {
26832698
method = "log" and
26842699
msgIndex = 1
26852700
|
2686-
this = Logger::instance().getMember(method).getACall()
2687-
or
2688-
this = API::moduleImport("logging").getMember(method).getACall()
2701+
this = Stdlib::Logger::instance().getMember(method).getACall()
26892702
)
26902703
}
26912704

26922705
override DataFlow::Node getAnInput() {
2693-
result = this.getArgByName("msg")
2706+
result = this.getArgByName(["msg", "extra"])
26942707
or
26952708
result = this.getArg(any(int i | i >= msgIndex))
26962709
}

python/ql/src/experimental/semmle/python/security/injection/LogInjection.qll renamed to python/ql/lib/semmle/python/security/dataflow/LogInjection.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import python
22
import semmle.python.Concepts
3-
import experimental.semmle.python.Concepts
3+
import semmle.python.Concepts
44
import semmle.python.dataflow.new.DataFlow
55
import semmle.python.dataflow.new.TaintTracking
66
import semmle.python.dataflow.new.RemoteFlowSources
@@ -13,7 +13,7 @@ class LogInjectionFlowConfig extends TaintTracking::Configuration {
1313

1414
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
1515

16-
override predicate isSink(DataFlow::Node sink) { sink = any(LogOutput logoutput).getAnInput() }
16+
override predicate isSink(DataFlow::Node sink) { sink = any(Logging write).getAnInput() }
1717

1818
override predicate isSanitizer(DataFlow::Node node) {
1919
exists(CallNode call |

python/ql/src/experimental/Security/CWE-117/LogInjection.qhelp renamed to python/ql/src/Security/CWE-117/LogInjection.qhelp

File renamed without changes.

python/ql/src/experimental/Security/CWE-117/LogInjection.ql renamed to python/ql/src/Security/CWE-117/LogInjection.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
import python
14-
import experimental.semmle.python.security.injection.LogInjection
14+
import semmle.python.security.dataflow.LogInjection
1515
import DataFlow::PathGraph
1616

1717
from LogInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink

python/ql/src/experimental/Security/CWE-117/LogInjectionBad.py renamed to python/ql/src/Security/CWE-117/LogInjectionBad.py

File renamed without changes.

python/ql/src/experimental/Security/CWE-117/LogInjectionGood.py renamed to python/ql/src/Security/CWE-117/LogInjectionGood.py

File renamed without changes.

python/ql/src/experimental/semmle/python/Concepts.qll

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,6 @@ private import semmle.python.dataflow.new.RemoteFlowSources
1414
private import semmle.python.dataflow.new.TaintTracking
1515
private import experimental.semmle.python.Frameworks
1616

17-
/** Provides classes for modeling log related APIs. */
18-
module LogOutput {
19-
/**
20-
* A data flow node for log output.
21-
*
22-
* Extend this class to model new APIs. If you want to refine existing API models,
23-
* extend `LogOutput` instead.
24-
*/
25-
abstract class Range extends DataFlow::Node {
26-
/**
27-
* Get the parameter value of the log output function.
28-
*/
29-
abstract DataFlow::Node getAnInput();
30-
}
31-
}
32-
33-
/**
34-
* A data flow node for log output.
35-
*
36-
* Extend this class to refine existing API models. If you want to model new APIs,
37-
* extend `LogOutput::Range` instead.
38-
*/
39-
class LogOutput extends DataFlow::Node {
40-
LogOutput::Range range;
41-
42-
LogOutput() { this = range }
43-
44-
DataFlow::Node getAnInput() { result = range.getAnInput() }
45-
}
46-
4717
/** Provides classes for modeling LDAP query execution-related APIs. */
4818
module LDAPQuery {
4919
/**

python/ql/src/experimental/semmle/python/Frameworks.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ private import experimental.semmle.python.frameworks.Django
88
private import experimental.semmle.python.frameworks.Werkzeug
99
private import experimental.semmle.python.frameworks.LDAP
1010
private import experimental.semmle.python.frameworks.NoSQL
11-
private import experimental.semmle.python.frameworks.Log
1211
private import experimental.semmle.python.frameworks.JWT
1312
private import experimental.semmle.python.libraries.PyJWT
1413
private import experimental.semmle.python.libraries.Authlib

0 commit comments

Comments
 (0)