mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #7654 from RasmusWL/remove-old-pointsto-queries
Python: Cleanup: Remove old points-to versions of queries
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail # see https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
|
||||
|
||||
# Promotes new dataflow queries to be the real ones
|
||||
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
cd $SCRIPTDIR
|
||||
for file in $(find . -mindepth 2); do
|
||||
echo "Promoting $file"
|
||||
mkdir -p "../../Security/$(dirname $file)"
|
||||
mv "$file" "../../Security/${file}"
|
||||
done
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
* @id py/old/bind-socket-all-network-interfaces
|
||||
* @problem.severity error
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
Value aSocket() { result.getClass() = Value::named("socket.socket") }
|
||||
|
||||
CallNode socketBindCall() {
|
||||
result = aSocket().attr("bind").(CallableValue).getACall() and major_version() = 3
|
||||
or
|
||||
result.getFunction().(AttrNode).getObject("bind").pointsTo(aSocket()) and
|
||||
major_version() = 2
|
||||
}
|
||||
|
||||
string allInterfaces() { result = "0.0.0.0" or result = "" }
|
||||
|
||||
Value getTextValue(string address) {
|
||||
result = Value::forUnicode(address) and major_version() = 3
|
||||
or
|
||||
result = Value::forString(address) and major_version() = 2
|
||||
}
|
||||
|
||||
from CallNode call, TupleValue args, string address
|
||||
where
|
||||
call = socketBindCall() and
|
||||
call.getArg(0).pointsTo(args) and
|
||||
args.getItem(0) = getTextValue(address) and
|
||||
address = allInterfaces()
|
||||
select call.getNode(), "'" + address + "' binds a socket to all interfaces."
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Uncontrolled data used in path expression
|
||||
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/path-injection
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import semmle.python.security.injection.Path
|
||||
|
||||
class PathInjectionConfiguration extends TaintTracking::Configuration {
|
||||
PathInjectionConfiguration() { this = "Path injection configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof OpenNode }
|
||||
|
||||
override predicate isSanitizer(Sanitizer sanitizer) {
|
||||
sanitizer instanceof PathSanitizer or
|
||||
sanitizer instanceof NormalizedPathSanitizer
|
||||
}
|
||||
|
||||
override predicate isExtension(TaintTracking::Extension extension) {
|
||||
extension instanceof AbsPath
|
||||
}
|
||||
}
|
||||
|
||||
from PathInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "This path depends on $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Uncontrolled command line
|
||||
* @description Using externally controlled strings in a command line may allow a malicious
|
||||
* user to change the meaning of the command.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/command-line-injection
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import semmle.python.security.injection.Command
|
||||
|
||||
class CommandInjectionConfiguration extends TaintTracking::Configuration {
|
||||
CommandInjectionConfiguration() { this = "Command injection configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof CommandSink }
|
||||
|
||||
override predicate isExtension(TaintTracking::Extension extension) {
|
||||
extension instanceof FirstElementFlow
|
||||
or
|
||||
extension instanceof FabricExecuteExtension
|
||||
}
|
||||
}
|
||||
|
||||
from CommandInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "This command depends on $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Reflected server-side cross-site scripting
|
||||
* @description Writing user input directly to a web page
|
||||
* allows for a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/reflective-xss
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import semmle.python.web.HttpResponse
|
||||
/* Flow */
|
||||
import semmle.python.security.strings.Untrusted
|
||||
|
||||
class ReflectedXssConfiguration extends TaintTracking::Configuration {
|
||||
ReflectedXssConfiguration() { this = "Reflected XSS configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) {
|
||||
sink instanceof HttpResponseTaintSink and
|
||||
not sink instanceof DjangoResponseContent
|
||||
or
|
||||
sink instanceof DjangoResponseContentXSSVulnerable
|
||||
}
|
||||
}
|
||||
|
||||
from ReflectedXssConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "Cross-site scripting vulnerability due to $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: SQL query built from user-controlled sources
|
||||
* @description Building a SQL query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious SQL code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/sql-injection
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import semmle.python.security.injection.Sql
|
||||
import semmle.python.web.django.Db
|
||||
import semmle.python.web.django.Model
|
||||
|
||||
class SQLInjectionConfiguration extends TaintTracking::Configuration {
|
||||
SQLInjectionConfiguration() { this = "SQL injection configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof SqlInjectionSink }
|
||||
}
|
||||
|
||||
/*
|
||||
* Additional configuration to support tracking of DB objects. Connections, cursors, etc.
|
||||
* Without this configuration (or the LegacyConfiguration), the pattern of
|
||||
* `any(MyTaintKind k).taints(control_flow_node)` used in DbConnectionExecuteArgument would not work.
|
||||
*/
|
||||
|
||||
class DbConfiguration extends TaintTracking::Configuration {
|
||||
DbConfiguration() { this = "DB configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof DjangoModelObjects or
|
||||
source instanceof DbConnectionSource
|
||||
}
|
||||
}
|
||||
|
||||
from SQLInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "This SQL query depends on $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @name Code injection
|
||||
* @description OLD QUERY: Interpreting unsanitized user input as code allows a malicious user arbitrary
|
||||
* code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/code-injection
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import semmle.python.security.injection.Exec
|
||||
|
||||
class CodeInjectionConfiguration extends TaintTracking::Configuration {
|
||||
CodeInjectionConfiguration() { this = "Code injection configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof StringEvaluationNode }
|
||||
}
|
||||
|
||||
from CodeInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "$@ flows to here and is interpreted as code.", src.getSource(),
|
||||
"A user-provided value"
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* @name Clear-text logging of sensitive information
|
||||
* @description OLD QUERY: Logging sensitive information without encryption or hashing can
|
||||
* expose it to an attacker.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/clear-text-logging-sensitive-data
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
import semmle.python.security.SensitiveData
|
||||
import semmle.python.security.ClearText
|
||||
|
||||
class CleartextLoggingConfiguration extends TaintTracking::Configuration {
|
||||
CleartextLoggingConfiguration() { this = "ClearTextLogging" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src, TaintKind kind) {
|
||||
src.asCfgNode().(SensitiveData::Source).isSourceOf(kind)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, TaintKind kind) {
|
||||
sink.asCfgNode() instanceof ClearTextLogging::Sink and
|
||||
kind instanceof SensitiveData
|
||||
}
|
||||
}
|
||||
|
||||
from CleartextLoggingConfiguration config, TaintedPathSource source, TaintedPathSink sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getSink(), source, sink, "Sensitive data returned by $@ is logged here.",
|
||||
source.getSource(), source.getCfgNode().(SensitiveData::Source).repr()
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* @name Clear-text storage of sensitive information
|
||||
* @description OLD QUERY: Sensitive information stored without encryption or hashing can expose it to an
|
||||
* attacker.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/clear-text-storage-sensitive-data
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
import semmle.python.security.SensitiveData
|
||||
import semmle.python.security.ClearText
|
||||
|
||||
class CleartextStorageConfiguration extends TaintTracking::Configuration {
|
||||
CleartextStorageConfiguration() { this = "ClearTextStorage" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src, TaintKind kind) {
|
||||
src.asCfgNode().(SensitiveData::Source).isSourceOf(kind)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, TaintKind kind) {
|
||||
sink.asCfgNode() instanceof ClearTextStorage::Sink and
|
||||
kind instanceof SensitiveData
|
||||
}
|
||||
}
|
||||
|
||||
from CleartextStorageConfiguration config, TaintedPathSource source, TaintedPathSink sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getSink(), source, sink, "Sensitive data from $@ is stored here.", source.getSource(),
|
||||
source.getCfgNode().(SensitiveData::Source).repr()
|
||||
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Use of weak cryptographic key
|
||||
* @description Use of a cryptographic key that is too small may allow the encryption to be broken.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id py/old/weak-crypto-key
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
int minimumSecureKeySize(string algo) {
|
||||
algo = "DSA" and result = 2048
|
||||
or
|
||||
algo = "RSA" and result = 2048
|
||||
or
|
||||
algo = "ECC" and result = 224
|
||||
}
|
||||
|
||||
predicate dsaRsaKeySizeArg(FunctionValue func, string algorithm, string arg) {
|
||||
exists(ModuleValue mod | func = mod.attr(_) |
|
||||
algorithm = "DSA" and
|
||||
(
|
||||
mod = Module::named("cryptography.hazmat.primitives.asymmetric.dsa") and arg = "key_size"
|
||||
or
|
||||
mod = Module::named("Crypto.PublicKey.DSA") and arg = "bits"
|
||||
or
|
||||
mod = Module::named("Cryptodome.PublicKey.DSA") and arg = "bits"
|
||||
)
|
||||
or
|
||||
algorithm = "RSA" and
|
||||
(
|
||||
mod = Module::named("cryptography.hazmat.primitives.asymmetric.rsa") and arg = "key_size"
|
||||
or
|
||||
mod = Module::named("Crypto.PublicKey.RSA") and arg = "bits"
|
||||
or
|
||||
mod = Module::named("Cryptodome.PublicKey.RSA") and arg = "bits"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate ecKeySizeArg(FunctionValue func, string arg) {
|
||||
exists(ModuleValue mod | func = mod.attr(_) |
|
||||
mod = Module::named("cryptography.hazmat.primitives.asymmetric.ec") and arg = "curve"
|
||||
)
|
||||
}
|
||||
|
||||
int keySizeFromCurve(ClassValue curveClass) {
|
||||
result = curveClass.declaredAttribute("key_size").(NumericValue).getIntValue()
|
||||
}
|
||||
|
||||
predicate algorithmAndKeysizeForCall(
|
||||
CallNode call, string algorithm, int keySize, ControlFlowNode keyOrigin
|
||||
) {
|
||||
exists(FunctionValue func, string argname, ControlFlowNode arg |
|
||||
arg = func.getNamedArgumentForCall(call, argname)
|
||||
|
|
||||
exists(NumericValue key |
|
||||
arg.pointsTo(key, keyOrigin) and
|
||||
dsaRsaKeySizeArg(func, algorithm, argname) and
|
||||
keySize = key.getIntValue()
|
||||
)
|
||||
or
|
||||
exists(Value curveClassInstance |
|
||||
algorithm = "ECC" and
|
||||
ecKeySizeArg(func, argname) and
|
||||
arg.pointsTo(_, curveClassInstance, keyOrigin) and
|
||||
keySize = keySizeFromCurve(curveClassInstance.getClass())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from CallNode call, string algo, int keySize, ControlFlowNode origin
|
||||
where
|
||||
algorithmAndKeysizeForCall(call, algo, keySize, origin) and
|
||||
keySize < minimumSecureKeySize(algo)
|
||||
select call,
|
||||
"Creation of an " + algo + " key uses $@ bits, which is below " + minimumSecureKeySize(algo) +
|
||||
" and considered breakable.", origin, keySize.toString()
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Use of a broken or weak cryptographic algorithm
|
||||
* @description Using broken or weak cryptographic algorithms can compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @id py/old/weak-cryptographic-algorithm
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
import semmle.python.security.SensitiveData
|
||||
import semmle.python.security.Crypto
|
||||
|
||||
class BrokenCryptoConfiguration extends TaintTracking::Configuration {
|
||||
BrokenCryptoConfiguration() { this = "Broken crypto configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof SensitiveDataSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof WeakCryptoSink }
|
||||
}
|
||||
|
||||
from BrokenCryptoConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "$@ is used in a broken or weak cryptographic algorithm.",
|
||||
src.getSource(), "Sensitive data"
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: Deserializing untrusted input
|
||||
* @description Deserializing user-controlled data may allow attackers to execute arbitrary code.
|
||||
* @kind path-problem
|
||||
* @id py/old/unsafe-deserialization
|
||||
* @problem.severity error
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
// Sources -- Any untrusted input
|
||||
import semmle.python.web.HttpRequest
|
||||
// Flow -- untrusted string
|
||||
import semmle.python.security.strings.Untrusted
|
||||
// Sink -- Unpickling and other deserialization formats.
|
||||
import semmle.python.security.injection.Pickle
|
||||
import semmle.python.security.injection.Marshal
|
||||
import semmle.python.security.injection.Yaml
|
||||
|
||||
class UnsafeDeserializationConfiguration extends TaintTracking::Configuration {
|
||||
UnsafeDeserializationConfiguration() { this = "Unsafe deserialization configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof DeserializationSink }
|
||||
}
|
||||
|
||||
from UnsafeDeserializationConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "Deserializing of $@.", src.getSource(), "untrusted input"
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @name OLD QUERY: URL redirection from remote source
|
||||
* @description URL redirection based on unvalidated user input
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id py/old/url-redirection
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
import semmle.python.web.HttpRedirect
|
||||
import semmle.python.web.HttpRequest
|
||||
import semmle.python.security.strings.Untrusted
|
||||
|
||||
/** Url redirection is a problem only if the user controls the prefix of the URL */
|
||||
class UntrustedPrefixStringKind extends UntrustedStringKind {
|
||||
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
|
||||
result = UntrustedStringKind.super.getTaintForFlowStep(fromnode, tonode) and
|
||||
not tonode.(BinaryExprNode).getRight() = fromnode
|
||||
}
|
||||
}
|
||||
|
||||
class UrlRedirectConfiguration extends TaintTracking::Configuration {
|
||||
UrlRedirectConfiguration() { this = "URL redirect configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpRedirectTaintSink }
|
||||
}
|
||||
|
||||
from UrlRedirectConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
Reference in New Issue
Block a user