mirror of
https://github.com/github/codeql.git
synced 2026-07-03 10:35:29 +02:00
Merge branch 'bazookamusic/python-prompt-injection' of https://github.com/github/codeql into bazookamusic/python-prompt-injection
This commit is contained in:
@@ -5,5 +5,7 @@
|
||||
import python
|
||||
|
||||
select count(Comprehension c |
|
||||
count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode())
|
||||
count(c.toString()) != 1 or
|
||||
count(c.getLocation()) != 1 or
|
||||
not exists(ControlFlowNode n | n.getNode() = c)
|
||||
)
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Classes/PropertyInOldStyleClass.ql
|
||||
query: Classes/PropertyInOldStyleClass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Classes/SlotsInOldStyleClass.ql
|
||||
query: Classes/SlotsInOldStyleClass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Classes/SuperInOldStyleClass.ql
|
||||
query: Classes/SuperInOldStyleClass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#Only works for Python2
|
||||
|
||||
class OldStyle1:
|
||||
class OldStyle1: # $ Alert[py/slots-in-old-style-class]
|
||||
|
||||
__slots__ = [ 'a', 'b' ]
|
||||
|
||||
@@ -12,7 +12,7 @@ class OldStyle1:
|
||||
class OldStyle2:
|
||||
|
||||
def __init__(self, x):
|
||||
super().__init__(x)
|
||||
super().__init__(x) # $ Alert[py/super-in-old-style]
|
||||
|
||||
class NewStyle1(object):
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ class OldStyle:
|
||||
def __init__(self, x):
|
||||
self._x = x
|
||||
|
||||
@property
|
||||
@property # $ Alert[py/property-in-old-style-class]
|
||||
def piosc(self):
|
||||
return self._x
|
||||
@@ -1 +1,2 @@
|
||||
Exceptions/CatchingBaseException.ql
|
||||
query: Exceptions/CatchingBaseException.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Exceptions/EmptyExcept.ql
|
||||
query: Exceptions/EmptyExcept.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Exceptions/IncorrectExceptOrder.ql
|
||||
query: Exceptions/IncorrectExceptOrder.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Exceptions/UnguardedNextInGenerator.ql
|
||||
query: Exceptions/UnguardedNextInGenerator.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
def bad1(it):
|
||||
while True:
|
||||
yield next(it)
|
||||
yield next(it) # $ Alert
|
||||
|
||||
def bad2(seq):
|
||||
it = iter(seq)
|
||||
#Not OK as seq may be empty
|
||||
raise KeyError(next(it))
|
||||
raise KeyError(next(it)) # $ Alert
|
||||
yield 0
|
||||
|
||||
def ok1(seq):
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Exceptions/RaisingTuple.ql
|
||||
query: Exceptions/RaisingTuple.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -5,11 +5,11 @@ def ok():
|
||||
|
||||
def bad1():
|
||||
ex = Exception, "message"
|
||||
raise ex
|
||||
raise ex # $ Alert
|
||||
|
||||
def bad2():
|
||||
raise (Exception, "message")
|
||||
raise (Exception, "message") # $ Alert
|
||||
|
||||
def bad3():
|
||||
ex = Exception,
|
||||
raise ex, "message"
|
||||
raise ex, "message" # $ Alert
|
||||
|
||||
@@ -16,7 +16,7 @@ def useofapply():
|
||||
|
||||
# This use of `apply` is a reference to the builtin function and so SHOULD be
|
||||
# caught by the query.
|
||||
apply(foo, [1])
|
||||
apply(foo, [1]) # $ Alert[py/use-of-apply]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Expressions/UseofApply.ql
|
||||
query: Expressions/UseofApply.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Expressions/UseofInput.ql
|
||||
query: Expressions/UseofInput.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
def use_of_apply(func, args):
|
||||
apply(func, args)
|
||||
apply(func, args) # $ Alert[py/use-of-apply]
|
||||
|
||||
|
||||
def use_of_input():
|
||||
return input() # NOT OK
|
||||
return input() # $ Alert[py/use-of-input] # NOT OK
|
||||
|
||||
|
||||
def not_use_of_input():
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Functions/DeprecatedSliceMethod.ql
|
||||
query: Functions/DeprecatedSliceMethod.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/EncodingError.ql
|
||||
query: Imports/EncodingError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/EncodingError.ql
|
||||
query: Imports/EncodingError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/SyntaxError.ql
|
||||
query: Imports/SyntaxError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
# encoding:shift-jis
|
||||
|
||||
def f():
|
||||
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD>납<EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>"
|
||||
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD>납<EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>" # $ Alert[py/encoding-error]
|
||||
"""
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
`Twas brillig, and the slithy toves
|
||||
`Twas brillig, and the slithy toves # $ Alert[py/syntax-error]
|
||||
Did gyre and gimble in the wabe:
|
||||
All mimsy were the borogoves,
|
||||
And the mome raths outgrabe.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Lexical/OldOctalLiteral.ql
|
||||
query: Lexical/OldOctalLiteral.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#Bad Octal literal
|
||||
017
|
||||
017 # $ Alert
|
||||
#Good Octal literal
|
||||
0o17
|
||||
#Special case file permissions
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/ExecUsed.ql
|
||||
query: Statements/ExecUsed.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/TopLevelPrint.ql
|
||||
query: Statements/TopLevelPrint.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#Top level prints in modules are bad
|
||||
print ("Side effect on import")
|
||||
print ("Side effect on import") # $ Alert[py/print-during-import]
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
def exec_used(val):
|
||||
exec (val)
|
||||
exec (val) # $ Alert[py/use-of-exec]
|
||||
|
||||
#Top level print
|
||||
import module
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Variables/LeakingListComprehension.ql
|
||||
query: Variables/LeakingListComprehension.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -2,12 +2,12 @@ from __future__ import print_function
|
||||
|
||||
def undefined_in_3():
|
||||
[x for x in range(3)]
|
||||
print(x)
|
||||
print(x) # $ Alert
|
||||
|
||||
def different_in_3():
|
||||
y = 10
|
||||
[y for y in range(3)]
|
||||
print(y)
|
||||
print(y) # $ Alert
|
||||
|
||||
def ok():
|
||||
[z for z in range(4)]
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Expressions/UseofApply.ql
|
||||
query: Expressions/UseofApply.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/EncodingError.ql
|
||||
query: Imports/EncodingError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/EncodingError.ql
|
||||
query: Imports/EncodingError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Imports/SyntaxError.ql
|
||||
query: Imports/SyntaxError.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
# encoding:shift-jis
|
||||
|
||||
def f():
|
||||
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD>납<EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>"
|
||||
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD>납<EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>" # $ Alert[py/encoding-error]
|
||||
"""
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
`Twas brillig, and the slithy toves
|
||||
`Twas brillig, and the slithy toves # $ Alert[py/syntax-error]
|
||||
Did gyre and gimble in the wabe:
|
||||
All mimsy were the borogoves,
|
||||
And the mome raths outgrabe.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/ExecUsed.ql
|
||||
query: Statements/ExecUsed.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/TopLevelPrint.ql
|
||||
query: Statements/TopLevelPrint.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#Top level prints in modules are bad
|
||||
print ("Side effect on import")
|
||||
print ("Side effect on import") # $ Alert[py/print-during-import]
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
def exec_used(val):
|
||||
exec(val)
|
||||
exec(val) # $ Alert[py/use-of-exec]
|
||||
|
||||
#Top level print
|
||||
import module
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/UnreachableCode.ql
|
||||
query: Statements/UnreachableCode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Statements/UnreachableCode.ql
|
||||
query: Statements/UnreachableCode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -45,13 +45,15 @@ private class VersionGuardedNode extends DataFlow::Node {
|
||||
|
||||
VersionGuardedNode() {
|
||||
version in [2, 3] and
|
||||
exists(If parent, CompareNode c | parent.getBody().contains(this.asExpr()) |
|
||||
exists(If parent, CompareNode c, ControlFlowNode litCfg |
|
||||
parent.getBody().contains(this.asExpr()) and
|
||||
litCfg.getNode() = any(IntegerLiteral lit | lit.getValue() = version)
|
||||
|
|
||||
c.operands(API::moduleImport("sys")
|
||||
.getMember("version_info")
|
||||
.getASubscript()
|
||||
.asSource()
|
||||
.asCfgNode(), any(Eq eq),
|
||||
any(IntegerLiteral lit | lit.getValue() = version).getAFlowNode())
|
||||
.asCfgNode(), any(Eq eq), litCfg)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
29
python/ql/test/experimental/meta/InlineInstanceTest.qll
Normal file
29
python/ql/test/experimental/meta/InlineInstanceTest.qll
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Defines an InlineExpectationsTest for class instances, that is,
|
||||
* for any API::Node that is an instance of a class (e.g. `Flask`).
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.ApiGraphs
|
||||
import utils.test.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
|
||||
signature API::Node getInstanceSig();
|
||||
|
||||
module MakeInlineInstanceTest<getInstanceSig/0 getInstance> {
|
||||
private module InlineInstanceTest implements TestSig {
|
||||
string getARelevantTag() { result = "instance" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(API::Node instance | instance = getInstance() |
|
||||
location = instance.getLocation() and
|
||||
element = prettyNode(instance.asSource()) and
|
||||
value = "" and
|
||||
tag = "instance"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<InlineInstanceTest>
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# BAD, do not start class or interface name with lowercase letter
|
||||
class badName:
|
||||
class badName: # $ Alert
|
||||
|
||||
def hello(self):
|
||||
print("hello")
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Classes/NamingConventionsClasses.ql
|
||||
query: experimental/Classes/NamingConventionsClasses.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Test:
|
||||
|
||||
# BAD, do not start function name with uppercase letter
|
||||
def HelloWorld(self):
|
||||
def HelloWorld(self): # $ Alert
|
||||
print("hello world")
|
||||
|
||||
# GOOD, function name starts with lowercase letter
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Functions/NamingConventionsFunctions.ql
|
||||
query: experimental/Functions/NamingConventionsFunctions.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-022bis/TarSlipImprov.ql
|
||||
query: experimental/Security/CWE-022bis/TarSlipImprov.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -12,14 +12,14 @@ import os.path
|
||||
unsafe_filename_tar = sys.argv[2]
|
||||
safe_filename_tar = "safe_path.tar"
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
result = []
|
||||
for member in tar:
|
||||
if ".." in member.name:
|
||||
raise ValueError("Path in member name !!!")
|
||||
result.append(member)
|
||||
path = unsafe_filename_tar
|
||||
tar.extractall(path=path, members=result)
|
||||
tar.extractall(path=path, members=result) # $ Alert[py/tarslip-extended]
|
||||
tar.close()
|
||||
|
||||
|
||||
@@ -35,27 +35,27 @@ def members_filter1(tarfile):
|
||||
result.append(member)
|
||||
return result
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=members_filter1(tar))
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=members_filter1(tar)) # $ Alert[py/tarslip-extended]
|
||||
tar.close()
|
||||
|
||||
|
||||
with tarfile.open(unsafe_filename_tar) as tar:
|
||||
with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
if ".." in entry.name:
|
||||
raise ValueError("Illegal tar archive entry")
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def _validate_archive_name(name, target):
|
||||
if not os.path.abspath(os.path.join(target, name)).startswith(target + os.path.sep):
|
||||
raise ValueError(f"Provided language pack contains invalid name {name}")
|
||||
|
||||
with tarfile.open(unsafe_filename_tar) as tar:
|
||||
with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
|
||||
target = "/tmp/unpack"
|
||||
for entry in tar:
|
||||
_validate_archive_name(entry.name, target)
|
||||
tar.extract(entry, target)
|
||||
tar.extract(entry, target) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def members_filter2(tarfile):
|
||||
@@ -85,10 +85,10 @@ def _validate_archive_name(name, target):
|
||||
raise ValueError(f"Provided language pack contains invalid name {name}")
|
||||
|
||||
target = "/tmp/unpack"
|
||||
with tarfile.open(unsafe_filename_tar, "r") as tar:
|
||||
with tarfile.open(unsafe_filename_tar, "r") as tar: # $ Source[py/tarslip-extended]
|
||||
for info in tar.getmembers():
|
||||
_validate_tar_info(info, target)
|
||||
tar.extractall(target)
|
||||
tar.extractall(target) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def members_filter3(tarfile):
|
||||
@@ -108,11 +108,11 @@ tar.extractall(path=tempfile.mkdtemp(), members=members_filter3(tar))
|
||||
tar.close()
|
||||
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
tarf = tar.getmembers()
|
||||
for f in tarf:
|
||||
if not f.issym():
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=[f])
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=[f]) # $ Alert[py/tarslip-extended]
|
||||
tar.close()
|
||||
|
||||
|
||||
@@ -120,27 +120,27 @@ class MKTar(TarFile):
|
||||
pass
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with MKTar.open(name=tarball) as tar:
|
||||
with MKTar.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
tar._extract_member(entry, entry.name)
|
||||
tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.open(tarball) as tar:
|
||||
tar.extractall()
|
||||
with tarfile.open(tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
tar.extractall() # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=None)
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=None) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
class MKTar(tarfile.TarFile):
|
||||
pass
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with MKTar.open(name=tarball) as tar:
|
||||
with MKTar.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
tar._extract_member(entry, entry.name)
|
||||
tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -148,7 +148,7 @@ def py2_tarxz(filename):
|
||||
with tempfile.TemporaryFile() as tmp:
|
||||
subprocess.check_call(["xz", "-dc", filename], stdout=tmp.fileno())
|
||||
tmp.seek(0)
|
||||
with closing(tarfile.TarFile(fileobj=tmp)) as tf:
|
||||
with closing(tarfile.TarFile(fileobj=tmp)) as tf: # $ Source[py/tarslip-extended]
|
||||
yield tf
|
||||
|
||||
def unpack_tarball(tar_filename, dest):
|
||||
@@ -156,7 +156,7 @@ def unpack_tarball(tar_filename, dest):
|
||||
# Py 2.7 lacks lzma support
|
||||
tar_cm = py2_tarxz(tar_filename)
|
||||
else:
|
||||
tar_cm = closing(tarfile.open(tar_filename))
|
||||
tar_cm = closing(tarfile.open(tar_filename)) # $ Source[py/tarslip-extended]
|
||||
|
||||
base_dir = None
|
||||
with tar_cm as tarc:
|
||||
@@ -166,32 +166,32 @@ def unpack_tarball(tar_filename, dest):
|
||||
base_dir = base_name
|
||||
elif base_dir != base_name:
|
||||
print('Unexpected path in %s: %s' % (tar_filename, base_name))
|
||||
tarc.extractall(dest)
|
||||
tarc.extractall(dest) # $ Alert[py/tarslip-extended]
|
||||
return os.path.join(dest, base_dir)
|
||||
|
||||
unpack_tarball(unsafe_filename_tar, "/tmp/unpack")
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.open(name=tarball) as tar:
|
||||
with tarfile.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
tar._extract_member(entry, entry.name)
|
||||
tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.open(name=tarball) as tar:
|
||||
with tarfile.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
tar = tarfile.open(tarball)
|
||||
tar.extractall("/tmp/unpack/")
|
||||
tar = tarfile.open(tarball) # $ Source[py/tarslip-extended]
|
||||
tar.extractall("/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.open(tarball, "r") as tar:
|
||||
tar.extractall(path="/tmp/unpack/", members=tar)
|
||||
with tarfile.open(tarball, "r") as tar: # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path="/tmp/unpack/", members=tar) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def members_filter4(tarfile):
|
||||
@@ -207,8 +207,8 @@ tar.extractall(path=tempfile.mkdtemp(), members=members_filter4(tar))
|
||||
tar.close()
|
||||
|
||||
|
||||
with tarfile.open(unsafe_filename_tar, "r") as tar:
|
||||
tar.extractall(path="/tmp/unpack")
|
||||
with tarfile.open(unsafe_filename_tar, "r") as tar: # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path="/tmp/unpack") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def members_filter5(tarfile):
|
||||
@@ -228,12 +228,12 @@ filename = unsafe_filename_tar
|
||||
tmp_dir = "/tmp/"
|
||||
|
||||
read_type = "r:gz" if filename.endswith("tgz") else "r"
|
||||
with tarfile.open(filename, read_type) as corpus_tar:
|
||||
with tarfile.open(filename, read_type) as corpus_tar: # $ Source[py/tarslip-extended]
|
||||
members = []
|
||||
for f in corpus_tar:
|
||||
if not os.path.isfile(os.path.join(tmp_dir, f.name)):
|
||||
members.append(f)
|
||||
corpus_tar.extractall(tmp_dir, members=members)
|
||||
corpus_tar.extractall(tmp_dir, members=members) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
def members_filter6(tarfile):
|
||||
@@ -251,66 +251,66 @@ tar.close()
|
||||
|
||||
archive_path = unsafe_filename_tar
|
||||
target_dir = "/tmp/unpack"
|
||||
tarfile.open(archive_path, "r").extractall(path=target_dir)
|
||||
tarfile.open(archive_path, "r").extractall(path=target_dir) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.open(tarball) as tar:
|
||||
with tarfile.open(tarball) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
if entry.isfile():
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
with tarfile.open(unsafe_filename_tar) as tar:
|
||||
with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
if entry.name.startswith("/"):
|
||||
raise ValueError("Illegal tar archive entry")
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
tarball = unsafe_filename_tar
|
||||
with tarfile.TarFile(tarball, mode="r") as tar:
|
||||
with tarfile.TarFile(tarball, mode="r") as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
if entry.isfile():
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
with tarfile.open(unsafe_filename_tar) as tar:
|
||||
with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
|
||||
for entry in tar:
|
||||
if os.path.isabs(entry.name):
|
||||
raise ValueError("Illegal tar archive entry")
|
||||
tar.extract(entry, "/tmp/unpack/")
|
||||
tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar:
|
||||
tar.extractall(path="/tmp/unpack")
|
||||
with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar: # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path="/tmp/unpack") # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tar = tarfile.open(filename)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=tar.getmembers())
|
||||
tar = tarfile.open(filename) # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=tar.getmembers()) # $ Alert[py/tarslip-extended]
|
||||
tar.close()
|
||||
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=None)
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=None) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=members_filter4(tar))
|
||||
tar.close()
|
||||
|
||||
|
||||
with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar:
|
||||
tar.extractall(path="/tmp/unpack/", members=tar)
|
||||
with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar: # $ Source[py/tarslip-extended]
|
||||
tar.extractall(path="/tmp/unpack/", members=tar) # $ Alert[py/tarslip-extended]
|
||||
|
||||
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
|
||||
result = []
|
||||
for member in tar:
|
||||
if member.issym():
|
||||
raise ValueError("But it is a symlink")
|
||||
result.append(member)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=result)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=result) # $ Alert[py/tarslip-extended]
|
||||
tar.close()
|
||||
|
||||
|
||||
archive_path = unsafe_filename_tar
|
||||
target_dir = "/tmp/unpack"
|
||||
tarfile.TarFile(unsafe_filename_tar, mode="r").extractall(path=target_dir)
|
||||
tarfile.TarFile(unsafe_filename_tar, mode="r").extractall(path=target_dir) # $ Alert[py/tarslip-extended]
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-022/ZipSlip.ql
|
||||
query: experimental/Security/CWE-022/ZipSlip.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -5,35 +5,35 @@ import gzip
|
||||
import zipfile
|
||||
|
||||
def unzip(filename):
|
||||
with tarfile.open(filename) as zipf:
|
||||
with tarfile.open(filename) as zipf: # $ Alert[py/zipslip]
|
||||
#BAD : This could write any file on the filesystem.
|
||||
for entry in zipf:
|
||||
shutil.move(entry, "/tmp/unpack/")
|
||||
shutil.move(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
|
||||
|
||||
def unzip1(filename):
|
||||
with gzip.open(filename) as zipf:
|
||||
with gzip.open(filename) as zipf: # $ Alert[py/zipslip]
|
||||
#BAD : This could write any file on the filesystem.
|
||||
for entry in zipf:
|
||||
shutil.copy2(entry, "/tmp/unpack/")
|
||||
shutil.copy2(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
|
||||
|
||||
def unzip2(filename):
|
||||
with bz2.open(filename) as zipf:
|
||||
with bz2.open(filename) as zipf: # $ Alert[py/zipslip]
|
||||
#BAD : This could write any file on the filesystem.
|
||||
for entry in zipf:
|
||||
shutil.copyfile(entry, "/tmp/unpack/")
|
||||
shutil.copyfile(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
|
||||
|
||||
def unzip3(filename):
|
||||
zf = zipfile.ZipFile(filename)
|
||||
with zf.namelist() as filelist:
|
||||
with zf.namelist() as filelist: # $ Alert[py/zipslip]
|
||||
#BAD : This could write any file on the filesystem.
|
||||
for x in filelist:
|
||||
shutil.copy(x, "/tmp/unpack/")
|
||||
shutil.copy(x, "/tmp/unpack/") # $ Sink[py/zipslip]
|
||||
|
||||
def unzip4(filename):
|
||||
zf = zipfile.ZipFile(filename)
|
||||
filelist = zf.namelist()
|
||||
filelist = zf.namelist() # $ Alert[py/zipslip]
|
||||
for x in filelist:
|
||||
with zf.open(x) as srcf:
|
||||
shutil.copyfileobj(x, "/tmp/unpack/")
|
||||
shutil.copyfileobj(x, "/tmp/unpack/") # $ Sink[py/zipslip]
|
||||
|
||||
import tty # to set the import root so we can identify the standard library
|
||||
|
||||
@@ -12,8 +12,8 @@ session.handshake(sock)
|
||||
session.userauth_password("user", "password")
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
async def bad1(cmd: str): # $ Source
|
||||
async with asyncssh.connect('localhost') as conn:
|
||||
result = await conn.run(cmd, check=True) # $ result=BAD getRemoteCommand=cmd
|
||||
result = await conn.run(cmd, check=True) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
print(result.stdout, end='')
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@@ -15,11 +15,11 @@ cisco_881 = {
|
||||
}
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
async def bad1(cmd: str): # $ Source
|
||||
net_connect = ConnectHandler(**cisco_881)
|
||||
net_connect.send_command(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_expect(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_timing(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_multiline(commands=[[cmd, "expect"]]) # $ result=BAD getRemoteCommand=List
|
||||
net_connect.send_multiline_timing(commands=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command(command_string=cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_expect(command_string=cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_timing(command_string=cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_multiline(commands=[[cmd, "expect"]]) # $ Alert result=BAD getRemoteCommand=List
|
||||
net_connect.send_multiline_timing(commands=cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@@ -12,10 +12,10 @@ ssh.login(hostname, username, password)
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
ssh.send(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
async def bad1(cmd: str): # $ Source
|
||||
ssh.send(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
ssh.prompt()
|
||||
ssh.sendline(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
ssh.sendline(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
ssh.prompt()
|
||||
ssh.logout()
|
||||
return {"success": stdout}
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql
|
||||
query: experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -10,7 +10,7 @@ from scrapli.driver import GenericDriver
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
async def bad1(cmd: str): # $ Source
|
||||
dev_connect = {
|
||||
"host": host,
|
||||
"auth_username": user,
|
||||
@@ -21,23 +21,23 @@ async def bad1(cmd: str):
|
||||
}
|
||||
driver = AsyncIOSXEDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = await conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncIOSXRDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = await conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncNXOSDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = await conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncEOSDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = await conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncJunosDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = await conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@app.get("/bad1")
|
||||
def bad2(cmd: str):
|
||||
def bad2(cmd: str): # $ Source
|
||||
dev_connect = {
|
||||
"host": host,
|
||||
"auth_username": user,
|
||||
@@ -48,19 +48,19 @@ def bad2(cmd: str):
|
||||
}
|
||||
driver = NXOSDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = IOSXRDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = IOSXEDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = EOSDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
driver = JunosDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
output = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
|
||||
dev_connect = {
|
||||
"host": "65.65.65.65",
|
||||
@@ -71,7 +71,7 @@ def bad2(cmd: str):
|
||||
"platform": "cisco_iosxe",
|
||||
}
|
||||
with Scrapli(**dev_connect) as conn:
|
||||
result = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
result = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
|
||||
dev_connect = {
|
||||
"host": "65.65.65.65",
|
||||
@@ -81,5 +81,5 @@ def bad2(cmd: str):
|
||||
"transport": "ssh2",
|
||||
}
|
||||
with GenericDriver(**dev_connect) as conn:
|
||||
result = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
result = conn.send_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@@ -10,10 +10,10 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: bytes):
|
||||
async def bad1(cmd: bytes): # $ Source
|
||||
endpoint = SSHCommandClientEndpoint.newConnection(
|
||||
reactor,
|
||||
cmd, # $ result=BAD getRemoteCommand=cmd
|
||||
cmd, # $ Alert result=BAD getRemoteCommand=cmd
|
||||
b"username",
|
||||
b"ssh.example.com",
|
||||
22,
|
||||
@@ -21,7 +21,7 @@ async def bad1(cmd: bytes):
|
||||
|
||||
SSHCommandClientEndpoint.existingConnection(
|
||||
endpoint,
|
||||
cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
|
||||
factory = Factory()
|
||||
d = endpoint.connect(factory)
|
||||
|
||||
@@ -12,11 +12,11 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
async def bad1(cmd: str): # $ Source
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@app.get("/bad2")
|
||||
async def bad2(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
async def bad2(cmd: str): # $ Source
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@@ -12,9 +12,9 @@ session.handshake(sock)
|
||||
session.userauth_password("user", "password")
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
async def bad1(cmd: str): # $ Source
|
||||
channel = session.open_session()
|
||||
channel.execute(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
channel.execute(cmd) # $ Alert result=BAD getRemoteCommand=cmd
|
||||
channel.wait_eof()
|
||||
channel.close()
|
||||
channel.wait_closed()
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-079/EmailXss.ql
|
||||
query: experimental/Security/CWE-079/EmailXss.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -11,7 +11,7 @@ def django_response(request):
|
||||
https://github.com/django/django/blob/ca9872905559026af82000e46cde6f7dedc897b6/django/core/mail/__init__.py#L64
|
||||
"""
|
||||
send_mail("Subject", "plain-text body", "from@example.com",
|
||||
["to@example.com"], html_message=django.http.request.GET.get("html"))
|
||||
["to@example.com"], html_message=django.http.request.GET.get("html")) # $ Alert
|
||||
|
||||
|
||||
def django_response(request):
|
||||
@@ -20,6 +20,6 @@ def django_response(request):
|
||||
https://github.com/django/django/blob/ca9872905559026af82000e46cde6f7dedc897b6/django/core/mail/__init__.py#L90-L121
|
||||
"""
|
||||
mail_admins("Subject", "plain-text body",
|
||||
html_message=django.http.request.GET.get("html"))
|
||||
html_message=django.http.request.GET.get("html")) # $ Alert
|
||||
mail_managers("Subject", "plain-text body",
|
||||
html_message=django.http.request.GET.get("html"))
|
||||
html_message=django.http.request.GET.get("html")) # $ Alert
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from flask import request, Flask
|
||||
from flask import request, Flask # $ Source
|
||||
from flask_mail import Mail, Message
|
||||
|
||||
app = Flask(__name__)
|
||||
@@ -10,12 +10,12 @@ def send():
|
||||
sender="from@example.com",
|
||||
recipients=["to@example.com"],
|
||||
body="plain-text body",
|
||||
html=request.args["html"])
|
||||
html=request.args["html"]) # $ Alert
|
||||
|
||||
# The message can contain a body and/or HTML:
|
||||
msg.body = "plain-text body"
|
||||
# The email's HTML can be set via msg.html or as an initialize argument when creating a Message object.
|
||||
msg.html = request.args["html"]
|
||||
msg.html = request.args["html"] # $ Alert
|
||||
|
||||
mail.send(msg)
|
||||
|
||||
@@ -28,5 +28,5 @@ def connect():
|
||||
msg = Message(subject="Subject",
|
||||
sender="from@example.com",
|
||||
recipients=["to@example.com"],
|
||||
html=request.args["html"])
|
||||
html=request.args["html"]) # $ Alert
|
||||
conn.send(msg)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from flask import request, Flask
|
||||
from flask import request, Flask # $ Source
|
||||
from sendgrid import SendGridAPIClient
|
||||
from sendgrid.helpers.mail import Mail, Email, To, Content, MimeType, HtmlContent
|
||||
|
||||
@@ -11,7 +11,7 @@ def send():
|
||||
from_email='from_email@example.com',
|
||||
to_emails='to@example.com',
|
||||
subject='Sending with Twilio SendGrid is Fun',
|
||||
html_content=request.args["html_content"])
|
||||
html_content=request.args["html_content"]) # $ Alert
|
||||
|
||||
sg = SendGridAPIClient('SENDGRID_API_KEY')
|
||||
sg.send(message)
|
||||
@@ -23,7 +23,7 @@ def send():
|
||||
from_email='from_email@example.com',
|
||||
to_emails='to@example.com',
|
||||
subject='Sending with Twilio SendGrid is Fun',
|
||||
html_content=HtmlContent(request.args["html_content"]))
|
||||
html_content=HtmlContent(request.args["html_content"])) # $ Alert
|
||||
|
||||
sg = SendGridAPIClient('SENDGRID_API_KEY')
|
||||
sg.send(message)
|
||||
@@ -34,7 +34,7 @@ def send_post():
|
||||
from_email = Email("test@example.com")
|
||||
to_email = To("test@example.com")
|
||||
subject = "Sending with SendGrid is Fun"
|
||||
html_content = Content("text/html", request.args["html_content"])
|
||||
html_content = Content("text/html", request.args["html_content"]) # $ Alert
|
||||
plain_content = Content("text/plain", request.args["plain_content"])
|
||||
|
||||
mail = Mail(from_email, to_email, subject, plain_content, html_content)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import sendgrid
|
||||
import os
|
||||
from flask import request, Flask
|
||||
from flask import request, Flask # $ Source
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -13,7 +13,7 @@ def send():
|
||||
"content": [
|
||||
{
|
||||
"type": "text/html",
|
||||
"value": "<html>{}</html>".format(request.args["html_content"])
|
||||
"value": "<html>{}</html>".format(request.args["html_content"]) # $ Alert
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
@@ -24,7 +24,7 @@ def send():
|
||||
"mail_settings": {
|
||||
"footer": {
|
||||
"enable": True,
|
||||
"html": "<html>{}</html>".format(request.args["html_footer"]),
|
||||
"html": "<html>{}</html>".format(request.args["html_footer"]), # $ Alert
|
||||
"text": "Thanks,/n The SendGrid Team"
|
||||
},
|
||||
},
|
||||
@@ -38,7 +38,7 @@ def send():
|
||||
"tracking_settings": {
|
||||
"subscription_tracking": {
|
||||
"enable": True,
|
||||
"html": "<html>{}</html>".format(request.args["html_tracking"]),
|
||||
"html": "<html>{}</html>".format(request.args["html_tracking"]), # $ Alert
|
||||
"substitution_tag": "<%click here%>",
|
||||
"text": "If you would like to unsubscribe and stop receiving these emails <% click here %>."
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# This test checks that the developer doesn't pass a MIMEText instance to a MIMEMultipart initializer via the subparts parameter.
|
||||
from flask import Flask, request
|
||||
from flask import Flask, request # $ Source
|
||||
import json
|
||||
import smtplib
|
||||
import ssl
|
||||
@@ -21,7 +21,7 @@ def email_person():
|
||||
|
||||
# Turn these into plain/html MIMEText objects
|
||||
part1 = MIMEText(text, "plain")
|
||||
part2 = MIMEText(html, "html")
|
||||
part2 = MIMEText(html, "html") # $ Alert
|
||||
|
||||
message = MIMEMultipart(_subparts=(part1, part2))
|
||||
message["Subject"] = "multipart test"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# This test checks that the developer doesn't pass a MIMEText instance to a MIMEMultipart message.
|
||||
from flask import Flask, request
|
||||
from flask import Flask, request # $ Source
|
||||
import json
|
||||
import smtplib, ssl
|
||||
from email.mime.text import MIMEText
|
||||
@@ -24,7 +24,7 @@ def email_person():
|
||||
|
||||
# Turn these into plain/html MIMEText objects
|
||||
part1 = MIMEText(text, "plain")
|
||||
part2 = MIMEText(html, "html")
|
||||
part2 = MIMEText(html, "html") # $ Alert
|
||||
|
||||
# Add HTML/plain-text parts to MIMEMultipart message
|
||||
# The email client will try to render the last part first
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
#select
|
||||
| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
edges
|
||||
| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:3:26:3:32 | ControlFlowNode for request | provenance | |
|
||||
| xslt.py:3:26:3:32 | ControlFlowNode for request | xslt.py:10:17:10:23 | ControlFlowNode for request | provenance | |
|
||||
@@ -64,7 +71,9 @@ edges
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | |
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | MaD:58660 |
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | MaD:1 |
|
||||
models
|
||||
| 1 | Summary: lxml; Member[etree].Member[fromstringlist]; Argument[0,strings:].ListElement; ReturnValue; taint |
|
||||
nodes
|
||||
| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
|
||||
| xslt.py:3:26:3:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
@@ -122,10 +131,3 @@ nodes
|
||||
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | semmle.label | ControlFlowNode for xsltStrings [List element] |
|
||||
| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root |
|
||||
subpaths
|
||||
#select
|
||||
| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
experimental/Security/CWE-091/XsltInjection.ql
|
||||
query: experimental/Security/CWE-091/XsltInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
from flask import Flask, request
|
||||
from flask import Flask, request # $ Source
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -11,4 +11,4 @@ def bad():
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root) # Not OK
|
||||
result_tree = tree.xslt(xslt_root) # $ Alert # Not OK
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
from flask import Flask, request
|
||||
from flask import Flask, request # $ Source
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -9,7 +9,7 @@ app = Flask(__name__)
|
||||
def a():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
transform = etree.XSLT(xslt_root) # Not OK
|
||||
transform = etree.XSLT(xslt_root) # $ Alert # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt2")
|
||||
@@ -18,7 +18,7 @@ def b():
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root) # Not OK
|
||||
result_tree = tree.xslt(xslt_root) # $ Alert # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt3")
|
||||
@@ -28,7 +28,7 @@ def c():
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
result = tree.xslt(xslt_root, a="'A'") # $ Alert # Not OK
|
||||
|
||||
@app.route("/xslt4")
|
||||
def d():
|
||||
@@ -37,7 +37,7 @@ def d():
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
result = tree.xslt(xslt_root, a="'A'") # $ Alert # Not OK
|
||||
|
||||
@app.route("/xslt5")
|
||||
def e():
|
||||
@@ -47,7 +47,7 @@ def e():
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
result = tree.xslt(xslt_root, a="'A'") # $ Alert # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt6")
|
||||
@@ -76,4 +76,4 @@ def h():
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # OK
|
||||
result = tree.xslt(xslt_root, a="'A'") # OK
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-094/Js2Py.ql
|
||||
query: experimental/Security/CWE-094/Js2Py.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -6,5 +6,5 @@ bp = flask.Blueprint("app", __name__, url_prefix="/")
|
||||
|
||||
@bp.route("/bad")
|
||||
def bad():
|
||||
jk = flask.request.form["jk"]
|
||||
jk = eval_js(f"{jk} f()")
|
||||
jk = flask.request.form["jk"] # $ Source
|
||||
jk = eval_js(f"{jk} f()") # $ Alert
|
||||
@@ -1,3 +1,7 @@
|
||||
#select
|
||||
| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
edges
|
||||
| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:9:19:9:25 | ControlFlowNode for request | provenance | |
|
||||
| csv_bad.py:9:19:9:25 | ControlFlowNode for request | csv_bad.py:16:16:16:22 | ControlFlowNode for request | provenance | |
|
||||
@@ -26,7 +30,3 @@ nodes
|
||||
| csv_bad.py:24:16:24:38 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data |
|
||||
subpaths
|
||||
#select
|
||||
| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-1236/CsvInjection.ql
|
||||
query: experimental/Security/CWE-1236/CsvInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import copy
|
||||
import csv
|
||||
from flask import Flask
|
||||
from flask import request
|
||||
from flask import request # $ Source
|
||||
from typing import List
|
||||
|
||||
app = Flask(__name__)
|
||||
@@ -15,17 +15,17 @@ app = Flask(__name__)
|
||||
def bad1():
|
||||
csv_data = request.args.get('csv')
|
||||
csvWriter = csv.writer(open("test.csv", "wt"))
|
||||
csvWriter.writerow(csv_data) # bad
|
||||
csvWriter.writerows(csv_data) # bad
|
||||
csvWriter.writerow(csv_data) # $ Alert # bad
|
||||
csvWriter.writerows(csv_data) # $ Alert # bad
|
||||
return "bad1"
|
||||
|
||||
@app.route('/bad2')
|
||||
def bad2():
|
||||
csv_data = request.args.get('csv')
|
||||
csvWriter = csv.DictWriter(f, fieldnames=csv_data) # bad
|
||||
csvWriter = csv.DictWriter(f, fieldnames=csv_data) # $ Alert # bad
|
||||
csvWriter.writeheader()
|
||||
return "bad2"
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.debug = True
|
||||
app.run()
|
||||
app.run()
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-176/UnicodeBypassValidation.ql
|
||||
query: experimental/Security/CWE-176/UnicodeBypassValidation.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import unicodedata
|
||||
from flask import Flask, request, escape, render_template
|
||||
from flask import Flask, request, escape, render_template # $ Source
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -7,7 +7,7 @@ app = Flask(__name__)
|
||||
@app.route("/unsafe1")
|
||||
def unsafe1():
|
||||
user_input = escape(request.args.get("ui"))
|
||||
normalized_user_input = unicodedata.normalize("NFKC", user_input) # $ result=BAD
|
||||
normalized_user_input = unicodedata.normalize("NFKC", user_input) # $ Alert result=BAD
|
||||
return render_template("result.html", normalized_user_input=normalized_user_input)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def unsafe1bis():
|
||||
if user_input.isascii():
|
||||
normalized_user_input = user_input
|
||||
else:
|
||||
normalized_user_input = unicodedata.normalize("NFC", user_input) # $ result=BAD
|
||||
normalized_user_input = unicodedata.normalize("NFC", user_input) # $ Alert result=BAD
|
||||
return render_template("result.html", normalized_user_input=normalized_user_input)
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#select
|
||||
| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | signature message |
|
||||
| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | MAC message |
|
||||
edges
|
||||
| TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | provenance | |
|
||||
| TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | provenance | |
|
||||
@@ -9,6 +12,3 @@ nodes
|
||||
| TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | semmle.label | ControlFlowNode for sign() |
|
||||
subpaths
|
||||
#select
|
||||
| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | signature message |
|
||||
| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | MAC message |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
|
||||
query: experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -16,25 +16,25 @@ def UnsafeCmacCheck(actualCmac):
|
||||
expected = cmac.CMAC(algorithms.AES(key))
|
||||
expected.update(b"message to authenticate")
|
||||
expected.finalize()
|
||||
return actualCmac == expected
|
||||
return actualCmac == expected
|
||||
|
||||
|
||||
def UnsafeCheckSignature(expected):
|
||||
message = b'To be signed'
|
||||
key = RSA.import_key(open('private_key.der').read())
|
||||
h = SHA256.new(message)
|
||||
signature = pkcs1_15.new(key).sign(h)
|
||||
return expected == signature
|
||||
signature = pkcs1_15.new(key).sign(h) # $ Source[py/possible-timing-attack-against-hash]
|
||||
return expected == signature # $ Alert[py/possible-timing-attack-against-hash]
|
||||
|
||||
def sign(pre_key, msg, alg):
|
||||
return hmac.new(pre_key, msg, alg).digest()
|
||||
return hmac.new(pre_key, msg, alg).digest() # $ Source[py/possible-timing-attack-against-hash]
|
||||
|
||||
def verifyGood(msg, sig):
|
||||
return constant_time_string_compare(sig, sign(key, msg, hashlib.sha256)) #good
|
||||
|
||||
|
||||
def verifyBad(msg, sig):
|
||||
key = "e179017a-62b0-4996-8a38-e91aa9f1"
|
||||
return sig == sign(key, msg, hashlib.sha256) #bad
|
||||
return sig == sign(key, msg, hashlib.sha256) # $ Alert[py/possible-timing-attack-against-hash] #bad
|
||||
|
||||
def constant_time_string_compare(a, b):
|
||||
if len(a) != len(b):
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
|
||||
query: experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -11,7 +11,7 @@ app = Flask(__name__)
|
||||
|
||||
@app.route('/bad')
|
||||
def bad():
|
||||
if not request.headers.get('X-Auth-Token') == "token":
|
||||
if not request.headers.get('X-Auth-Token') == "token": # $ Alert
|
||||
raise Exception('bad token')
|
||||
return 'bad'
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
|
||||
query: experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
|
||||
query: experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -12,8 +12,8 @@ app = Flask(__name__)
|
||||
@app.route('/bad', methods = ['POST', 'GET'])
|
||||
def bad():
|
||||
if request.method == 'POST':
|
||||
password = request.form['pwd']
|
||||
return password == "1234"
|
||||
password = request.form['pwd'] # $ Source
|
||||
return password == "1234" # $ Alert
|
||||
|
||||
@app.route('/good', methods = ['POST', 'GET'])
|
||||
def good():
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
|
||||
query: experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -2,7 +2,7 @@ from flask import Flask, session
|
||||
from flask_session import Session
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'CHANGEME'
|
||||
app.config['SECRET_KEY'] = 'CHANGEME' # $ Alert
|
||||
|
||||
Session(app)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from flask import Flask, session
|
||||
|
||||
app = Flask(__name__)
|
||||
aConstant = 'CHANGEME1'
|
||||
app.config['SECRET_KEY'] = aConstant
|
||||
app.secret_key = aConstant
|
||||
app.config.update(SECRET_KEY=aConstant)
|
||||
app.config.from_mapping(SECRET_KEY=aConstant)
|
||||
aConstant = 'CHANGEME1' # $ Source
|
||||
app.config['SECRET_KEY'] = aConstant # $ Alert
|
||||
app.secret_key = aConstant # $ Alert
|
||||
app.config.update(SECRET_KEY=aConstant) # $ Alert
|
||||
app.config.from_mapping(SECRET_KEY=aConstant) # $ Alert
|
||||
app.config.from_pyfile("config.py")
|
||||
app.config.from_object('config.Config')
|
||||
|
||||
|
||||
@@ -4,16 +4,16 @@ import os
|
||||
import random
|
||||
|
||||
FLASK_DEBUG = True
|
||||
aConstant = 'CHANGEME2'
|
||||
aConstant = 'CHANGEME2' # $ Source
|
||||
|
||||
|
||||
class Config:
|
||||
SECRET_KEY = environ.get("envKey")
|
||||
SECRET_KEY = aConstant
|
||||
SECRET_KEY = aConstant # $ Alert
|
||||
SECRET_KEY = os.getenv('envKey')
|
||||
SECRET_KEY = os.environ.get('envKey')
|
||||
SECRET_KEY = os.environ.get('envKey', random.randint)
|
||||
SECRET_KEY = os.getenv('envKey', random.randint)
|
||||
SECRET_KEY = os.getenv('envKey', aConstant)
|
||||
SECRET_KEY = os.environ.get('envKey', aConstant)
|
||||
SECRET_KEY = os.getenv('envKey', aConstant) # $ Alert
|
||||
SECRET_KEY = os.environ.get('envKey', aConstant) # $ Alert
|
||||
SECRET_KEY = os.environ['envKey']
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
# General Config
|
||||
FLASK_DEBUG = True
|
||||
SECRET_KEY = "CHANGEME5"
|
||||
SECRET_KEY = "CHANGEME5" # $ Alert
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-287/ImproperLdapAuth.ql
|
||||
query: experimental/Security/CWE-287/ImproperLdapAuth.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -16,7 +16,7 @@ def simple_bind_example():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.simple_bind('cn=root')
|
||||
ldap_connection.simple_bind('cn=root') # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ def simple_bind_s_example():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.simple_bind_s('cn=root')
|
||||
ldap_connection.simple_bind_s('cn=root') # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ def bind_s_example():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.bind_s('cn=root', None)
|
||||
ldap_connection.bind_s('cn=root', None) # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
@app.route("/bind_s_example")
|
||||
@@ -57,7 +57,7 @@ def bind_s_example_kwargs():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.bind_s(who='cn=root', cred=None)
|
||||
ldap_connection.bind_s(who='cn=root', cred=None) # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
@app.route("/bind_example")
|
||||
@@ -70,7 +70,7 @@ def bind_example():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.bind('cn=root', "")
|
||||
ldap_connection.bind('cn=root', "") # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ def bind_example():
|
||||
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
|
||||
|
||||
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
|
||||
ldap_connection.bind(who='cn=root', cred="")
|
||||
ldap_connection.bind(who='cn=root', cred="") # $ Alert
|
||||
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def passwordNone():
|
||||
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
|
||||
|
||||
srv = Server('servername', get_info=ALL)
|
||||
conn = Connection(srv, 'user_dn', None)
|
||||
conn = Connection(srv, 'user_dn', None) # $ Alert
|
||||
status, result, response, _ = conn.search(dn, search_filter)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ def passwordNoneKwargs():
|
||||
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
|
||||
|
||||
srv = Server('servername', get_info=ALL)
|
||||
conn = Connection(srv, user='user_dn', password=None)
|
||||
conn = Connection(srv, user='user_dn', password=None) # $ Alert
|
||||
status, result, response, _ = conn.search(dn, search_filter)
|
||||
|
||||
@app.route("/passwordEmpty")
|
||||
@@ -43,7 +43,7 @@ def passwordEmpty():
|
||||
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
|
||||
|
||||
srv = Server('servername', get_info=ALL)
|
||||
conn = Connection(srv, user='user_dn', password="")
|
||||
conn = Connection(srv, user='user_dn', password="") # $ Alert
|
||||
status, result, response, _ = conn.search(dn, search_filter)
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ def notPassword():
|
||||
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
|
||||
|
||||
srv = Server('servername', get_info=ALL)
|
||||
conn = Connection(srv, user='user_dn')
|
||||
conn = Connection(srv, user='user_dn') # $ Alert
|
||||
status, result, response, _ = conn.search(dn, search_filter)
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#select
|
||||
| test.py:11:9:11:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:11:9:11:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:21:9:21:19 | ControlFlowNode for blob_client | test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:21:9:21:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:31:9:31:19 | ControlFlowNode for blob_client | test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:31:9:31:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:43:9:43:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:43:9:43:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:75:9:75:10 | ControlFlowNode for bc | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:75:9:75:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
edges
|
||||
| test.py:3:1:3:3 | ControlFlowNode for BSC | test.py:7:19:7:21 | ControlFlowNode for BSC | provenance | |
|
||||
| test.py:3:1:3:3 | ControlFlowNode for BSC | test.py:35:19:35:21 | ControlFlowNode for BSC | provenance | |
|
||||
@@ -86,9 +92,3 @@ nodes
|
||||
| test.py:73:10:73:33 | ControlFlowNode for get_unsafe_blob_client() | semmle.label | ControlFlowNode for get_unsafe_blob_client() |
|
||||
| test.py:75:9:75:10 | ControlFlowNode for bc | semmle.label | ControlFlowNode for bc |
|
||||
subpaths
|
||||
#select
|
||||
| test.py:11:9:11:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:11:9:11:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:21:9:21:19 | ControlFlowNode for blob_client | test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:21:9:21:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:31:9:31:19 | ControlFlowNode for blob_client | test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:31:9:31:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:43:9:43:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:43:9:43:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
| test.py:75:9:75:10 | ControlFlowNode for bc | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:75:9:75:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
|
||||
query: experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient
|
||||
|
||||
BSC = BlobServiceClient.from_connection_string(...)
|
||||
BSC = BlobServiceClient.from_connection_string(...) # $ Source
|
||||
|
||||
def unsafe():
|
||||
# does not set encryption_version to 2.0, default is unsafe
|
||||
@@ -8,27 +8,27 @@ def unsafe():
|
||||
blob_client.require_encryption = True
|
||||
blob_client.key_encryption_key = ...
|
||||
with open("decryptedcontentfile.txt", "rb") as stream:
|
||||
blob_client.upload_blob(stream) # BAD
|
||||
blob_client.upload_blob(stream) # $ Alert # BAD
|
||||
|
||||
|
||||
def unsafe_setting_on_blob_service_client():
|
||||
blob_service_client = BlobServiceClient.from_connection_string(...)
|
||||
blob_service_client = BlobServiceClient.from_connection_string(...) # $ Source
|
||||
blob_service_client.require_encryption = True
|
||||
blob_service_client.key_encryption_key = ...
|
||||
|
||||
blob_client = blob_service_client.get_blob_client(...)
|
||||
with open("decryptedcontentfile.txt", "rb") as stream:
|
||||
blob_client.upload_blob(stream)
|
||||
blob_client.upload_blob(stream) # $ Alert
|
||||
|
||||
|
||||
def unsafe_setting_on_container_client():
|
||||
container_client = ContainerClient.from_connection_string(...)
|
||||
container_client = ContainerClient.from_connection_string(...) # $ Source
|
||||
container_client.require_encryption = True
|
||||
container_client.key_encryption_key = ...
|
||||
|
||||
blob_client = container_client.get_blob_client(...)
|
||||
with open("decryptedcontentfile.txt", "rb") as stream:
|
||||
blob_client.upload_blob(stream)
|
||||
blob_client.upload_blob(stream) # $ Alert
|
||||
|
||||
|
||||
def potentially_unsafe(use_new_version=False):
|
||||
@@ -40,7 +40,7 @@ def potentially_unsafe(use_new_version=False):
|
||||
blob_client.encryption_version = '2.0'
|
||||
|
||||
with open("decryptedcontentfile.txt", "rb") as stream:
|
||||
blob_client.upload_blob(stream) # BAD
|
||||
blob_client.upload_blob(stream) # $ Alert # BAD
|
||||
|
||||
|
||||
def safe():
|
||||
@@ -72,7 +72,7 @@ def get_unsafe_blob_client():
|
||||
def unsafe_with_calls():
|
||||
bc = get_unsafe_blob_client()
|
||||
with open("decryptedcontentfile.txt", "rb") as stream:
|
||||
bc.upload_blob(stream) # BAD
|
||||
bc.upload_blob(stream) # $ Alert # BAD
|
||||
|
||||
|
||||
def get_safe_blob_client():
|
||||
|
||||
@@ -2,4 +2,4 @@ import random
|
||||
|
||||
def generatePassword():
|
||||
# BAD: the random is not cryptographically secure
|
||||
return random.random()
|
||||
return random.random() # $ Alert
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-338/InsecureRandomness.ql
|
||||
query: experimental/Security/CWE-338/InsecureRandomness.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user