Python: Add modeling of http.server.BaseHTTPRequestHandler

This commit is contained in:
Rasmus Wriedt Larsen
2020-04-20 12:00:17 +02:00
parent 243dea706e
commit 26ed911bb2
5 changed files with 157 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
| test.py:16 | ok | taint_sources | self | BaseHTTPRequestHandlerKind |
| test.py:18 | ok | taint_sources | Attribute | externally controlled string |
| test.py:20 | ok | taint_sources | Attribute | externally controlled string |
| test.py:22 | ok | taint_sources | Attribute | {externally controlled string} |
| test.py:23 | ok | taint_sources | Subscript | externally controlled string |
| test.py:24 | ok | taint_sources | Attribute() | externally controlled string |
| test.py:25 | ok | taint_sources | Attribute() | [externally controlled string] |
| test.py:26 | fail | taint_sources | Attribute() | <NO TAINT> |
| test.py:27 | ok | taint_sources | Attribute() | [externally controlled string] |
| test.py:28 | fail | taint_sources | Attribute() | <NO TAINT> |
| test.py:29 | ok | taint_sources | Attribute() | externally controlled string |
| test.py:30 | ok | taint_sources | Attribute() | externally controlled string |
| test.py:31 | ok | taint_sources | str() | externally controlled string |
| test.py:32 | ok | taint_sources | bytes() | externally controlled string |
| test.py:34 | ok | taint_sources | Attribute | file[externally controlled string] |
| test.py:35 | ok | taint_sources | Attribute() | externally controlled string |

View File

@@ -0,0 +1,32 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.web.HttpRequest
import semmle.python.security.strings.Untrusted
from
Call call, Expr arg, boolean expected_taint, boolean has_taint, string test_res,
string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
(
call.getFunc().(Name).getId() = "ensure_tainted" and
expected_taint = true
or
call.getFunc().(Name).getId() = "ensure_not_tainted" and
expected_taint = false
) and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "<NO TAINT>" and
has_taint = false
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
) and
has_taint = true
) and
if expected_taint = has_taint then test_res = "ok " else test_res = "fail"
// if expected_taint = has_taint then test_res = "✓" else test_res = "✕"
select arg.getLocation().toString(), test_res, call.getScope().(Function).getName(), arg.toString(),
taint_string

View File

@@ -0,0 +1,54 @@
import sys
if sys.version_info[0] == 2:
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
if sys.version_info[0] == 3:
from http.server import HTTPServer, BaseHTTPRequestHandler
class MyHandler(BaseHTTPRequestHandler):
def taint_sources(self):
ensure_tainted(
self,
self.requestline,
self.path,
self.headers,
self.headers['Foo'],
self.headers.get('Foo'),
self.headers.get_all('Foo'),
self.headers.keys(),
self.headers.values(),
self.headers.items(),
self.headers.as_bytes(),
self.headers.as_string(),
str(self.headers),
bytes(self.headers),
self.rfile,
self.rfile.read(),
)
def do_GET(self):
# send_response will log a line to stderr
self.send_response(200)
self.send_header("Content-type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write(b"Hello BaseHTTPRequestHandler")
print(self.headers)
if __name__ == "__main__":
server = HTTPServer(("127.0.0.1", 8080), MyHandler)
server.serve_forever()
# Headers works case insensitvely, so self.headers['foo'] == self.headers['FOO']
# curl localhost:8080 --header "Foo: 1" --header "foo: 2"