From 897de1968dfb5df0ea35219cc2a9956a60d1a815 Mon Sep 17 00:00:00 2001 From: Yan Date: Fri, 30 Aug 2024 23:35:56 -0700 Subject: [PATCH] add intro cmdi --- web-security/cmdi-ls-1/DESCRIPTION.md | 28 ++++++++++++++++++++++++ web-security/cmdi-ls-1/server | 31 +++++++++++++++++++++++++++ web-security/module.yml | 4 +++- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 web-security/cmdi-ls-1/DESCRIPTION.md create mode 100755 web-security/cmdi-ls-1/server diff --git a/web-security/cmdi-ls-1/DESCRIPTION.md b/web-security/cmdi-ls-1/DESCRIPTION.md new file mode 100644 index 0000000..9aaf7ce --- /dev/null +++ b/web-security/cmdi-ls-1/DESCRIPTION.md @@ -0,0 +1,28 @@ +The previous levels' path traversals happened because of a disconnect between at least two of the following: + +1. A lack of developer awareness of the true range of potential input that an attacker might send to their application (e.g., the concept of an attacker sending characters that have special meaning in paths). +2. The developer's understanding of how paths work in Linux (e.g., that `..` can occur anywhere, not just in the beginning). +3. A gap in the flow of a semantic understanding of developer intent between the server (where the implementation makes it clear that we only expect files under the `/challenge/files` directory to be served) and the filesystem (where `..` wreaks havok). + +Now, all this happened just with paths in the mix. +Imagine getting more crazy: interactions between the web server and the whole Linux shell! + +Depressingly often, developers rely on the command line shell to help with complex operations. +In these cases, a web server will execute a Linux command and use the command's results in its operation (a frequent usecase of this, for example, is the `Imagemagick` suite of commands that facilitate image processing). +Different languages have different ways to do this (the simplest way in Python is `os.system`, but we will mostly be interacting with the more advanced `subprocess.check_output`), but almost all suffer from the risk of _command injection_. + +In path traversal, the attacker sent an unexpected character (`.`) that caused the filesystem to do something unexpected to the developer (look in the parent directory). +The shell, similarly, is chock full of special characters that cause effects unintended by the developer, and the gap between what the developer intended and the reality of what the shell (or, in previous challenges, the file system) does holds all sorts of security issues. + +For example, consider the following Python snippet that runs a shell command: + +```console +os.system(f"echo Hello {word}") +``` + +The developer clearly intends the user to send something like `Hackers`, and the result to be something like the command `echo Hello Hackers`. +But the hacker might send _anything_ the code doesn't explicitly block. +Recall what you learned [Chaining](/linux-luminarium/chaining) module of the [Linux Luminarium](/linux-luminarium): what if the hacker sends something containing a `;`? + +In this level, we will explore this exact concept. +See if you can trick the level and leak the flag! diff --git a/web-security/cmdi-ls-1/server b/web-security/cmdi-ls-1/server new file mode 100755 index 0000000..015b79d --- /dev/null +++ b/web-security/cmdi-ls-1/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: +
+
+ Listing for: {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 b2d7ebb..eba560c 100644 --- a/web-security/module.yml +++ b/web-security/module.yml @@ -4,8 +4,10 @@ challenges: name: Path Traversal 1 - id: path-traversal-2 name: Path Traversal 2 +- id: cmdi-ls-1 + name: CMDi 1 - id: level-2 - name: CMDi + name: CMDi 2 description: Exploit a command injection vulnerability - id: level-3 name: Authentication Bypass