Files
codeql/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll
2024-09-10 14:32:35 +02:00

87 lines
2.9 KiB
Plaintext

/**
* Provides default sources, sinks and sanitizers for detecting
* "reflected server-side cross-site scripting"
* vulnerabilities, as well as extension points for adding your own.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.frameworks.data.ModelsAsData
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.BarrierGuards
/**
* Provides default sources, sinks and sanitizers for detecting
* "reflected server-side cross-site scripting"
* vulnerabilities, as well as extension points for adding your own.
*/
module ReflectedXss {
/**
* A data flow source for "reflected server-side cross-site scripting" vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for "reflected server-side cross-site scripting" vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for "reflected server-side cross-site scripting" vulnerabilities.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED: Use `ActiveThreatModelSource` from Concepts instead!
*/
deprecated class RemoteFlowSourceAsSource = ActiveThreatModelSourceAsSource;
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { }
/**
* A data flow sink for "reflected cross-site scripting" vulnerabilities.
*/
private class SinkFromModel extends Sink {
SinkFromModel() {
this = ModelOutput::getASinkNode(["html-injection", "js-injection"]).asSink()
}
}
/**
* The body of a HTTP response that will be returned from a server, considered as a flow sink.
*/
class ServerHttpResponseBodyAsSink extends Sink {
ServerHttpResponseBodyAsSink() {
exists(Http::Server::HttpResponse response |
response.getMimetype().toLowerCase() = "text/html" and
this = response.getBody()
)
}
}
/**
* An HTML escaping, considered as a sanitizer.
*/
class HtmlEscapingAsSanitizer extends Sanitizer {
HtmlEscapingAsSanitizer() {
// TODO: For now, since there is not an `isSanitizingStep` member-predicate part of a
// `TaintTracking::Configuration`, we treat the output as a taint-sanitizer. This
// is slightly imprecise, which you can see in the `m_unsafe + SAFE` test-case in
// python/ql/test/library-tests/frameworks/markupsafe/taint_test.py
//
// However, it is better than `getAnInput()`. Due to use-use flow, that would remove
// the taint-flow to `SINK()` in `some_escape(tainted); SINK(tainted)`.
this = any(HtmlEscaping esc).getOutput()
}
}
/**
* A comparison with a constant string, considered as a sanitizer-guard.
*/
class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { }
}