Skip to content

Commit 0cb2e8e

Browse files
shell-injection: Eliminate YAML
Signed-off-by: David A. Wheeler <[email protected]>
1 parent f75462f commit 0cb2e8e

File tree

2 files changed

+246
-263
lines changed

2 files changed

+246
-263
lines changed

docs/labs/shell-injection.html

Lines changed: 1 addition & 263 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<link rel="stylesheet" href="checker.css">
88
<script src="js-yaml.min.js"></script>
99
<script src="checker.js"></script>
10+
<script src="shell-injection.js"></script>
1011
<link rel="license" href="https://creativecommons.org/licenses/by/4.0/">
1112

1213
<!-- See create_labs.md for how to create your own lab! -->
@@ -44,269 +45,6 @@
4445
\s*
4546
</script>
4647

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>
31048
</head>
31149
<body>
31250
<!-- For GitHub Pages formatting: -->

0 commit comments

Comments
 (0)