|
26 | 26 | \s* const data = JSON \. parse \( base64Decoded \) \; \s* |
27 | 27 | </script> |
28 | 28 | <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* |
30 | 30 | </script> |
31 | 31 |
|
32 | 32 | <script id="info" type="application/yaml"> |
33 | 33 | --- |
| 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)) |
34 | 63 | hints: |
35 | 64 | - absent: | |
36 | 65 | ^ const data = |
|
49 | 78 | text: JavaScript does not require semicolons at the end of a |
50 | 79 | statement, but since the other statements terminate with semicolons, |
51 | 80 | you should also terminate your statement with a semicolon to be consistent. |
52 | | -- absent: | |
| 81 | +- absent: |- |
53 | 82 | ^ if \( |
54 | 83 | index: 1 |
55 | 84 | 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 { |
56 | 90 | - absent: | |
57 | 91 | data \. username |
58 | 92 | index: 1 |
|
73 | 107 | index: 1 |
74 | 108 | text: check if the length of the string is smaller than 20 characters. |
75 | 109 | Use the expression `data.username.length < 20` to determine this. |
76 | | -- present: | |
77 | | - (\&\&|\() \( |
| 110 | +- present: |- |
| 111 | + ^ if \( |
| 112 | + absent: |- |
| 113 | + ^ if \( data \. username && |
78 | 114 | 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)) { |
81 | 139 | # debug: true |
82 | 140 | </script> |
83 | 141 | </head> |
@@ -107,9 +165,9 @@ <h2>Task Information</h2> |
107 | 165 | <p> |
108 | 166 |
|
109 | 167 | <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. |
111 | 169 | <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. |
113 | 171 | <p> |
114 | 172 | 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. |
115 | 173 | <ol> |
|
0 commit comments