Solving WarmUp from csictf CTF 2020

Posted on Wed 22 July 2020 in CTF by 0xshrimantyogi


The author note for WarmUp challenge from csictf CTF 2020.

1
2
3
If you know, you know; otherwise you might waste a lot of time.

http://chall.csivit.com:30272

Visiting the challenge URL I was presented with the following source code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
    if (isset($_GET['hash'])) {
        if ($_GET['hash'] === "10932435112") {
            die('Not so easy mate.');
        }

        $hash = sha1($_GET['hash']);
        $target = sha1(10932435112);
        if($hash == $target) {
            include('flag.php');
            print $flag;
        } else {
            print "csictf{loser}";
        }
    } else {
        show_source(__FILE__);
    }

?>

Now, lets understand the code first. We have to craft a URL with a parameter hash and its value which is not equal to the number 10932435112. This is mandatory in order to evade if loop at line 3. Next, the value of hash variable should be such, that its SHA1 hash and the SHA1 hash of 10932435112 is same. Only then we will be presented with the flag.

Hmm !!! This was tough and like the challenge quoted If you know, you know; otherwise you might waste a lot of time. So, by not knowing the solution I made up my mind to sacrifice lot of time :P

So after a lot of searching around I came across this concept called type juggling in PHP. More details about this can be found here. General idea is to find a number/string which is not equal to 10932435112 but whose sha1 hash matches sha1(10932435112). To understand why this kind of type juggling works we need to understand what the below SHA1 value is and how it is represented. This notation is called scientific notation.

1
sha1(10932435112) = 0e07766915004133176347055865026311692244

If we convert from scientific notation to decimal it becomes.

1
0e07766915004133176347055865026311692244 = 0 x 10^7766915004133176347055865026311692244 = 0

So now we need a number whose sha1 hash when converted to decimal will give us 0. A quick search landed me on 0e00000000000000000000081614617300000000 whose SHA1 value was as follows

1
sha1(0e00000000000000000000081614617300000000) = 0e65307525940999632287492285468259219070

So when the above hash value is converted to decimal it gave

1
0e65307525940999632287492285468259219070 = 0 x 10^65307525940999632287492285468259219070 = 0

All input provided in the $_GET superglobal variable is of the type string and due to the PHP's type juggling issue both strings are treated as floating point numbers written in scientific notation and when cast to float they both equal 0.

So the final payload becomes

1
http://chall.csivit.com:30272/?hash=0e00000000000000000000081614617300000000

and we get the flag...Happy ending :P

flag

Thanks for stopping by and reading and thanks csictf CTF team for the challenge

--0xshrimantyogi