This page looks best with JavaScript enabled

X-MAS CTF

 ·  ā˜• 3 min read

PHP Master

PHP Master

In this challenge we are given the following source code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

include('flag.php');

$p1 = $_GET['param1'];
$p2 = $_GET['param2'];

if(!isset($p1) || !isset($p2)) {
    highlight_file(__FILE__);
    die();
}

if(strpos($p1, 'e') === false && strpos($p2, 'e') === false  && strlen($p1) === strlen($p2) && $p1 !== $p2 && $p1[0] != '0' && $p1 == $p2) {
    die($flag);
}

?>

In order to get the flag we need to accomplish the next conditions:

  • Both parameters can’t contain the letter e
  • They must have the same length
  • Only one of them can start by 0
  • Parameters can’t be strictly identical (===), however they have to be equal (==).

To solve the challenge we have to do type juggling, it seems that cientific notation is blocked (0eX).
Before anything created a small sandbox to test out stuff
Firstly thought that it could be done with hexadecimal notation:
Hexadecimal type juggling

However it only works on PHP version 5. After searching for different type juggling payloads until I found this article:
Hexadecimal type juggling

As it only checks for lowercase “e” is still vulnerable:

[jusepe@nix:~]$ curl "http://challs.xmas.htsp.ro:3000/?param1=2E2&param2=200" && echo ""
X-MAS{s0_php_m4ny_skillz-69acb43810ed4c42}

Santa’s consolation

Santa&rsquo;s consolation

If we have a look at the source files, there is a javascript file called challenge.js with the following content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
console.log("%cā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–‘ā–ˆā–ˆā•—ā–‘ā–‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•—ā–‘ā–‘ā–‘ā–ˆā–ˆā•—ā–ˆā–ˆā•—ā–‘ā–‘ā–‘ā–ˆā–ˆā•—ā–ˆā–ˆā•—ā–‘ā–‘ā–ˆā–ˆā•—\n\ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā–‘ā–ˆā–ˆā•”ā•\nā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•¦ā•ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā•ā•ā–‘\nā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā–‘ā–‘ā–‘ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā–ˆā–ˆā•—ā–‘\nā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•¦ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā•šā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā•šā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā•‘ā–‘ā•šā–ˆā–ˆā•—\nā•šā•ā•ā•ā•ā•ā•ā–‘ā•šā•ā•ā•ā•ā•ā•ā•ā–‘ā•šā•ā•ā•ā•ā•ā•ā–‘ā–‘ā•šā•ā•ā•ā•ā•ā•ā–‘ā•šā•ā•ā–‘ā–‘ā•šā•ā•\n", "color: #5cdb95");
console.log("šŸ¢ Javascript Challenge šŸ¢");
console.log("Call win(<string>) with the correct parameter to get the flag");
console.log("And don't forget to subscribe to our newsletter :D");
function check(s) {
    const k = "MkVUTThoak44TlROOGR6TThaak44TlROOGR6TThWRE14d0hPMnczTTF3M056d25OMnczTTF3M056d1hPNXdITzJ3M00xdzNOenduTjJ3M00xdzNOendYTndFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYwRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOEZETXh3SE8ydzNNMXczTnp3bk4ydzNNMXczTnp3bk13RURmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmeUlUTThoak44TlROOGR6TThaak44TlROOGR6TThCVE14d0hPMnczTTF3M056d25OMnczTTF3M056dzNOeEVEZjRZRGZ6VURmM01EZjJZRGZ6VURmM01EZjFBVE04aGpOOE5UTjhkek04WmpOOE5UTjhkek04bFRPOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOGRUTzhoak44TlROOGR6TThaak44TlROOGR6TThSVE14d0hPMnczTTF3M056d25OMnczTTF3M056d1hPNXdITzJ3M00xdzNOenduTjJ3M00xdzNOenduTXlFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYzRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOGhETjhoak44TlROOGR6TThaak44TlROOGR6TThGak14d0hPMnczTTF3M056d25OMnczTTF3M056d25NeUVEZjRZRGZ6VURmM01EZjJZRGZ6VURmM01EZjFFVE04aGpOOE5UTjhkek04WmpOOE5UTjhkek04RkRNeHdITzJ3M00xdzNOenduTjJ3M00xdzNOendITndFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYxRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOFZETXh3SE8ydzNNMXczTnp3bk4ydzNNMXczTnp3WE94RURmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmeUlUTThoak44TlROOGR6TThaak44TlROOGR6TThkVE84aGpOOE5UTjhkek04WmpOOE5UTjhkek04WlRNeHdITzJ3M00xdzNOenduTjJ3M00xdzNOendITXhFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYza0RmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmMUVUTTAwMDBERVRDQURFUg==";
    const k1 = atob(k).split('').reverse().join('');
    return bobify(s) === k1;
}
function bobify(s) {
    if (~s.indexOf('a') || ~s.indexOf('t') || ~s.indexOf('e') || ~s.indexOf('i') || ~s.indexOf('z'))
        return "[REDACTED]";
    const s1 = s.replace(/4/g, 'a').replace(/3/g, 'e').replace(/1/g, 'i').replace(/7/g, 't').replace(/_/g, 'z').split('').join('[]');
    const s2 = encodeURI(s1).split('').map(c=>c.charCodeAt(0)).join('|');
    const s3 = btoa("D@\xc0\t1\x03\xd3M4" + s2);
    return s3;
}
function win(x) {
    return check(x) ? "X-MAS{" + x + "}" : "[REDACTED]";
}

There is a function win() that given a flag checks if it’s correct or not with the check() auxiliar function.

To get the flag we need to reverse bobify(), the expected string would be

REDACTED0000MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDk3fDM3fDUzfDY2fDM3fDUzfDY4fDExMHwzN3w1M3w2NnwzN3w1M3w2OHwxMTZ8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTd8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTIyfDM3fDUzfDY2fDM3fDUzfDY4fDExOXwzN3w1M3w2NnwzN3w1M3w2OHwxMDV8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDEwNHwzN3w1M3w2NnwzN3w1M3w2OHwxMDF8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDEyMnwzN3w1M3w2NnwzN3w1M3w2OHwxMjF8Mzd8NTN8NjZ8Mzd8NTN8Njh8NDh8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE3fDM3fDUzfDY2fDM3fDUzfDY4fDEyMnwzN3w1M3w2NnwzN3w1M3w2OHw5OXwzN3w1M3w2NnwzN3w1M3w2OHwxMTR8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTd8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTl8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTA1fDM3fDUzfDY2fDM3fDUzfDY4fDExN3wzN3w1M3w2NnwzN3w1M3w2OHwxMTB8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTIyfDM3fDUzfDY2fDM3fDUzfDY4fDEwMnwzN3w1M3w2NnwzN3w1M3w2OHwxMDF8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE0fDM3fDUzfDY2fDM3fDUzfDY4fDEwNXwzN3w1M3w2NnwzN3w1M3w2OHw5OXwzN3w1M3w2NnwzN3w1M3w2OHwxMDV8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE2

We can ignore the start because it is appending it :

1
const s3 = btoa("D@\xc0\t1\x03\xd3M4" + s2); // s3 = REDACTED0000 + s3

The steps to revert the function are:

  1. Transform the expected output from ascii to binary
  2. Remove all | that are concatened.
  3. Remove all 37,53, 66,68. They are added as [] then URL encoded (%5B%5D) and transformed into binary (375366375368)

To do so created a sample function:

1
2
3
4
5
6
7
function getSolution(){
  bin_flag = atob("MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDk3fDM3fDUzfDY2fDM3fDUzfDY4fDExMHwzN3w1M3w2NnwzN3w1M3w2OHwxMTZ8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTd8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTIyfDM3fDUzfDY2fDM3fDUzfDY4fDExOXwzN3w1M3w2NnwzN3w1M3w2OHwxMDV8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDEwNHwzN3w1M3w2NnwzN3w1M3w2OHwxMDF8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE1fDM3fDUzfDY2fDM3fDUzfDY4fDEyMnwzN3w1M3w2NnwzN3w1M3w2OHwxMjF8Mzd8NTN8NjZ8Mzd8NTN8Njh8NDh8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE3fDM3fDUzfDY2fDM3fDUzfDY4fDEyMnwzN3w1M3w2NnwzN3w1M3w2OHw5OXwzN3w1M3w2NnwzN3w1M3w2OHwxMTR8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTd8Mzd8NTN8NjZ8Mzd8NTN8Njh8OTl8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTA1fDM3fDUzfDY2fDM3fDUzfDY4fDExN3wzN3w1M3w2NnwzN3w1M3w2OHwxMTB8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTIyfDM3fDUzfDY2fDM3fDUzfDY4fDEwMnwzN3w1M3w2NnwzN3w1M3w2OHwxMDF8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE0fDM3fDUzfDY2fDM3fDUzfDY4fDEwNXwzN3w1M3w2NnwzN3w1M3w2OHw5OXwzN3w1M3w2NnwzN3w1M3w2OHwxMDV8Mzd8NTN8NjZ8Mzd8NTN8Njh8MTE2");
  filtered = bin_flag.split("|").filter(a => a !== "37").filter(a => a !== "53").filter(a => a !== "66").filter(a => a !== "68");
  ascii_flag = filtered.map(c=>String.fromCharCode(c)).join('');
  flag = ascii_flag.replace(/a/g, '4').replace(/e/g, '3').replace(/i/g, '1').replace(/t/g, '7').replace(/z/g, '_');
  return flag
}
Share on

ITasahobby
WRITTEN BY
ITasahobby
InTernet lover