---
# System prepended metadata

title: KCSC Recruitment 2023
tags: [CTF_WU]

---

# 1. save_the_world

![image](https://hackmd.io/_uploads/HkFJSO28p.png)
```python
from flask import Flask, send_file, request, render_template
import os
from urllib.parse import unquote
import secrets
import config
from middleware import PathTraversalMiddleware

app = Flask(__name__,template_folder="templates")

app.wsgi_app = PathTraversalMiddleware(app.wsgi_app)


@app.route('/')
def hello_world():
    return render_template('index.html')

@app.route('/upload', methods=['POST','GET'])
def handleUpload():
    if request.method == 'POST':
        if 'file' not in request.files:
            return 'No file part'
        file = request.files['file']
        if file.filename == '':
            return 'No selected file'
        extension = file.filename.split('.')[-1]
        if extension not in config.ALLOW_EXTENSION:
            return 'Invalid file extension'
        new_name  = '%s.%s' % (secrets.token_hex(16), extension)
        if file:
            file.save('%s/%s' % (config.UPLOAD_FOLDER,new_name))
            return render_template('upload.html', success_message='File uploaded successfully: %s' % new_name)
    else:
        return render_template('upload.html')
    
@app.route('/viewfile/<filepath>')
def handleFile(filepath):
    target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath)))
    if os.path.isfile(target_file):
        return send_file(target_file)
    else:
        return '', 404

if __name__ == '__main__':
    app.run(host="0.0.0.0",port=5000)
```

## Phân tích

App này có 2 chức năng chính đó là `upload file` và `viewfile`

Do ở challenge này đã bị `filter whitelist` rồi nên ta sẽ không thể upload file to rce được

```python
#config.py
UPLOAD_FOLDER = "/app/uploads"
ALLOW_EXTENSION = ["jpg","png","gif"]
```

Next sang hàm tiếp theo

```python
@app.route('/viewfile/<filepath>')
def handleFile(filepath):
    target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath)))
    if os.path.isfile(target_file):
        return send_file(target_file)
    else:
        return '', 404
```

Ở đây có xuất hiện hàm `send_file` dẫn đến `Path Traversal`

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

## Exploit

Ở đây có 1 class chống path travelsal được import ở `app.py`

```python
class PathTraversalMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        # Extract the path from the request
        path = environ.get('PATH_INFO', '')

        # Check if the path contains ".."
        if ".." in path:
            # Block the request if it contains ".."
            return self.block_request(start_response)

        # If the path is safe, proceed with the request
        return self.app(environ, start_response)

    def block_request(self, start_response):
        # Return a 403 Forbidden response
        start_response('403 Forbidden', [('Content-Type', 'text/plain')])
        return [b'Forbidden: Path traversal not allowed.']
```

Bypass được bằng url decode

Nhưng bị dính hàm `unquote(filepath)`

```bash
$ cat test.py
from urllib.parse import unquote
filepath = '%2e%2e%2f%2e%2e%2f%2e%2e%2f'
print(unquote(filepath))
$ python3 test.py
../../../
```

Hàm này sẽ url decode ra nên khi ta truyền thằng trên url như kia sẽ bị dính `..` trong path

-> ez bypass bằng `double encode`

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

Flag được lưu ở biến env

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

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

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

# 2. WarmupPHP

Bài này có 3 flag với mỗi vuln 1 flag

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

## Flag1

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

Có thể thấy đây là [smarty ssti](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#smarty-php)

Tưởng dễ ăn nhưng lại chỉ sử dụng được hàm `{$smarty.version}`

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

Bế tắc nên mình chuyển sang dirsearch và có được source

```
$ curl http://103.162.14.116:10007/robots.txt
User-agent: *
Disallow: /?source
```

```php
<?php
include('flagl.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']);
```

ez flag1

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

## Flag2

### Phân tích

```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'
];
?>
```

Nhìn lại file source có:

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

khi chuỗi bắt đầu bằng `kcsc` sẽ kích hoạt `$policy` cho phép sử dụng 2 hàm `debug` và `symlink`

```
$allow_php_func = [
    'debug',
    'symlink'
];
```

Đầu tiền với hàm `debug`

```php
function debug($input) {
    if (str_contains($input, '/') || str_contains($input, '.')) {
        die('invalid filepath');
    }
    if (strlen(readlink($input)) >= 128) {
        echo file_get_contents($input);
    }
}
```

Đầu tiên hàm này sẽ kiểm tra xem symlink có chứa `.` hay `/` không thì sẽ `die()`

Thứ 2, sẽ kiểm tra độ dài của symlink khi được link lúc đầu nếu lớn hơn 128 sẽ in ra file được link ấy

### Exploit

Luồng exploit sẽ như sau:

- Tạo 1 symlink có độ dài > 128 đến file `flag2.php` bằng hàm `symlink()`

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

- Đọc file bằng hàm `debug()`

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

# 




