Repo for my website
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
4.4 KiB

4 years ago
+++
author = "Maik de Kruif"
title = "Challenge 14 - AdventOfCTF"
date = 2020-12-14T19:45:51+01:00
description = "A writeup for challenge 14 of AdventOfCTF."
cover = "img/adventofctf/dd04640480d764ab09eea047cde749cd.png"
tags = [
"AdventOfCTF",
"challenge",
"ctf",
"hacking",
"writeup",
"web",
"php",
]
categories = [
"ctf",
"writeups",
"hacking",
]
+++
- Points: 1400
## Description
We are testing a new 2-factor security system for Santa's deepest secrets. It should be pretty secure!
Visit <https://14.adventofctf.com> to start the challenge.
## Finding the vulnerability
Upon opening the challenge website we're greeted with some PHP code, as well as two input fields. The PHP code is the following:
```php
<?php
ini_set('display_errors', 0);
include("flag.php");
if (isset($_POST["password"], $_POST["verifier"])) {
$password = $_POST["password"];
$verifier = $_POST["verifier"];
$hash = sha1($password + $secret_salt);
$reference = substr($hash, 0, 7);
if ($verifier === $reference) {
echo $flag;
die();
}
}
header("Location: /index.php?error=That was not right.");
exit();
?>
```
As we can see, we only get the flag if `$verifier` is equal to `$reference`, where `$reference` is the `SHA-1` hash of the password in our request together with `$secret_salt`.
_Note: when I started with this challenge, [@credmp](https://twitter.com/credmp) had already posted a hint which I, unfortunately, saw. It said "The salt is a number."._
## Type Juggling
Because we already know `$secret_salt` is a number, we can leverage PHP type juggling to generate a known value for the hashing algorithm. But first, what is type juggling?
Because PHP does not support explicit type definition in a variable declaration, a variable's type is determined by the context in which the variable is used. For instance, if a `string` value is assigned to a variable `$var`, `$var` becomes a string. But if an `int` value is then assigned to `$var`, it becomes an int. This means that if we have a `string` and add an `int` to it, the outcome will be an `int`. The value of this `int` depends on what is inside the `string`. If the `string` starts with a number, it will be interpreted as an `int` with the value of the number inside the `string`, and if it starts with a letter, it will be interpreted as `0`.
For example, if we have a variable with the value `"hello"`, it will be converted to `0`. And if we have a variable with the value `"24"` or `"12ab"` it will be interpreted as `24` and `12` respectively.
## Generating a verifier value
To see what input will be converted to what output, we can create a little script that will generate those values for us. An example would be the following:
```php
<?php
$password = "1a";
$secret_salt = "11";
$hash = sha1($password + $secret_salt);
$reference = substr($hash, 0, 7);
echo ($password + $secret_salt)."\n";
echo $hash."\n";
echo $reference."\n";
?>
```
We can then run this script on our local machine or on a website like <https://sandbox.onlinephpfunctions.com/>.
This script will take the two inputs and give us the outcome of the addition with the `$secret_salt` (I used 11 as the salt number but it could be any number), the generated hash and thus the `$verifier` input we need for the original script.
If we make `$password` a really big number like `922337203685477580792233720368547758079223372036854775807` we see that the output of the addition will be written in the scientific notation if it is converted to a string. And because the `sha1()` function wants a `string` for the input, it will also get the shrunk-down version. This means that if we make `$password` big enough, the value of `$secret_salt` will not matter as it is not significant enough for the output.
If we thus enter `922337203685477580792233720368547758079223372036854775807` as `$password` in the above script, we get the following output:
```text
9.2233720368548E+56
48a888ebec04f516e8b765bc3879354411ac2387
48a888e
```
If we thus use `922337203685477580792233720368547758079223372036854775807` as the password and `48a888e` as the verifier, it should echo the flag.
## Solution
After entering the above form data and submitting it, we get the flag: `NOVI{typ3_juggl1ng_f0r_l1fe}`!
This flag can then be submitted for the [challenge](https://ctfd.adventofctf.com/challenges#14-15).