Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds reviewed files for the UTCTF 2024 challenge set, including challenge configurations, source code, documentation, and support files. The changes primarily involve adding new challenge implementations across multiple categories including crypto, forensics, web, and reverse engineering.
- Complete UTCTF 2024 challenge suite with module configuration and individual challenge files
- Challenge source code and supporting files for 22 different challenges
- Documentation files including descriptions, rehosting instructions, and setup notes
Reviewed Changes
Copilot reviewed 67 out of 86 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| utctf24/module.yml | Main module configuration defining all 22 challenges |
| utctf24/merger/merger.js | Object merging functionality with command execution |
| utctf24/merger/app.js | Express.js web application for company merger simulation |
| utctf24/simplesig/main | RSA signature generation service with validation |
| utctf24/numbrrrs2/main | Enhanced encryption service with key guessing game |
| utctf24/cookie/app | Flask application for cookie clicker game |
| utctf24/ccv/server | Credit card validation service |
| Various DESCRIPTION.md files | Challenge descriptions and setup instructions |
| Various REHOST.md files | Rehosting documentation for challenge deployment |
Comments suppressed due to low confidence (1)
| cmd = secret.cmd; | ||
| } | ||
|
|
||
|
|
||
| exec(cmd, (err, stdout, stderr) => { |
There was a problem hiding this comment.
This code allows command execution through the secret.cmd property which can be set via prototype pollution. The merger logic allows setting arbitrary properties on objects, including proto, which could be used to modify the secret object and inject arbitrary commands.
| cmd = secret.cmd; | |
| } | |
| exec(cmd, (err, stdout, stderr) => { | |
| if (typeof secret.cmd === 'string' && /^[a-zA-Z0-9_\-./]+$/.test(secret.cmd)) { | |
| cmd = secret.cmd; // Only allow safe commands | |
| } else { | |
| console.error("Invalid command in secret.cmd"); | |
| } | |
| } | |
| execFile(cmd, (err, stdout, stderr) => { |
| for (let k = 0; k < Math.min(data.attributes.length, data.values.length); k++) { | ||
|
|
||
| if (!(orig[data.attributes[k]] === undefined) && isObject(orig[data.attributes[k]]) && isObject(data.values[k])) { | ||
| for (const key in data.values[k]) { |
There was a problem hiding this comment.
This merge logic is vulnerable to prototype pollution. It allows merging objects without checking if the attribute is 'proto' or 'constructor', which can be exploited to modify the prototype chain and affect the global secret object.
| for (const key in data.values[k]) { | |
| for (const key in data.values[k]) { | |
| if (key === '__proto__' || key === 'constructor') { | |
| continue; | |
| } |
| app = Flask(__name__) | ||
|
|
||
| flag = open('/flag', 'r').read() | ||
| FLAG = "Wow, you beat me. Congrats! ", flag |
There was a problem hiding this comment.
The FLAG variable is defined as a tuple instead of a string concatenation. This will cause the response to be a tuple representation instead of the intended concatenated string message.
| FLAG = "Wow, you beat me. Congrats! ", flag | |
| FLAG = "Wow, you beat me. Congrats! " + flag |
| except: | ||
| return "Those aren't valid clicks..." | ||
|
|
||
| if count >= 1000000: |
There was a problem hiding this comment.
The frontend JavaScript checks for count >= 10000000 (10 million) but the backend only requires count >= 1000000 (1 million). This inconsistency could lead to confusion or unintended behavior.
| if count >= 1000000: | |
| if count >= 10000000: |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Second iteration, reviewed files