-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathtarslip.py
More file actions
129 lines (96 loc) · 3.45 KB
/
tarslip.py
File metadata and controls
129 lines (96 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/python
import tarfile
import os
import sys
unsafe_filename_tar = sys.argv[1]
safe_filename_tar = "safe_path.tar"
tar = tarfile.open(safe_filename_tar)
for entry in tar:
tar.extract(entry)
tar = tarfile.open(unsafe_filename_tar)
tar.extractall()
tar.close()
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
tar.extract(entry)
tar = tarfile.open(safe_filename_tar)
tar.extractall()
tar.close()
#Sanitized
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if os.path.isabs(entry.name) or ".." in entry.name:
raise ValueError("Illegal tar archive entry")
tar.extract(entry, "/tmp/unpack/")
#Part Sanitized
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if ".." in entry.name:
raise ValueError("Illegal tar archive entry")
tar.extract(entry, "/tmp/unpack/")
#Unsanitized members
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(members=tar)
#Sanitize members
def safemembers(members):
for info in members:
if os.path.isabs(info.name) or ".." in info.name:
raise
yield info
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(members=safemembers(tar))
# Wrong sanitizer (is missing not)
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if os.path.isabs(entry.name) or ".." in entry.name:
tar.extract(entry, "/tmp/unpack/")
# OK Sanitized using not
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if not (os.path.isabs(entry.name) or ".." in entry.name):
tar.extract(entry, "/tmp/unpack/")
# The following two variants are included by purpose, since by default there is a
# difference in handling `not x` and `not (x or False)` when overriding
# Sanitizer.sanitizingEdge. We want to ensure we handle both consistently.
# Not reported, although vulnerable to '..'
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if not (os.path.isabs(entry.name) or False):
tar.extract(entry, "/tmp/unpack/")
# Not reported, although vulnerable to '..'
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
if not os.path.isabs(entry.name):
tar.extract(entry, "/tmp/unpack/")
# Extraction filters
extraction_filter = "fully_trusted"
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(filter=extraction_filter) # unsafe
tar.close()
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
tar.extract(entry, filter=extraction_filter) # unsafe
extraction_filter = "data"
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(filter=extraction_filter) # safe
tar.close()
tar = tarfile.open(unsafe_filename_tar)
for entry in tar:
tar.extract(entry, filter=extraction_filter) # safe
extraction_filter = None
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(filter=extraction_filter) # unsafe
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(members=tar, filter=extraction_filter) # unsafe
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(members=safemembers(tar), filter=extraction_filter) # safe -- we assume `safemembers` makes up for the unsafe filter
import shutil
import subprocess
# shutil.unpack_archive
shutil.unpack_archive(unsafe_filename_tar, "out") # unsafe
shutil.unpack_archive("safe.tar", "out") # safe
# subprocess tar extraction
subprocess.run(["tar", "-xf", unsafe_filename_tar]) # unsafe
subprocess.check_call(["tar", "-xf", unsafe_filename_tar]) # unsafe
subprocess.run(["tar", "-xf", "safe.tar"]) # safe
subprocess.run(["echo", unsafe_filename_tar]) # safe - not a tar extraction