Merge pull request #6155 from RasmusWL/port-cleartext-queries

Python: Port cleartext queries
This commit is contained in:
yoff
2021-06-30 15:52:34 +02:00
committed by GitHub
39 changed files with 1293 additions and 263 deletions

View File

@@ -93,6 +93,23 @@ class EncodingTest extends InlineExpectationsTest {
}
}
class LoggingTest extends InlineExpectationsTest {
LoggingTest() { this = "LoggingTest" }
override string getARelevantTag() { result in ["loggingInput"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(Logging logging, DataFlow::Node data |
location = data.getLocation() and
element = data.toString() and
value = prettyNodeForInlineTest(data) and
data = logging.getAnInput() and
tag = "loggingInput"
)
}
}
class CodeExecutionTest extends InlineExpectationsTest {
CodeExecutionTest() { this = "CodeExecutionTest" }
@@ -284,6 +301,38 @@ class HttpServerHttpRedirectResponseTest extends InlineExpectationsTest {
}
}
class HttpServerCookieWriteTest extends InlineExpectationsTest {
HttpServerCookieWriteTest() { this = "HttpServerCookieWriteTest" }
override string getARelevantTag() {
result in ["CookieWrite", "CookieRawHeader", "CookieName", "CookieValue"]
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(HTTP::Server::CookieWrite cookieWrite |
location = cookieWrite.getLocation() and
(
element = cookieWrite.toString() and
value = "" and
tag = "CookieWrite"
or
element = cookieWrite.toString() and
value = prettyNodeForInlineTest(cookieWrite.getHeaderArg()) and
tag = "CookieRawHeader"
or
element = cookieWrite.toString() and
value = prettyNodeForInlineTest(cookieWrite.getNameArg()) and
tag = "CookieName"
or
element = cookieWrite.toString() and
value = prettyNodeForInlineTest(cookieWrite.getValueArg()) and
tag = "CookieValue"
)
)
}
}
class FileSystemAccessTest extends InlineExpectationsTest {
FileSystemAccessTest() { this = "FileSystemAccessTest" }
@@ -301,6 +350,23 @@ class FileSystemAccessTest extends InlineExpectationsTest {
}
}
class FileSystemWriteAccessTest extends InlineExpectationsTest {
FileSystemWriteAccessTest() { this = "FileSystemWriteAccessTest" }
override string getARelevantTag() { result = "fileWriteData" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(FileSystemWriteAccess write, DataFlow::Node data |
data = write.getADataNode() and
location = data.getLocation() and
element = data.toString() and
value = prettyNodeForInlineTest(data) and
tag = "fileWriteData"
)
}
}
class PathNormalizationTest extends InlineExpectationsTest {
PathNormalizationTest() { this = "PathNormalizationTest" }

View File

@@ -65,6 +65,20 @@ async def redirect_302(request): # $ requestHandler
else:
raise web.HTTPFound(location="/logout") # $ HttpResponse HttpRedirectResponse mimetype=application/octet-stream redirectLocation="/logout"
################################################################################
# Cookies
################################################################################
@routes.get("/setting_cookie") # $ routeSetup="/setting_cookie"
async def setting_cookie(request): # $ requestHandler
resp = web.Response(text="foo") # $ HttpResponse mimetype=text/plain responseBody="foo"
resp.cookies["key"] = "value" # $ CookieWrite CookieName="key" CookieValue="value"
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
resp.set_cookie("key3", "value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
resp.set_cookie(name="key3", value="value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
resp.del_cookie("key4") # $ CookieWrite CookieName="key4"
return resp
if __name__ == "__main__":
app = web.Application()

View File

@@ -103,3 +103,17 @@ class CustomJsonResponse(JsonResponse):
def safe__custom_json_response(request):
return CustomJsonResponse("ACME Responses", {"foo": request.GET.get("foo")}) # $HttpResponse mimetype=application/json MISSING: responseBody=Dict SPURIOUS: responseBody="ACME Responses"
################################################################################
# Cookies
################################################################################
def setting_cookie(request):
resp = HttpResponse() # $ HttpResponse mimetype=text/html
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
return resp

View File

@@ -184,6 +184,20 @@ def redirect_simple(): # $requestHandler
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
################################################################################
# Cookies
################################################################################
@app.route("/setting_cookie") # $routeSetup="/setting_cookie"
def setting_cookie(): # $requestHandler
resp = make_response() # $ HttpResponse mimetype=text/html
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
resp.headers.add("Set-Cookie", "key2=value2") # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
resp.delete_cookie("key3") # $ CookieWrite CookieName="key3"
resp.delete_cookie(key="key3") # $ CookieWrite CookieName="key3"
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
################################################################################

View File

@@ -0,0 +1,23 @@
from pathlib import Path, PosixPath, WindowsPath
p = Path("filepath")
posix = PosixPath("posix/filepath")
windows = WindowsPath("windows/filepath")
p.chmod(0o777) # $ getAPathArgument=p
posix.chmod(0o777) # $ getAPathArgument=posix
windows.chmod(0o777) # $ getAPathArgument=windows
with p.open() as f: # $ getAPathArgument=p
f.read()
p.write_bytes(b"hello") # $ getAPathArgument=p fileWriteData=b"hello"
p.write_text("hello") # $ getAPathArgument=p fileWriteData="hello"
p.open("wt").write("hello") # $ getAPathArgument=p fileWriteData="hello"
name = windows.parent.name
o = open
o(name) # $ getAPathArgument=name
wb = p.write_bytes
wb(b"hello") # $ getAPathArgument=p fileWriteData=b"hello"

View File

@@ -1,39 +1,29 @@
import builtins
import io
open("filepath") # $getAPathArgument="filepath"
open(file="filepath") # $getAPathArgument="filepath"
open("filepath") # $ getAPathArgument="filepath"
open(file="filepath") # $ getAPathArgument="filepath"
o = open
o("filepath") # $getAPathArgument="filepath"
o(file="filepath") # $getAPathArgument="filepath"
o("filepath") # $ getAPathArgument="filepath"
o(file="filepath") # $ getAPathArgument="filepath"
builtins.open("filepath") # $getAPathArgument="filepath"
builtins.open(file="filepath") # $getAPathArgument="filepath"
builtins.open("filepath") # $ getAPathArgument="filepath"
builtins.open(file="filepath") # $ getAPathArgument="filepath"
io.open("filepath") # $getAPathArgument="filepath"
io.open(file="filepath") # $getAPathArgument="filepath"
io.open("filepath") # $ getAPathArgument="filepath"
io.open(file="filepath") # $ getAPathArgument="filepath"
from pathlib import Path, PosixPath, WindowsPath
f = open("path") # $ getAPathArgument="path"
f.write("foo") # $ getAPathArgument="path" fileWriteData="foo"
lines = ["foo"]
f.writelines(lines) # $ getAPathArgument="path" fileWriteData=lines
p = Path("filepath")
posix = PosixPath("posix/filepath")
windows = WindowsPath("windows/filepath")
p.chmod(0o777) # $getAPathArgument=p
posix.chmod(0o777) # $getAPathArgument=posix
windows.chmod(0o777) # $getAPathArgument=windows
def through_function(open_file):
open_file.write("foo") # $ fileWriteData="foo" getAPathArgument="path"
with p.open() as f: # $getAPathArgument=p
f.read()
p.write_bytes(b"hello") # $getAPathArgument=p
name = windows.parent.name
o(name) # $getAPathArgument=name
wb = p.write_bytes
wb(b"hello") # $getAPathArgument=p
through_function(f)

View File

@@ -0,0 +1,45 @@
import logging
# this bit just included to make this file runable
logging.basicConfig(level=logging.DEBUG)
password = "<pass>"
msg = "foo %s"
LOGGER = logging.getLogger("LOGGER")
logging.info(msg, password) # $ loggingInput=msg loggingInput=password
logging.info(msg="hello") # $ loggingInput="hello"
logging.log(logging.INFO, msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.log(logging.INFO, msg, password) # $ loggingInput=msg loggingInput=password
logging.root.info(msg, password) # $ loggingInput=msg loggingInput=password
# test of all levels
logging.critical(msg, password) # $ loggingInput=msg loggingInput=password
logging.fatal(msg, password) # $ loggingInput=msg loggingInput=password
logging.error(msg, password) # $ loggingInput=msg loggingInput=password
logging.warning(msg, password) # $ loggingInput=msg loggingInput=password
logging.warn(msg, password) # $ loggingInput=msg loggingInput=password
logging.info(msg, password) # $ loggingInput=msg loggingInput=password
logging.debug(msg, password) # $ loggingInput=msg loggingInput=password
logging.exception(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.critical(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.fatal(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.error(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.warning(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.warn(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.info(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.debug(msg, password) # $ loggingInput=msg loggingInput=password
LOGGER.exception(msg, password) # $ loggingInput=msg loggingInput=password
# not sure how to make these print anything, but just to show that it works
logging.Logger("foo").info("hello") # $ loggingInput="hello"
class MyLogger(logging.Logger):
pass
MyLogger("bar").info("hello") # $ loggingInput="hello"

View File

@@ -58,6 +58,18 @@ class ExampleConnectionWrite(tornado.web.RequestHandler):
stream.write(b"foo stream") # $ MISSING: HttpResponse responseBody=b"foo stream"
stream.close()
################################################################################
# Cookies
################################################################################
class CookieWriting(tornado.web.RequestHandler):
def get(self): # $ requestHandler
self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo"
self.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
self.set_cookie(name="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
self.set_header("Set-Cookie", "key2=value2") # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
def make_app():
return tornado.web.Application(
[
@@ -66,6 +78,7 @@ def make_app():
(r"/ExampleRedirect", ExampleRedirect), # $ routeSetup="/ExampleRedirect"
(r"/ExampleConnectionWrite", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite"
(r"/ExampleConnectionWrite/(stream)", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite/(stream)"
(r"/CookieWriting", CookieWriting), # $ routeSetup="/CookieWriting"
],
debug=True,
)
@@ -74,6 +87,7 @@ def make_app():
if __name__ == "__main__":
import tornado.ioloop
print("running on http://localhost:8888/")
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

View File

@@ -43,16 +43,21 @@ class Redirect(Resource):
# requested with curl.
return b"hello" # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=b"hello"
################################################################################
# Cookies
################################################################################
class NonHttpBodyOutput(Resource):
class CookieWriting(Resource):
"""Examples of providing values in response that is not in the body
"""
def render_GET(self, request: Request): # $ requestHandler
request.responseHeaders.addRawHeader("key", "value")
request.setHeader("key2", "value")
request.addCookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
request.addCookie(k="key", v="value") # $ CookieWrite CookieName="key" CookieValue="value"
val = "key2=value"
request.cookies.append(val) # $ CookieWrite CookieRawHeader=val
request.addCookie("key", "value")
request.cookies.append(b"key2=value")
request.responseHeaders.addRawHeader("key", "value")
request.setHeader("Set-Cookie", "key3=value3") # $ MISSING: CookieWrite CookieRawHeader="key3=value3"
return b"" # $ HttpResponse mimetype=text/html responseBody=b""
@@ -62,7 +67,7 @@ root.putChild(b"also-now", AlsoNow())
root.putChild(b"later", Later())
root.putChild(b"plain-text", PlainText())
root.putChild(b"redirect", Redirect())
root.putChild(b"non-body", NonHttpBodyOutput())
root.putChild(b"setting_cookie", CookieWriting())
if __name__ == "__main__":

View File

@@ -0,0 +1,27 @@
edges
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password |
nodes
| test.py:19:16:19:29 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:20:48:20:55 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:22:58:22:65 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:23:58:23:65 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:27:40:27:47 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:30:58:30:65 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:34:30:34:39 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
#select
| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:22:58:22:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | $@ is logged here. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) |

View File

@@ -0,0 +1,46 @@
import logging
import sys
LOGGER = logging.getLogger("LOGGER")
def get_logger():
return LOGGER
def get_password():
return "<PASSWORD>"
def get_cert():
return "<CERT>"
def log_password():
password = get_password()
logging.info("logging.info Password '%s'", password) # NOT OK
LOGGER.log(logging.INFO, "LOGGER.log Password '%s'", password) # NOT OK
logging.root.info("logging.root.info Password '%s'", password) # NOT OK
# name of logger variable should not matter
foo = LOGGER
foo.info("foo.info Password '%s'", password) # NOT OK
# return value from function
get_logger().info("get_logger().info Password '%s'", password) # NOT OK
def log_cert():
logging.debug("Cert=%s", get_cert()) # NOT OK
def print_password():
print(get_password()) # NOT OK
sys.stdout.write(get_password()) # NOT OK
sys.stderr.write(get_password()) # NOT OK
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
log_password()
log_cert()
print_password()

View File

@@ -0,0 +1,13 @@
edges
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert |
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() |
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert |
nodes
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
| test.py:12:21:12:24 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:13:22:13:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:15:26:15:29 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
#select
| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |

View File

@@ -0,0 +1,15 @@
import pathlib
def get_cert():
return "<CERT>"
def write_password(filename):
cert = get_cert()
path = pathlib.Path(filename)
path.write_text(cert) # NOT OK
path.write_bytes(cert.encode("utf-8")) # NOT OK
path.open("w").write(cert) # NOT OK

View File

@@ -0,0 +1,20 @@
edges
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password |
| password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:9:17:9:29 | ControlFlowNode for List |
| test.py:9:17:9:29 | ControlFlowNode for List | test.py:10:25:10:29 | ControlFlowNode for lines |
nodes
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:9:17:9:29 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
#select
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |

View File

@@ -0,0 +1 @@
Security/CWE-312/CleartextStorage.ql

View File

@@ -6,12 +6,12 @@ app = Flask("Leak password")
def index():
password = request.args.get("password")
resp = make_response(render_template(...))
resp.set_cookie("password", password)
resp.set_cookie("password", password) # NOT OK
return resp
@app.route('/')
def index2():
password = request.args.get("password")
resp = Response(...)
resp.set_cookie("password", password)
resp.set_cookie("password", password) # NOT OK
return resp

View File

@@ -0,0 +1,10 @@
def get_cert():
return "<CERT>"
def write_cert(filename):
cert = get_cert()
with open(filename, "w") as file:
file.write(cert) # NOT OK
lines = [cert + "\n"]
file.writelines(lines) # NOT OK

View File

@@ -1,10 +0,0 @@
edges
| password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password |
| password_in_cookie.py:14:16:14:43 | a password | password_in_cookie.py:16:33:16:40 | a password |
| test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password |
| test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password |
| test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key |
#select
| test.py:8:35:8:42 | password | test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password | Sensitive data returned by $@ is logged here. | test.py:7:16:7:29 | get_password() | a call returning a password |
| test.py:14:30:14:39 | get_cert() | test.py:14:30:14:39 | a certificate or key | test.py:14:30:14:39 | a certificate or key | Sensitive data returned by $@ is logged here. | test.py:14:30:14:39 | get_cert() | a call returning a certificate or key |
| test.py:17:11:17:24 | get_password() | test.py:17:11:17:24 | a password | test.py:17:11:17:24 | a password | Sensitive data returned by $@ is logged here. | test.py:17:11:17:24 | get_password() | a call returning a password |

View File

@@ -1,12 +0,0 @@
edges
| password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password |
| password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password |
| password_in_cookie.py:14:16:14:43 | a password | password_in_cookie.py:16:33:16:40 | a password |
| password_in_cookie.py:14:16:14:43 | a password | password_in_cookie.py:16:33:16:40 | a password |
| test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password |
| test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key |
| test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key |
#select
| password_in_cookie.py:9:33:9:40 | password | password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password | Sensitive data from $@ is stored here. | password_in_cookie.py:7:16:7:43 | Attribute() | a request parameter containing a password |
| password_in_cookie.py:16:33:16:40 | password | password_in_cookie.py:14:16:14:43 | a password | password_in_cookie.py:16:33:16:40 | a password | Sensitive data from $@ is stored here. | password_in_cookie.py:14:16:14:43 | Attribute() | a request parameter containing a password |
| test.py:22:20:22:23 | cert | test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key | Sensitive data from $@ is stored here. | test.py:20:12:20:21 | get_cert() | a call returning a certificate or key |

View File

@@ -1 +0,0 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3

View File

@@ -1,22 +0,0 @@
#Don't import logging; it transitively imports a lot of stuff
def get_password():
pass
def log_password():
password = get_password()
logging.info("Password '%s'", password)
def get_cert():
pass
def log_cert():
logging.debug("Cert=%s", get_cert())
def print_password():
print(get_password())
def write_cert(filename):
cert = get_cert()
with open(filename, "w") as file:
file.write(cert)