|
1 | 1 | from aiohttp import web
|
2 | 2 |
|
3 |
| -async def test_heuristic_taint(request: web.Request): |
4 |
| - ensure_tainted( |
5 |
| - # see https://docs.aiohttp.org/en/stable/web_reference.html#request-and-base-request |
6 |
| - request, # $ tainted |
7 |
| - |
8 |
| - # yarl.URL (see `yarl` framework tests) |
9 |
| - request.url, # $ tainted |
10 |
| - request.url.human_repr(), # $ tainted |
11 |
| - request.rel_url, # $ tainted |
12 |
| - request.rel_url.human_repr(), # $ tainted |
13 |
| - |
14 |
| - request.forwarded, # $ tainted |
15 |
| - |
16 |
| - request.host, # $ tainted |
17 |
| - request.remote, # $ tainted |
18 |
| - request.path, # $ tainted |
19 |
| - request.path_qs, # $ tainted |
20 |
| - request.raw_path, # $ tainted |
21 |
| - |
22 |
| - # dict-like for captured parts of the URL |
23 |
| - request.match_info, # $ tainted |
24 |
| - request.match_info["key"], # $ tainted |
25 |
| - request.match_info.get("key"), # $ tainted |
26 |
| - |
27 |
| - # multidict.MultiDictProxy[str] (see `multidict` framework tests) |
28 |
| - request.query, # $ tainted |
29 |
| - request.query.getone("key"), # $ tainted |
30 |
| - |
31 |
| - # multidict.CIMultiDictProxy[str] (see `multidict` framework tests) |
32 |
| - request.headers, # $ tainted |
33 |
| - request.headers.getone("key"), # $ tainted |
34 |
| - |
35 |
| - |
36 |
| - |
37 |
| - # dict-like (readonly) |
38 |
| - request.cookies, # $ tainted |
39 |
| - request.cookies["key"], # $ tainted |
40 |
| - request.cookies.get("key"), # $ tainted |
41 |
| - request.cookies.keys(), # $ tainted |
42 |
| - request.cookies.values(), # $ tainted |
43 |
| - request.cookies.items(), # $ tainted |
44 |
| - list(request.cookies), # $ tainted |
45 |
| - iter(request.cookies), # $ tainted |
46 |
| - |
47 |
| - |
48 |
| - # aiohttp.StreamReader |
49 |
| - # see https://docs.aiohttp.org/en/stable/streams.html#aiohttp.StreamReader |
50 |
| - request.content, # $ tainted |
51 |
| - await request.content.read(), # $ tainted |
52 |
| - await request.content.readany(), # $ tainted |
53 |
| - await request.content.readexactly(42), # $ tainted |
54 |
| - await request.content.readline(), # $ tainted |
55 |
| - await request.content.readchunk(), # $ tainted |
56 |
| - (await request.content.readchunk())[0], # $ tainted |
57 |
| - [line async for line in request.content], # $ tainted |
58 |
| - [data async for data in request.content.iter_chunked(1024)], # $ tainted |
59 |
| - [data async for data in request.content.iter_any()], # $ tainted |
60 |
| - [data async for data, _ in request.content.iter_chunks()], # $ tainted |
61 |
| - request.content.read_nowait(), # $ tainted |
62 |
| - |
63 |
| - # aiohttp.StreamReader |
64 |
| - request._payload, # $ tainted |
65 |
| - await request._payload.readany(), # $ tainted |
66 |
| - |
67 |
| - request.content_type, # $ tainted |
68 |
| - request.charset, # $ tainted |
69 |
| - |
70 |
| - request.http_range, # $ tainted |
71 |
| - |
72 |
| - # Optional[datetime] |
73 |
| - request.if_modified_since, # $ tainted |
74 |
| - request.if_unmodified_since, # $ tainted |
75 |
| - request.if_range, # $ tainted |
76 |
| - |
77 |
| - request.clone(scheme="https"), # $ tainted |
78 |
| - |
79 |
| - # asyncio.Transport |
80 |
| - # https://docs.python.org/3/library/asyncio-protocol.html#asyncio-transport |
81 |
| - # example given in https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.BaseRequest.transport |
82 |
| - # uses `peername` to get IP address of client |
83 |
| - request.transport, # $ tainted |
84 |
| - request.transport.get_extra_info("key"), # $ MISSING: tainted |
85 |
| - |
86 |
| - # Like request.transport.get_extra_info |
87 |
| - request.get_extra_info("key"), # $ tainted |
88 |
| - |
89 |
| - # Like request.transport.get_extra_info |
90 |
| - request.protocol.transport.get_extra_info("key"), # $ MISSING: tainted |
91 |
| - |
92 |
| - # bytes |
93 |
| - await request.read(), # $ tainted |
94 |
| - |
95 |
| - # str |
96 |
| - await request.text(), # $ tainted |
97 |
| - |
98 |
| - # obj |
99 |
| - await request.json(), # $ tainted |
100 |
| - |
101 |
| - # aiohttp.multipart.MultipartReader |
102 |
| - await request.multipart(), # $ tainted |
103 |
| - |
104 |
| - # multidict.MultiDictProxy[str] (see `multidict` framework tests) |
105 |
| - await request.post(), # $ tainted |
106 |
| - (await request.post()).getone("key"), # $ tainted |
107 |
| - ) |
108 |
| - |
109 |
| - # things that are technically controlled by sender of request, |
110 |
| - # but doesn't seem that likely for exploitation. |
111 |
| - ensure_not_tainted( |
112 |
| - request.method, |
113 |
| - request.version, |
114 |
| - request.scheme, |
115 |
| - request.secure, |
116 |
| - request.keep_alive, |
117 |
| - |
118 |
| - request.content_length, |
119 |
| - request.body_exists, |
120 |
| - request.has_body, |
121 |
| - request.can_read_body, |
122 |
| - ) |
123 |
| - |
124 |
| - ensure_not_tainted( |
125 |
| - request.loop, |
126 |
| - |
127 |
| - request.app, |
128 |
| - request.config_dict, |
129 |
| - ) |
130 |
| - |
131 |
| - |
132 | 3 | async def test_taint(request: web.Request): # $ requestHandler
|
133 | 4 |
|
134 | 5 | ensure_tainted(
|
@@ -271,6 +142,17 @@ def get(self): # $ requestHandler
|
271 | 142 | self.request.url # $ tainted
|
272 | 143 | )
|
273 | 144 |
|
| 145 | +# not a request handler, and not called, btu since we have type-annotation, should be a |
| 146 | +# remote-flow-source. |
| 147 | +async def test_heuristic_taint(request: web.Request): |
| 148 | + # picking out just a few of the tests from `test_taint` above, to show that we have |
| 149 | + # the same taint-steps :) |
| 150 | + ensure_tainted( |
| 151 | + request, # $ tainted |
| 152 | + request.url, # $ tainted |
| 153 | + await request.content.read(), # $ tainted |
| 154 | + ) |
| 155 | + |
274 | 156 |
|
275 | 157 | app = web.Application()
|
276 | 158 | app.router.add_get(r"/test_taint/{name}/{number:\d+}", test_taint) # $ routeSetup="/test_taint/{name}/{number:\d+}"
|
|
0 commit comments