diff --git a/_posts/2024-05-06-squ1rrel-mutex-lock.md b/_posts/2024-05-06-squ1rrel-mutex-lock.md index 52e0bd9..ef1d8e4 100644 --- a/_posts/2024-05-06-squ1rrel-mutex-lock.md +++ b/_posts/2024-05-06-squ1rrel-mutex-lock.md @@ -1,7 +1,7 @@ --- layout: post current: post -cover: assets/squ1rrel/nisala/mutex-lock/cover.png +cover: assets/squ1rrel/nisala/mutex-lock/cover.webp navigation: True title: "Mutex Lock" date: 2024-05-06 09:59:00 @@ -11,13 +11,15 @@ subclass: 'post' author: nisala --- -challenge description +just solved distributed systems + +This challenge was the second hardest in web, with ten solves. As I discuss later in this writeup, I wrote this challenge in response to new trends in web security. Backdoored and malicious packages are becoming increasingly common, especially in the npm ecosystem. [Entire companies](https://socket.dev) have been created to help identify these problems, and yet I've never seen a challenge with one in a CTF before. ## Step 1: Getting our bearings -In this challenge, we're presented with a simple "web mutex" interface, that allows us to create and lock a mutex, and unlock it given the pasword we got when we acquired the lock. +In this challenge, we're presented with a simple "web mutex" interface. The interface allows us to create and lock a mutex, and unlock it given the pasword we got when we acquired the lock. -TODO INSERT IMAGE +![Image of the challenge website](/assets/squ1rrel/nisala/mutex-lock/challenge-site.png) Now, as far as I can tell, there's nothing exploitable at all in this -- the operations are very simple, and there's nothing nefarious going on. The flag is stored in the env, but there's no way to get to it using this simple web server code. @@ -25,19 +27,19 @@ Now, as far as I can tell, there's nothing exploitable at all in this -- the ope However, if you look in the frontend source, you'll see something very curious: a button that takes you to `/flag`. What happens when you go there? -TODO IMAGE OF NOT FOUND +![Browser standard 404 page](/assets/squ1rrel/nisala/mutex-lock/remoteflagnotfound.png) A "Not Found" page. Boring, right? But what if you go to another URL that shouldn't exist, like `/asdf`? -TODO IMAGE OF ACTUAL 404 PAGE +![Express 404 page](/assets/squ1rrel/nisala/mutex-lock/remoteothernotfound.png) The 404 page is different... but the `/flag` route isn't in the provided source. What's going on? Another way to discover this is by running the web server locally. If you download the ZIP file and run `npm install` and then `node index.js`, and go to `localhost:3000/flag`, here's what you see. -TOOD IMAGE OF NORMAL 404 PAGE +![Express 404 page](/assets/squ1rrel/nisala/mutex-lock/localflagnotfound.png) -Okay, something really weird is going on. This is a normal 404 page. The tampering is gone! +Okay, something really weird is going on. This is a normal Express 404 page. The tampering is gone! Clearly, something must've changed in the install step. At this point, there are two ways you might notice what's going on: @@ -46,9 +48,9 @@ Clearly, something must've changed in the install step. At this point, there are ## Step 3: Exploiting the dependency -Diffing `package-lock.json` will show that `express`, despite what `package.json` is telling you, isn't coming from NPM -- it's coming from GitHub. This is an issue with NPM. Although typically, when you install a package from GitHub, the source will show up in `package.json`, it isn't *required* to be there to pass validation when doing a clean install. You can replace it with a simple version number, like it would be with an installation from the NPM registry, and as long as the `package-lock.json` is still there, it'll keep silently installing from GitHub. Even `npm audit` won't show that this is secretly happening -- in fact, there are [companies dedicated to finding hidden exploits like this!](https://socket.dev) +Diffing `package-lock.json` will show that `express`, despite what `package.json` is telling you, isn't coming from NPM -- it's coming from GitHub. This is an issue with NPM. Typically, when you install a package from GitHub, it'll show you it's from GitHub in `package.json`. However, it isn't *required* to be there to pass validation when doing a clean install. You can replace it with a simple version number, like it would be with an installation from the NPM registry, and as long as the `package-lock.json` is still there, it'll keep silently installing from GitHub. Even `npm audit` won't show that this is secretly happening. *This is a huge issue with npm.* -As an aside, GitHub doesn't even show `package-lock.json` diffs in PRs, calling them "too long". Without some external tool monitoring a project's `package-lock.json`, you could easily slip in your own version of a dependency in a routine PR, and create a backdoor that nobody would notice. Scary stuff, and we're already starting to see high-profile supply-chain attacks like this. I believe this is part of the future of web security and vulnerability analysis, which is what inspired me to write a challenge like this. +As an aside, GitHub doesn't even show `package-lock.json` diffs in PRs, calling them "too long". Without some external tool monitoring a project's `package-lock.json`, you could easily slip in your own version of a dependency in a routine PR, and create a backdoor that nobody would notice. Scary stuff, and we're already starting to see high-profile supply-chain attacks like this. I believe this is part of the future of web security and vulnerability analysis, which, again, is what inspired me to write a challenge like this. Anyways, here's the diff you'll see: @@ -61,8 +63,8 @@ Anyways, here's the diff you'll see: If we go to this commit of this repo, what do we find? -TODO INSERT DIFF +![Diff showing modified code in express package](/assets/squ1rrel/nisala/mutex-lock/diff.png) Without the `pwd` parameter, we get a 404 page. But with it? -TODO INSERT IMAGE OF FLAG \ No newline at end of file +![Flag](/assets/squ1rrel/nisala/mutex-lock/flag.png) diff --git a/assets/squ1rrel/nisala/mutex-lock/challenge-site.png b/assets/squ1rrel/nisala/mutex-lock/challenge-site.png new file mode 100644 index 0000000..36ad9fe Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/challenge-site.png differ diff --git a/assets/squ1rrel/nisala/mutex-lock/cover.webp b/assets/squ1rrel/nisala/mutex-lock/cover.webp new file mode 100644 index 0000000..ff7e5b2 Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/cover.webp differ diff --git a/assets/squ1rrel/nisala/mutex-lock/diff.png b/assets/squ1rrel/nisala/mutex-lock/diff.png new file mode 100644 index 0000000..265be6a Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/diff.png differ diff --git a/assets/squ1rrel/nisala/mutex-lock/flag.png b/assets/squ1rrel/nisala/mutex-lock/flag.png new file mode 100644 index 0000000..d3dd014 Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/flag.png differ diff --git a/assets/squ1rrel/nisala/mutex-lock/localflagnotfound.png b/assets/squ1rrel/nisala/mutex-lock/localflagnotfound.png new file mode 100644 index 0000000..34dd481 Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/localflagnotfound.png differ diff --git a/assets/squ1rrel/nisala/mutex-lock/remoteflagnotfound.png b/assets/squ1rrel/nisala/mutex-lock/remoteflagnotfound.png new file mode 100644 index 0000000..8ddcb24 Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/remoteflagnotfound.png differ diff --git a/assets/squ1rrel/nisala/mutex-lock/remoteothernotfound.png b/assets/squ1rrel/nisala/mutex-lock/remoteothernotfound.png new file mode 100644 index 0000000..8ed3506 Binary files /dev/null and b/assets/squ1rrel/nisala/mutex-lock/remoteothernotfound.png differ