|
7 | 7 | <link rel="stylesheet" href="checker.css"> |
8 | 8 | <script src="js-yaml.min.js"></script> |
9 | 9 | <script src="checker.js"></script> |
| 10 | +<script src="shell-injection.js"></script> |
10 | 11 | <link rel="license" href="https://creativecommons.org/licenses/by/4.0/"> |
11 | 12 |
|
12 | 13 | <!-- See create_labs.md for how to create your own lab! --> |
|
44 | 45 | \s* |
45 | 46 | </script> |
46 | 47 |
|
47 | | -<script id="info" type="application/yaml"> |
48 | | ---- |
49 | | -hints: |
50 | | -- absent: |- |
51 | | - ^[\n\r]*\x20\x20[^\x20] |
52 | | - text: > |
53 | | - Python is an indentation-sensitive language, so your indentation |
54 | | - must be consistent. |
55 | | - In this case, your line in the first section |
56 | | - must start with exactly 2 spaces followed by a non-space. |
57 | | -- absent: |- |
58 | | - ^\x20\x20[^\x20] |
59 | | - index: 1 |
60 | | - text: > |
61 | | - Python is an indentation-sensitive language, so your indentation |
62 | | - must be consistent. |
63 | | - In this case, your line in the second section |
64 | | - must start with exactly 2 spaces followed by |
65 | | - a non-space. |
66 | | -- absent: |- |
67 | | - re \. sub |
68 | | - text: > |
69 | | - Use re.sub(PATTERN, REPLACETEXT, dir_to_list) to |
70 | | - substitute anything that is |
71 | | - not an alphanumeric character (removing the rest). |
72 | | - examples: |
73 | | - - |
74 | | - - ' clean_dir = dir_to_list' |
75 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
76 | | -- absent: |- |
77 | | - clean_dir = re \. sub \( |
78 | | - present: |- |
79 | | - re \. sub |
80 | | - text: > |
81 | | - You need to compute a new string using re.sub and assign the result |
82 | | - to `clean_dir`. Your first line should look like |
83 | | - `clean_dir = re.sub(PATTERN, REPLACETEXT, dir_to_list)`. |
84 | | - examples: |
85 | | - - |
86 | | - - ' clean_dir re.sub = dir_to_list' |
87 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
88 | | -- present: PATTERN |
89 | | - text: > |
90 | | - We use `PATTERN` as a placeholder (metavariable) for the |
91 | | - expression you should use. The answer won't actually say PATTERN |
92 | | - anywhere. Your first line should look like |
93 | | - `clean_dir = re.sub(PATTERN, REPLACETEXT, dir_to_list)` |
94 | | - but `PATTERN` is a string with the regex of the pattern of text you |
95 | | - want to replace, and `REPLACETEXT` is what you want to replace it with. |
96 | | - The PATTERN would probably look like `r'...'` where the `...` |
97 | | - is the regular expression matching what you want to eliminate. |
98 | | - examples: |
99 | | - - |
100 | | - - " clean_dir = re.sub(PATTERN, PATTERN, dir_to_list)" |
101 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
102 | | -- absent: |- |
103 | | - re \. sub \( r |
104 | | - text: > |
105 | | - Python re.sub uses strings to indicate a regex pattern. |
106 | | - By convention these strings are usually 'raw' strings, so they |
107 | | - have the form `r'PATTERN'`. We would recommend that you use raw strings, |
108 | | - in the pattern |
109 | | - `re.sub(r'...', ...)` even though raw strings don't make this |
110 | | - *specific* example easier. |
111 | | -- absent: |- |
112 | | - re \. sub \( r['"] |
113 | | - text: > |
114 | | - Python re.sub uses strings to indicate a regex pattern. |
115 | | - By convention these strings usually 'raw' strings, so they |
116 | | - have the form `r'PATTERN'`. You have the "r" but not the following |
117 | | - single or double quote character. |
118 | | -- present: |- |
119 | | - re \. sub \( r?['"]\( |
120 | | - text: > |
121 | | - It is syntactically *legal* to use unnecessary parentheses in a |
122 | | - regular expression, e.g., `([^a-zA-Z0-9])`. However, it's usually best |
123 | | - to make regular expressions as simple as possible. So please don't use |
124 | | - unnecessary parentheses. |
125 | | - examples: |
126 | | - - |
127 | | - - " clean_dir = re.sub(r'([^a-zA-Z0-9])', '', dir_to_list)" |
128 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
129 | | -- absent: |- |
130 | | - re \. sub \( r?['"]\[ |
131 | | - text: > |
132 | | - Use re.sub(r'[...]', ...) to |
133 | | - indicate that you want to replace every character matching a |
134 | | - certain pattern. Note the square brackets in the regular expression. |
135 | | - Replace the `...` with the pattern of characters to be replaced. |
136 | | - examples: |
137 | | - - |
138 | | - - " clean_dir = re.sub(r'', '', dir_to_list)" |
139 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
140 | | -- absent: |- |
141 | | - re \. sub \( r?['"]\[\^ |
142 | | - text: > |
143 | | - Use re.sub(r'[^ALPHANUMERIC_PATTERN]', '', dir_to_list) to |
144 | | - indicate that you want to replace everything that is not |
145 | | - an alphanumeric character. Notice the use of the caret symbol `^`; |
146 | | - we are replacing everything *not* matching a certain pattern. |
147 | | - It's okay to use a caret here, because we aren't validating input, |
148 | | - we are filtering (removing) all the input *not* permitted. |
149 | | - Be sure to replace ALPHANUMERIC_PATTERN |
150 | | - with a regular expression pattern that describes alphanumerics! |
151 | | - examples: |
152 | | - - |
153 | | - - " clean_dir = re.sub(r'[a-zA-Z0-9]', '', dir_to_list)" |
154 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
155 | | -- absent: |- |
156 | | - a-zA-Z0-9 |
157 | | - text: >- |
158 | | - Use `a-zA-Z0-9` in your substitution pattern. |
159 | | - examples: |
160 | | - - |
161 | | - - " clean_dir = re.sub(r'[^]', '', dir_to_list)" |
162 | | - - ' subprocess.run(f"ls -l {dir_to_list}")' |
163 | | -- absent: |- |
164 | | - re \. sub \( r?('\[\^a-zA-Z0-9\]'|"\[\^a-zA-Z0-9\]") , r?(''|"") |
165 | | - text: > |
166 | | - The second parameter of `re.sub` should be an empty string, that is, |
167 | | - `''` or `""`. You are matching everything you don't want, and |
168 | | - replacing it with nothing at all. |
169 | | - examples: |
170 | | - - |
171 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', NOWWHAT, dir_to_list)" |
172 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
173 | | -- absent: "subprocess.run" |
174 | | - index: 1 |
175 | | - text: Use subprocess.run |
176 | | -- present: |- |
177 | | - shell = [Tt]rue |
178 | | - index: 1 |
179 | | - text: |- |
180 | | - Don't say `shell = True`; we don't want to unnecessarily run the shell. |
181 | | - examples: |
182 | | - - |
183 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
184 | | - - ' subprocess.run(f"ls -l {dir_to_list}", shell=True)' |
185 | | -- present: |- |
186 | | - f["']ls\s+-l |
187 | | - index: 1 |
188 | | - text: >- |
189 | | - You should generally avoid using string concatenation when creating |
190 | | - a command to execute. Formatted strings like f"..." are a form of |
191 | | - string concatenation. In addition, you MUST avoid string concatenation |
192 | | - in this case. The shell uses spaces to separate arguments, but we're |
193 | | - trying to avoid using the shell when it's not needed. |
194 | | - You must instead provide the arguments as a list that contains |
195 | | - separate parameters. The parameters should be something like |
196 | | - "ls", "-l", clean_dir |
197 | | - examples: |
198 | | - - |
199 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
200 | | - - ' subprocess.run(f"ls -l {dir_to_list}")' |
201 | | -- present: |- |
202 | | - ["']ls\s+-l |
203 | | - index: 1 |
204 | | - text: >- |
205 | | - The shell uses spaces to separate arguments, but we're |
206 | | - trying to avoid using the shell when it's not needed. |
207 | | - You must instead provide the arguments as a list that contains |
208 | | - separate parameters. The parameters should be something like |
209 | | - "ls", "-l", clean_dir |
210 | | - examples: |
211 | | - - |
212 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
213 | | - - ' subprocess.run("ls -l {dir_to_list}")' |
214 | | -- present: |- |
215 | | - subprocess \. run \( [A-Za-z0-9"'] |
216 | | - index: 1 |
217 | | - text: >- |
218 | | - The `subprocess.run` function takes a LIST of parameters as its command, |
219 | | - not just comma-separated parameters. |
220 | | - This means you need something like |
221 | | - the form `subprocess.run([P1, P2, ...])`. Note the square brackets |
222 | | - inside the parentheses. |
223 | | - examples: |
224 | | - - |
225 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
226 | | - - ' subprocess.run("ls", "-l", clean_dir)' |
227 | | -- present: |- |
228 | | - \{(dir_to_list|clean_dir)\} |
229 | | - index: 1 |
230 | | - text: >- |
231 | | - You don't need {...} in your result. |
232 | | - Each parameter should be free-standing, not an expression |
233 | | - concatenated within a formatted string. |
234 | | - examples: |
235 | | - - |
236 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
237 | | - - ' subprocess.run(["ls", "-l", {dir_to_list}])' |
238 | | -- present: |- |
239 | | - dir_to_list\" |
240 | | - index: 1 |
241 | | - text: >- |
242 | | - You have a double-quote after `dir_to_list`; you don't want that. |
243 | | -- present: |- |
244 | | - clean_dir\" |
245 | | - index: 1 |
246 | | - text: >- |
247 | | - You have a double-quote after `clean_dir`; you don't want that. |
248 | | -- present: |- |
249 | | - dir_to_list |
250 | | - index: 1 |
251 | | - text: >- |
252 | | - The parameter `dir_to_list` is what was provided, but you don't want |
253 | | - to use that. You want to use the cleaned value `clean_dir` instead. |
254 | | - examples: |
255 | | - - |
256 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
257 | | - - ' subprocess.run(["ls", "-l", dir_to_list])' |
258 | | -- absent: |- |
259 | | - run \(.*\) |
260 | | - index: 1 |
261 | | - text: >- |
262 | | - You need a pair of matching parentheses in the second section. |
263 | | - examples: |
264 | | - - |
265 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)" |
266 | | - - ' subprocess.run(["ls", "-l", clean_dir]' |
267 | | -- absent: |- |
268 | | - run \( \[.*\] |
269 | | - index: 1 |
270 | | - text: >- |
271 | | - You need a pair of matching square brackets in the second section. |
272 | | - examples: |
273 | | - - |
274 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)" |
275 | | - - ' subprocess.run(["ls", "-l", clean_dir)' |
276 | | -- absent: |- |
277 | | - ^ subprocess . run \( \[ ('ls'|"ls") , ('-l'|"-l") , clean_dir \] \) $ |
278 | | - index: 1 |
279 | | - text: >- |
280 | | - You are getting close. The `subprocess.run` line should look like |
281 | | - subprocess.run(["ls", "-l", clean_dir]) or similar. |
282 | | - examples: |
283 | | - - |
284 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)" |
285 | | - - ' subprocess.run(["ls", "-l", clean_dir, foo])' |
286 | | -successes: |
287 | | -- |
288 | | - - " clean_dir = re . sub( '[^a-zA-Z0-9]' , '' , dir_to_list )" |
289 | | - - ' subprocess . run ( [ "ls" , "-l" , clean_dir ] )' |
290 | | -- |
291 | | - - "\r\n\n clean_dir = re . sub( r'[^a-zA-Z0-9]' , '' , dir_to_list )" |
292 | | - - ' subprocess . run ( [ "ls" , "-l" , clean_dir ] )' |
293 | | -- |
294 | | - - " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)" |
295 | | - - ' subprocess.run(["ls", "-l", clean_dir], shell=False)' |
296 | | -failures: |
297 | | -# Newline in middle of assignment |
298 | | -- |
299 | | - - " clean_dir =\n re . sub( r'[^a-zA-Z0-9]' , '' , dir_to_list )" |
300 | | - - ' subprocess . run ( [ "ls" , "-l" , clean_dir ] )' |
301 | | -# Failure to indent |
302 | | -- |
303 | | - - "clean_dir = re . sub( r'[^a-zA-Z0-9]' , '' , dir_to_list )" |
304 | | - - 'subprocess . run ( [ "ls" , "-l" , clean_dir ] )' |
305 | | -# Indent too far |
306 | | -- |
307 | | - - " clean_dir = re . sub( r'[^a-zA-Z0-9]' , '' , dir_to_list )" |
308 | | - - ' subprocess . run ( [ "ls" , "-l" , clean_dir ] )' |
309 | | -</script> |
310 | 48 | </head> |
311 | 49 | <body> |
312 | 50 | <!-- For GitHub Pages formatting: --> |
|
0 commit comments