Skip to content

Commit 12b36e1

Browse files
Lab deserialization: Allow more variation
Allow sub-conditions to be surrounded by parentheses. Signed-off-by: David A. Wheeler <[email protected]>
1 parent 992c8c3 commit 12b36e1

File tree

1 file changed

+66
-8
lines changed

1 file changed

+66
-8
lines changed

docs/labs/deserialization.html

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,40 @@
2626
\s* const data = JSON \. parse \( base64Decoded \) \; \s*
2727
</script>
2828
<script id="correct1" type="plain/text">
29-
\s* if \( data \. username && typeof\s+data \. username == ('string'|"string"|`string`) && data \. username \. length < 20 \) \{ \s*
29+
\s* if \( CONDALL \) \{ \s*
3030
</script>
3131

3232
<script id="info" type="application/yaml">
3333
---
34+
# Allow condition subexpressions to be optionally surrounded by parentheses
35+
# and allow the order to vary. This allows more real-world answers to be
36+
# considered acceptable.
37+
# Doing this is more easily done by buildigg up definitions,
38+
# which is annoying to write but general.
39+
definitions:
40+
- term: COND0
41+
value: |-
42+
data \. username
43+
- term: COND0
44+
value: |-
45+
(COND0|\( COND0 \))
46+
- term: COND1
47+
value: |-
48+
typeof\s+data \. username == ('string'|"string"|`string`)
49+
- term: COND1
50+
value: |-
51+
(COND1|\( COND1 \))
52+
- term: COND2
53+
value: |-
54+
data \. username \. length < 20
55+
- term: COND2
56+
value: |-
57+
(COND2|\( COND2 \))
58+
# Only the first one is likely, but we may as well allow both possibilities.
59+
# The first condition MUST be first because it checks if the value exists.
60+
- term: CONDALL
61+
value: |-
62+
(COND0 && (COND1 && COND2|COND2 && COND1))
3463
hints:
3564
- absent: |
3665
^ const data =
@@ -49,10 +78,15 @@
4978
text: JavaScript does not require semicolons at the end of a
5079
statement, but since the other statements terminate with semicolons,
5180
you should also terminate your statement with a semicolon to be consistent.
52-
- absent: |
81+
- absent: |-
5382
^ if \(
5483
index: 1
5584
text: The second section should start with `if (` followed by a condition.
85+
examples:
86+
-
87+
- const data = JSON.parse(base64Decoded);
88+
- |
89+
if data.username {
5690
- absent: |
5791
data \. username
5892
index: 1
@@ -73,11 +107,35 @@
73107
index: 1
74108
text: check if the length of the string is smaller than 20 characters.
75109
Use the expression `data.username.length &lt; 20` to determine this.
76-
- present: |
77-
(\&\&|\() \(
110+
- present: |-
111+
^ if \(
112+
absent: |-
113+
^ if \( data \. username &&
78114
index: 1
79-
text: For purposes of this lab, don't use extra parentheses
80-
around each term in the condition.
115+
text: Begin the second section with `if ( data.username && ... `
116+
because you must check if data is even present before you can check
117+
various attributes of that data.
118+
# examples:
119+
# -
120+
# - "const data = JSON.parse(base64Decoded);"
121+
# - "if (typeof data.username == 'string' && data.username.length < 20 && data.username) {"
122+
successes:
123+
-
124+
- const data = JSON.parse(base64Decoded);
125+
- if (data.username && typeof data.username == 'string' && data.username.length < 20) {
126+
-
127+
- const data = JSON . parse ( base64Decoded ) ;
128+
- if ( data . username && typeof data . username == 'string' && data . username.length < 20) {
129+
-
130+
- const data = JSON.parse(base64Decoded);
131+
- if (data.username && (typeof data.username == 'string') && (data.username.length < 20)) {
132+
-
133+
- const data = JSON.parse(base64Decoded);
134+
- if (data.username && typeof data.username == 'string' && (data.username.length < 20)) {
135+
failures:
136+
-
137+
- const data = JSON.parse(base64Decoded);
138+
- if (data.username && (typeof data.username == 'string')) && (data.username.length < 20)) {
81139
# debug: true
82140
</script>
83141
</head>
@@ -107,9 +165,9 @@ <h2>Task Information</h2>
107165
<p>
108166

109167
<p>
110-
The code below is called after an application login page. After login, a cookie is set up with the user profile, then in the homepage the cookie is deserialized and uses the username in a greeting message.
168+
The code below is called after an application login page. After login, a cookie is set up with the user profile, then in the homepage the cookie is deserialized and uses the username in a greeting message.
111169
<p>
112-
If you take a closer look at this code, you’ll see that it’s using <tt>eval()</tt> to deserialize the data from the cookie. This can be very dangerous as <tt>eval()</tt> evaluates a string as JavaScript code, which means any code inside that string will be executed, opening the possibility of Remote Code Execution (RCE) and Code Injection attacks.
170+
If you take a closer look at this code, you’ll see that it’s using <tt>eval()</tt> to deserialize the data from the cookie. This can be very dangerous as <tt>eval()</tt> evaluates a string as JavaScript code, which means any code inside that string will be executed, opening the possibility of Remote Code Execution (RCE) and Code Injection attacks.
113171
<p>
114172
For this lab we want to fix this by using an approach that prevents executing code from the attacker. We will also add some simple input validation to make sure the data we receive from inside the JSON data is what we are expecting.
115173
<ol>

0 commit comments

Comments
 (0)