blog of bosh mainly cybersec

bcaCTF 2021 - Gerald Catalog

b1c and Rogue Waves merged for a big 1st place (W over both redpwn teams!!) in bcaCTF 2021.

Though the pwn curve was pretty sad, I also solved a web challenge, Gerald Catalog.

Gerald Catalog

Least solved challenge in the whole CTF!

The website we are given lets us view and create “Geralds”. Gerald is just an image (of a stegosaurus). Each Gerald has a title and a caption. There is a Gerald with the flag, and only the admin can see it. Our goal is to get the contents of the flag Gerald.

We are also allowed to opt into push notifications. When a Gerald is viewed, we can opt into getting push notifications for view events. Viewing a corresponding Gerald will cause a push notification to be sent to one’s browser, and a popup will be shown.

Read More

PlaidCTF 2021 - The Cobol Job

Even though I was going through some post-quarter-end burnout, I managed to join DiceGang for a bit during PlaidCTF 2021. We ended up getting 2nd, 1 place short of pre-qualifying for DEFCONCTF 2021 Finals :(

The Cobol Job

We are given a cobol program that lets us:

-----------------------
1 - Create file
2 - Open file
3 - Read file
4 - Write file
5 - Close file
6 - Copy file
7 - Exit
>

We can leak all the addresses including the base of libc by copying /proc/self/maps to a file we create, and then reading it.

Read More

picoCTF v8 exploitation, part 2

Previously, I went over how to turn an out of bounds read and write into shellcode execution in picoCTF 2021’s Download Horsepower.

However, that vulnerability was fairly contrived; generally, no sane developer would make a function to unsafely set arbitrary lengths of arrays.

It turns out that a lot of v8 exploitation is about tricking the v8 Just-In-Time (JIT) compiler, TurboFan, to make dangerous compiler optimizations which can lead to type confusion.

TurboFlan

The provided patch removes the calls to DeoptimizeIfNot(DeoptimizeReason::kWrongMap, ...); in EffectControlLinearizer::LowerCheckMaps().

v8 is known for its speed, and one way it achieves this is by optimizing hot functions, or functions that get called many times. If it gets called so many times, why not compile it and skip the interpretation each call?

However, such optimization presents the danger of confusing types in passed arguments. So, v8 also includes checks to verify the types of objects that are passed to a JITted function, among other checks too. If a check fails, the optimized code is considered unusable and is “deoptimized”, or thrown out.

The patch in TurboFlan basically removes the check that the maps are the same across function calls. If we get a function to be JITted that expects an argument of type a, and then give it an argument of type b, the function won’t be de-optimized and will treat the argument that is actually type b as type a.

Read More

picoCTF v8 exploitation, part 1

Even though I didn’t do the v8 pwns during the timeframe of the competition, I was interested in learning v8 exploitation and so I upsolved them.

This is the first time I’ve ever done any browser exploitation, and I hope that documenting my thought process will be a reference for future me. Perhaps one day I will look back at this writeup like I look at my writeup of my first heap challenge.

Download Horsepower

This was essentially the Four Function Heap version of v8 exploitation to me. I learned so much about how v8 objects are represented in memory (and how to corrupt them, of course).

Reading the patch, it is clear that they give us essentially an unlimited Out-Of-Bounds read/write in an array:

...
+namespace array {
+
+transitioning javascript builtin
+ArraySetHorsepower(
+  js-implicit context: NativeContext, receiver: JSAny)(horsepower: JSAny): JSAny {
+    try {
+      const h: Smi = Cast<Smi>(horsepower) otherwise End;
+      const a: JSArray = Cast<JSArray>(receiver) otherwise End;
+      a.SetLength(h);
+    } label End {
+        Print("Improper attempt to set horsepower");
+    }
+    return receiver;
+}
+}
...
Read More

ĂĄngstromCTF 2021

This past weekend I had the privilege of helping organize ĂĄngstromCTF 2021!

These are the solutions to my challenges.

Sea of Quills

From the app.rb, we can see that it filters our input in cols, limit, and offset. Because cols does not have a length check, we can simply bypass the blacklist.

We can find the name of the flag table by sending cols as name from sqlite_master union select name, flagtable. Some further digging shows that there is a column named flag.

Our final payload is:

cols: "flag FROM flagtable UNION SELECT name"
limit: "1"
offset: "0"

Flag: actf{and_i_was_doing_fine_but_as_you_came_in_i_watch_my_regex_rewrite_f53d98be5199ab7ff81668df}

Read More