diff --git a/_posts/2023-09-09-sekai-scanner.md b/_posts/2023-09-09-sekai-scanner.md index 78ac298..cce8897 100644 --- a/_posts/2023-09-09-sekai-scanner.md +++ b/_posts/2023-09-09-sekai-scanner.md @@ -22,7 +22,7 @@ Here's what the scanner is doing internally: ```rb post '/' do input_service = escape_shell_input(params[:service]) -hostname, port = input_service.split ':', 2 +hostname, port = input_service.split ':', 2∑ begin if valid_ip? hostname and valid_port? port # Service up? diff --git a/_posts/2024-05-06-squ1rrel-personal-website.md b/_posts/2024-05-06-squ1rrel-personal-website.md index 8102702..38ac882 100644 --- a/_posts/2024-05-06-squ1rrel-personal-website.md +++ b/_posts/2024-05-06-squ1rrel-personal-website.md @@ -1,7 +1,7 @@ --- layout: post current: post -cover: assets/squ1rrel/nisala/personal-website/cover.png +cover: assets/squ1rrel/nisala/personal-website/cover.webp navigation: True title: "Personal Website" date: 2024-05-06 10:00:00 @@ -11,25 +11,27 @@ subclass: 'post' author: nisala --- -challenge description +Check out my personal website! I have a blog! + +This was the hardest web challenge in the CTF, with only two solves. My favorite part about this challenge is that it kinda "punishes" you for thinking like a CTF player. This challenge doesn't respond well to throwing tools at the problem. Instead, you have to really understand the technology and its shortcomings, and take a methodical approach that's specific to the challenge itself. ## Step 1: Getting our bearings This challenge has no source, so all we have to go off of is the website, https://blog.squ1rrel.dev. -TODO INSERT PHOTO OF SITE +![Image of the challenge website](/assets/squ1rrel/nisala/personal-website/challenge-site.png) -Let's start by identifying its technologies. Using the chrome extension Wappalyzer, we can see that the site is hosted on Firebase. I'm not entirely sure how this extension is figuring this out, but there are a number of possibilities, from the IP it's connecting to (the primary Firebase load balancer), to the fact that blog.squ1rrel.dev has a CNAME record to a web.app URL (Firebase Hosting's subdomain). +Let's start by identifying its technologies. Using the Chrome extension Wappalyzer, we can see that the site is hosted on Firebase. I'm not entirely sure how the extension is figuring this out, but there are a number of possibilities, from the IP it's connecting to (an easily-identifiable Firebase load balancer), to the fact that blog.squ1rrel.dev has a CNAME record to a web.app URL (Firebase Hosting's subdomain). We can also see that the challenge very clearly wants us to look at cloud storage. The blog post only has one image, and it's being loaded in from Firebase storage. The blog post also says they have "more in storage". So, let's do that. -TODO INSERT IMAGE +![Storage link in HTML](/assets/squ1rrel/nisala/personal-website/storage.png) ## Step 2: Authentication There are two layers of authentication in this challenge -- authentication with Firebase as a web app, and authentication with Firebase as a user. Let's start with app authentication. -In order for Firebase to know what app we're referencing, we need to pass it a config, which contains an API key and various access URLs. Thankfully, because this site is hosted on Firebase, that's easy to get. It's always at https://blog.squ1rrel.dev/__/firebase/init.json (among other places in these reserved URLs). +In order for Firebase to know what app we're referencing, we need to pass it a config, which contains an API key and various access URLs. Thankfully, because this site is hosted on Firebase, that's easy to get. It's always at `https://blog.squ1rrel.dev/__/firebase/init.json` (among other places in these reserved URLs). ```js const firebaseConfig = { @@ -51,9 +53,11 @@ const auth = getAuth(); await createUserWithEmailAndPassword(auth, "test@user.com", "password"); ``` +And we're authenticated! + ## Step 3: Storage -And we're fully authenticated! Now, it's time to get our files. Firebase Storage does technically have a way to stop users from enumerating the files in a storage bucket, but most people don't configure it. Instead, they just mark the bucket as "read-only", not realizing that "read" permissions also for some reason include "list" permissions. Thus, we can list the files in this bucket. +Now, it's time to get our files. Firebase Storage does technically have a way to stop users from enumerating the files in a storage bucket, but most people don't configure it. Instead, they just mark the bucket as "read-only", not realizing that "read" permissions also for some reason include "list" permissions. Thus, we can list the files in this bucket. ```js const storage = getStorage(app); @@ -95,4 +99,4 @@ for (let i = 0; i < flag.length; ++i) { If the `set` fails, that means we guessed the wrong letter and need to try again. But if it succeeds, the letter is correct and we can move onto the next one. -And with that, we have the flag! \ No newline at end of file +And with that, we have the flag! `squ1rrel{fIrebas3_hAs_s0me_interesting_qu1rks}` \ No newline at end of file diff --git a/assets/squ1rrel/nisala/personal-website/challenge-site.png b/assets/squ1rrel/nisala/personal-website/challenge-site.png new file mode 100644 index 0000000..5723098 Binary files /dev/null and b/assets/squ1rrel/nisala/personal-website/challenge-site.png differ diff --git a/assets/squ1rrel/nisala/personal-website/cover.webp b/assets/squ1rrel/nisala/personal-website/cover.webp new file mode 100644 index 0000000..e46f484 Binary files /dev/null and b/assets/squ1rrel/nisala/personal-website/cover.webp differ diff --git a/assets/squ1rrel/nisala/personal-website/storage.png b/assets/squ1rrel/nisala/personal-website/storage.png new file mode 100644 index 0000000..e4142d8 Binary files /dev/null and b/assets/squ1rrel/nisala/personal-website/storage.png differ