From 136be9586bc11a06bdd0c0b53b714015acd21df5 Mon Sep 17 00:00:00 2001 From: Yan Date: Sat, 31 Aug 2024 00:07:06 -0700 Subject: [PATCH] awesome quote level --- web-security/cmdi-ls-quote/DESCRIPTION.md | 19 ++++++++++++++ web-security/cmdi-ls-quote/server | 31 +++++++++++++++++++++++ web-security/module.yml | 5 ++-- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 web-security/cmdi-ls-quote/DESCRIPTION.md create mode 100755 web-security/cmdi-ls-quote/server diff --git a/web-security/cmdi-ls-quote/DESCRIPTION.md b/web-security/cmdi-ls-quote/DESCRIPTION.md new file mode 100644 index 00000000..3bd433c5 --- /dev/null +++ b/web-security/cmdi-ls-quote/DESCRIPTION.md @@ -0,0 +1,19 @@ +An interesting thing about command injection is that you don't get to choose where in the command the injection occurs: the developer accidentally makes that choice for you when writing the program. +Sometimes, these injections occur in uncomfortable places. +Consider the following: + +```python +os.system(f"echo Hello '{word}'") +``` + +Here, the developer tried to convey to the shell that `word` should really be only one word. +The shell, when given arguments in single quotes, treats otherwise-special characters like `;`, `$`, and so on as just normal characters, until it hits the closing single quote (`'`). + +This level gives you this scenario. +Can you bypass it? + +---- +**HINT:** +Keep in mind that there will be a `'` character right at the end of whatever you inject. +In the shell, all quotes must be matched with a partner, or the command is invalid. +Make sure to craft your injection so that the resulting command is valid! diff --git a/web-security/cmdi-ls-quote/server b/web-security/cmdi-ls-quote/server new file mode 100755 index 00000000..f3aaaaa2 --- /dev/null +++ b/web-security/cmdi-ls-quote/server @@ -0,0 +1,31 @@ +#!/opt/pwn.college/python + +import subprocess +import flask +import os + +app = flask.Flask(__name__) + +@app.route("/", methods=["GET", "POST"]) +def challenge(): + directory = flask.request.args.get("directory", "/challenge") + listing = subprocess.run( + f"ls -l '{directory}'", # the command to run + shell=True, # use the shell to run this command + stdout=subprocess.PIPE, # capture the standard output + stderr=subprocess.STDOUT, # 2>&1 + encoding="latin" # capture the resulting output as text + ).stdout + + return f""" + + Welcome to the dirlister service! Please choose a directory to list the files of: +
+
+ Output of: ls -l '{directory}'
+
{listing.replace("\n", "
")}
+ + """ + +app.secret_key = open("/flag").read().strip() +app.run("challenge.localhost", int(os.environ.get("HTTP_PORT", 80))) diff --git a/web-security/module.yml b/web-security/module.yml index 04417275..4c7f07c8 100644 --- a/web-security/module.yml +++ b/web-security/module.yml @@ -8,9 +8,10 @@ challenges: name: CMDi 1 - id: cmdi-ls-pipe name: CMDi 2 -- id: level-2 +- id: cmdi-ls-quote name: CMDi 3 - description: Exploit a command injection vulnerability +- id: level-2 + name: CMDi 4 - id: level-3 name: Authentication Bypass description: Exploit an authentication bypass vulnerability