Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9336f4f

Browse files
committed
Considering the use of contextlib.closing() method
1 parent 2801b84 commit 9336f4f

3 files changed

Lines changed: 59 additions & 4 deletions

File tree

python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class UnsafeUnpackingConfig extends TaintTracking::Configuration {
3434
}
3535

3636
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
37-
// Writing the response data to the archive
3837
(
38+
// Writing the response data to the archive
3939
exists(Stdlib::FileLikeObject::InstanceSource is, Node f, MethodCallNode mc |
4040
is.flowsTo(f) and
4141
mc.getMethodName() = "write" and
@@ -48,11 +48,18 @@ class UnsafeUnpackingConfig extends TaintTracking::Configuration {
4848
exists(MethodCallNode mc |
4949
nodeFrom = mc.getObject() and
5050
mc.getMethodName() = "read" and
51-
nodeTo = mc
51+
mc.flowsTo(nodeTo)
5252
)
5353
or
5454
// Accessing the name
5555
exists(AttrRead ar | ar.accesses(nodeFrom, "name") and nodeTo = ar)
56+
or
57+
// Considering closing use
58+
exists(API::Node closing |
59+
closing = API::moduleImport("contextlib").getMember("closing") and
60+
closing.getACall().flowsTo(nodeTo) and
61+
nodeFrom = closing.getACall().getArg(0)
62+
)
5663
)
5764
}
5865
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
edges
22
| UnsafeUnpack.py:5:12:5:41 | ControlFlowNode for Attribute() | UnsafeUnpack.py:9:15:9:26 | ControlFlowNode for Attribute |
33
| UnsafeUnpack.py:9:15:9:26 | ControlFlowNode for Attribute | UnsafeUnpack.py:12:23:12:29 | ControlFlowNode for tarpath |
4+
| UnsafeUnpack.py:36:24:36:43 | ControlFlowNode for Attribute() | UnsafeUnpack.py:55:31:55:37 | ControlFlowNode for to_path |
45
nodes
56
| UnsafeUnpack.py:5:12:5:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
67
| UnsafeUnpack.py:9:15:9:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
78
| UnsafeUnpack.py:12:23:12:29 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
9+
| UnsafeUnpack.py:36:24:36:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
10+
| UnsafeUnpack.py:55:31:55:37 | ControlFlowNode for to_path | semmle.label | ControlFlowNode for to_path |
811
subpaths
912
#select
10-
| UnsafeUnpack.py:5:12:5:41 | ControlFlowNode for Attribute() | UnsafeUnpack.py:5:12:5:41 | ControlFlowNode for Attribute() | UnsafeUnpack.py:12:23:12:29 | ControlFlowNode for tarpath | Unsafe extraction from a malicious tarball, is used in a $@ | PathNode | during archive unpacking. |
13+
| UnsafeUnpack.py:12:23:12:29 | ControlFlowNode for tarpath | UnsafeUnpack.py:5:12:5:41 | ControlFlowNode for Attribute() | UnsafeUnpack.py:12:23:12:29 | ControlFlowNode for tarpath | Unsafe extraction from a malicious tarball retrieved from a remote location. |
14+
| UnsafeUnpack.py:55:31:55:37 | ControlFlowNode for to_path | UnsafeUnpack.py:36:24:36:43 | ControlFlowNode for Attribute() | UnsafeUnpack.py:55:31:55:37 | ControlFlowNode for to_path | Unsafe extraction from a malicious tarball retrieved from a remote location. |

python/ql/test/experimental/query-tests/Security/CWE-022/UnsafeUnpack.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,48 @@
99
f.write(response.raw.read())
1010

1111
untarredpath = "/tmp/tmp123"
12-
shutil.unpack_archive(tarpath, untarredpath)
12+
shutil.unpack_archive(tarpath, untarredpath)
13+
14+
15+
import tempfile
16+
import os
17+
from urllib import request
18+
import contextlib
19+
import shutil
20+
21+
unpack = True
22+
to_path = "/tmp/tmp123"
23+
uri = "https://www.goog.com/zzz.tar.gz"
24+
scheme = "https"
25+
26+
with tempfile.TemporaryDirectory() as temp_dir:
27+
if unpack and (str(uri).endswith("zip") or str(uri).endswith("tar.gz")):
28+
unpack_path = to_path
29+
to_path = temp_dir
30+
else:
31+
unpack_path = None
32+
if scheme in ["http", "https", "ftp"]:
33+
if os.path.isdir(to_path):
34+
to_path = os.path.join(to_path, os.path.basename(uri))
35+
url = uri
36+
url_response = request.urlopen(url)
37+
with contextlib.closing(url_response) as fp:
38+
with open(to_path, "wb") as out_file:
39+
block_size = DEFAULT_BUFFER_SIZE * 8
40+
while True:
41+
block = fp.read(block_size)
42+
if not block:
43+
break
44+
out_file.write(block)
45+
else:
46+
if scheme == "oci" and not storage_options:
47+
storage_options = default_signer()
48+
fs = fsspec.filesystem(scheme, **storage_options)
49+
if os.path.isdir(to_path):
50+
to_path = os.path.join(
51+
to_path, os.path.basename(str(uri).rstrip("/"))
52+
)
53+
fs.get(uri, to_path, recursive=True)
54+
if unpack_path:
55+
shutil.unpack_archive(to_path, unpack_path)
56+
to_path = unpack_path

0 commit comments

Comments
 (0)