@@ -59,15 +59,52 @@ It can also intercept responses to ensure no schema data is being leaked in any
5959
6060** Which of the OWASP API Security Top 10 2019 issues does disabling introspection queries address?**
6161
62- _ Uncomment the line with your answer. _
62+ <!-- livebook:{"attrs":"eyJzb3VyY2UiOiIjIEdSQVBIUUw6MVxuXG5pbnB1dCA9IEtpbm8uSW5wdXQuc2VsZWN0KFwiQ2hvb3NlIHlvdXIgYW5zd2VyXCIsIFtcbiAgYTogXCJBUEk2XzIwMTlfTWFzc19Bc3NpZ25tZW50XCIsIFxuICBiOiBcIkFQSTEwXzIwMTlfSW5zdWZmaWNpZW50X0xvZ2dpbmdfTW9uaXRvcmluZ1wiLCBcbiAgYzogXCJBUEkzXzIwMTlfRXhjZXNzaXZlX0RhdGFfRXhwb3N1cmVcIixcbiAgZDogXCJBUEk0XzIwMTlfTGFja19vZl9SZXNvdXJjZXNfUmF0ZV9MaW1pdGluZ1wiXG5dKVxuXG5LaW5vLnJlbmRlcihpbnB1dClcblxuS2luby5JbnB1dC5yZWFkKGlucHV0KSJ9","chunks":null,"kind":"Elixir.GradingClient.GradedCell","livebook_object":"smart_cell"} -->
6363
6464``` elixir
65- # answer = :API6_2019_Mass_Assignment
66- # answer = :API10_2019_Insufficient_Logging_Monitoring
67- # answer = :API3_2019_Excessive_Data_Exposure
68- # answer = :API4_2019_Lack_of_Resources_Rate_Limiting
69-
70- IO .puts (answer)
65+ result =
66+ (
67+ input =
68+ Kino .Input .select (" Choose your answer" ,
69+ a: " API6_2019_Mass_Assignment" ,
70+ b: " API10_2019_Insufficient_Logging_Monitoring" ,
71+ c: " API3_2019_Excessive_Data_Exposure" ,
72+ d: " API4_2019_Lack_of_Resources_Rate_Limiting"
73+ )
74+
75+ Kino .render (input)
76+ Kino .Input .read (input)
77+ )
78+
79+ [module_id, question_id] =
80+ " # GRAPHQL:1\n\n input = Kino.Input.select(\" Choose your answer\" , [\n a: \" API6_2019_Mass_Assignment\" , \n b: \" API10_2019_Insufficient_Logging_Monitoring\" , \n c: \" API3_2019_Excessive_Data_Exposure\" ,\n d: \" API4_2019_Lack_of_Resources_Rate_Limiting\"\n ])\n\n Kino.render(input)\n\n Kino.Input.read(input)"
81+ |> String .split (" \n " , parts: 2 )
82+ |> hd ()
83+ |> String .trim_leading (" #" )
84+ |> String .split (" :" , parts: 2 )
85+
86+ module_id =
87+ case %{" ESCT" => ESCT , " GRAPHQL" => GRAPHQL , " OWASP" => OWASP }[String .trim (module_id)] do
88+ nil -> raise " invalid module id: #{ module_id } "
89+ module_id -> module_id
90+ end
91+
92+ question_id =
93+ case Integer .parse (String .trim (question_id)) do
94+ {id, " " } -> id
95+ _ -> raise " invalid question id: #{ question_id } "
96+ end
97+
98+ case GradingClient .check_answer (module_id, question_id, result) do
99+ :correct ->
100+ IO .puts ([IO .ANSI .green (), " Correct!" , IO .ANSI .reset ()])
101+
102+ {:incorrect , help_text} when is_binary (help_text) - >
103+ IO .puts ([IO .ANSI .red (), " Incorrect: " , IO .ANSI .reset (), help_text])
104+
105+ _ ->
106+ IO .puts ([IO .ANSI .red (), " Incorrect." , IO .ANSI .reset ()])
107+ end
71108```
72109
73110## Error Disclosure
@@ -88,58 +125,51 @@ OWASP recommends explicitly defining and enforcing all API response payload sche
88125
89126** Select the best example of a “good” error message, from the perspective of developer who is writing code that is intended to inform a user (who may or may not be a malicious actor) that the action they have attempted was unsuccessful:**
90127
91- _ Uncomment the item number (1-4) with your answer_
128+ <!-- livebook:{"attrs":"eyJzb3VyY2UiOiIjIEdSQVBIUUw6MlxuXG4jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiMgT3B0aW9uIDFcbiNcbiMgSFRUUC8yIDQwMSBVbmF1dGhvcml6ZWRcbiMgRGF0ZTogVHVlcywgMTYgQXVnIDIwMjIgMjE6MDY6NDIgR01UXG4jIOKAplxuIyB7XG4jIFx04oCcZXJyb3LigJ064oCddG9rZW4gZXhwaXJlZOKAnVxuIyB7XG4jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiMgT3B0aW9uIDJcbiNcbiMgSFRUUC8yIDIwMCBPS1xuIyBEYXRlOiBUdWVzLCAxNiBBdWcgMjAyMSAyMjowNjo0MiBHTVRcbiMg4oCmXG4jIHtcbiMgXHTigJxlcnJvcnPigJ06W1xuIyBcdFx0e1xuIyBcdFx0XHTigJxsb2NhdGlvbnPigJ06W1xuIyBcdFx0XHR7XG4jIFx0XHRcdFx04oCcY29sdW1u4oCdOjIsXG4jIFx0XHRcdFx0OmxpbmXigJ06MlxuIyBcdFx0XHR9XG4jIFx0XHRcdF0sXG4jIFx0XHRcdOKAnG1lc3NhZ2XigJ06IOKAnFBhcnNpbmcgZmFpbGVkIGF0XG4jIFx0XHR9XG4jIFx0XVxuIyB9XG4jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4jIE9wdGlvbiAzXG4jXG4jIEhUVFAvMiAyMDAgT0tcbiMgRGF0ZTogVHVlcywgMTYgQXVnIDIwMjIgMjE6MDY6NDIgR01UXG4jIOKAplxuIyB7XG4jIFx04oCcZXJyb3LigJ064oCdSUQgdG9rZW4gZm9yIHVzZXIgNTVlNGNiMDcgYXQgb3JnIDEyMzQgZXhwaXJlZOKAnVxuIyB7XG4jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIyBPcHRpb24gNFxuI1xuIyBIVFRQLzIgNDA0IEZpbGUgTm90IEZvdW5kXG4jIERhdGU6IFR1ZXMsIDE2IEF1ZyAyMDIyIDIxOjA2OjQyIEdNVFxuIyDigKZcbiMge1xuIyBcdOKAnGVycm9y4oCdOuKAnS93d3cvaG9tZS9maWxlLnR4dCBub3QgZm91bmQg4oCdXG4jIHtcbiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmlucHV0ID0gS2luby5JbnB1dC5zZWxlY3QoXCJDaG9vc2UgeW91ciBhbnN3ZXJcIiwgW1xuICBub25lOiBcIlwiLFxuICBhOiBcIk9wdGlvbiAxXCIsIFxuICBiOiBcIk9wdGlvbiAyXCIsIFxuICBjOiBcIk9wdGlvbiAzXCIsXG4gIGQ6IFwiT3B0aW9uIDRcIlxuXSwgZGVmYXVsdDogOm5vbmUpXG5cbktpbm8ucmVuZGVyKGlucHV0KVxuXG5LaW5vLklucHV0LnJlYWQoaW5wdXQpIn0","chunks":null,"kind":"Elixir.GradingClient.GradedCell","livebook_object":"smart_cell"} -->
92129
93130``` elixir
94- # -------------------------------------------------------------
95- # answer = 1
96- #
97- # HTTP/2 401 Unauthorized
98- # Date: Tues, 16 Aug 2022 21:06:42 GMT
99- # …
100- # {
101- # “error”:”token expired”
102- # {
103- # -------------------------------------------------------------
104- # answer = 2
105- #
106- # HTTP/2 200 OK
107- # Date: Tues, 16 Aug 2021 22:06:42 GMT
108- # …
109- # {
110- # “errors”:[
111- # {
112- # “locations”:[
113- # {
114- # “column”:2,
115- # :line”:2
116- # }
117- # ],
118- # “message”: “Parsing failed at
119- # }
120- # ]
121- # }
122- # --------------------------------------------------------------
123- # answer = 3
124- #
125- # HTTP/2 200 OK
126- # Date: Tues, 16 Aug 2022 21:06:42 GMT
127- # …
128- # {
129- # “error”:”ID token for user 55e4cb07 at org 1234 expired”
130- # {
131- # ---------------------------------------------------------------
132- # answer = 4
133- #
134- # HTTP/2 404 File Not Found
135- # Date: Tues, 16 Aug 2022 21:06:42 GMT
136- # …
137- # {
138- # “error”:”/www/home/file.txt not found ”
139- # {
140- # ---------------------------------------------------------------
141-
142- IO .puts (answer)
131+ result =
132+ (
133+ input =
134+ Kino .Input .select (
135+ " Choose your answer" ,
136+ [none: " " , a: " Option 1" , b: " Option 2" , c: " Option 3" , d: " Option 4" ],
137+ default: :none
138+ )
139+
140+ Kino .render (input)
141+ Kino .Input .read (input)
142+ )
143+
144+ [module_id, question_id] =
145+ "# GRAPHQL:2\n\n# -------------------------------------------------------------\n# Option 1\n#\n# HTTP/2 401 Unauthorized\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”token expired”\n# {\n# -------------------------------------------------------------\n# Option 2\n#\n# HTTP/2 200 OK\n# Date: Tues, 16 Aug 2021 22:06:42 GMT\n# …\n# {\n# \t“errors”:[\n# \t\t{\n# \t\t\t“locations”:[\n# \t\t\t{\n# \t\t\t\t“column”:2,\n# \t\t\t\t:line”:2\n# \t\t\t}\n# \t\t\t],\n# \t\t\t“message”: “Parsing failed at\n# \t\t}\n# \t]\n# }\n# --------------------------------------------------------------\n# Option 3\n#\n# HTTP/2 200 OK\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”ID token for user 55e4cb07 at org 1234 expired”\n# {\n# ---------------------------------------------------------------\n# Option 4\n#\n# HTTP/2 404 File Not Found\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”/www/home/file.txt not found ”\n# {\n# ---------------------------------------------------------------\n\ninput = Kino.Input.select(\"Choose your answer\", [\n none: \"\",\n a: \"Option 1\", \n b: \"Option 2\", \n c: \"Option 3\",\n d: \"Option 4\"\n], default: :none)\n\nKino.render(input)\n\nKino.Input.read(input)"
146+ |> String .split (" \n " , parts: 2 )
147+ |> hd ()
148+ |> String .trim_leading (" #" )
149+ |> String .split (" :" , parts: 2 )
150+
151+ module_id =
152+ case %{" ESCT" => ESCT , " GRAPHQL" => GRAPHQL , " OWASP" => OWASP }[String .trim (module_id)] do
153+ nil -> raise " invalid module id: #{ module_id } "
154+ module_id -> module_id
155+ end
156+
157+ question_id =
158+ case Integer .parse (String .trim (question_id)) do
159+ {id, " " } -> id
160+ _ -> raise " invalid question id: #{ question_id } "
161+ end
162+
163+ case GradingClient .check_answer (module_id, question_id, result) do
164+ :correct ->
165+ IO .puts ([IO .ANSI .green (), " Correct!" , IO .ANSI .reset ()])
166+
167+ {:incorrect , help_text} when is_binary (help_text) - >
168+ IO .puts ([IO .ANSI .red (), " Incorrect: " , IO .ANSI .reset (), help_text])
169+
170+ _ ->
171+ IO .puts ([IO .ANSI .red (), " Incorrect." , IO .ANSI .reset ()])
172+ end
143173```
144174
145175### Resources
0 commit comments