hxp CTF 2021

Challenge
Category
Points

Log 4 Sanity Check

We could see that the vulnerable log4j library is used to log the user input when it is "wrong".

/* Decompiler 2ms, total 1137ms, lines 28 */
import java.util.Scanner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Vuln {
   public static void main(String[] var0) {
      try {
         Logger var1 = LogManager.getLogger(Vuln.class);
         System.out.println("What is your favourite CTF?");
         String var2 = (new Scanner(System.in)).next();
         if (var2.toLowerCase().contains("dragon")) {
            System.out.println("<3");
            System.exit(0);
         }

         if (var2.toLowerCase().contains("hxp")) {
            System.out.println(":)");
         } else {
            System.out.println(":(");
            var1.error("Wrong answer: {}", var2);
         }
      } catch (Exception var3) {
         System.err.println(var3);
      }

   }
}

I wasn't able to get full-on RCE, but information disclosure through this vector was sufficient! We could use ${env:FOO} to substitute the FOO environment variable into the URI.

We just have to start an LDAP server and listen for the queried URI.

hxp{Phew, I am glad I code everything in PHP anyhow :) - :( :( :(}

Shitty Blog

We could see that when inserting entries, the user_id is not validated. This is also directly substituted into the SQL query, allowing an SQL injection.

Interestingly, get_user uses $db->query, while delete_entry uses $db->exec. The exec() function allows multiline (stacked) queries, allowing us to use this RCE payload to upload a webshell.

The difficulty lies in bypassing the following validation to insert a custom $id from the session cookie.

Notice that in hash_hmac(), binary=true is set but crypt() is not binary safe - the function only processes the input string up to a null byte terminator!

It would therefore be trivial to find two $id numbers that produce the same $mac by bruteforcing - this happens when hash_hmac() returns a result starting with \x00.

Since this $mac corresponds to the case where hash_hmac() returns a result starting with \x00, we would be able to bypass the following validation by using this $mac value in our session cookie, while changing the $id value in our session cookie until its HMAC starts with \x00.

This can be done by appending different things to the end of the payload (after an SQL comment) until we get a valid value. This value will produce a crypt() result corresponding to the $mac found previously.

The full script to generate the exploit payload is as follows:

Once we obtain the payload, we first have to create an entry with the malicious user ID payload.

Next, we simply delete the created entry. This is when the user ID payload is substituted into the SQL query, causing a PHP file to be created.

Next, we simply have to visit our webshell to get the flag.

hxp{dynamically_typed_statically_typed_php_c_I_hate_you_all_equally__at_least_its_not_node_lol_:(}

Last updated

Was this helpful?