---
# System prepended metadata

title: PIS CTF

---

```
        __        ______  ___ _____ _____      _   _ ____  ____  
        \ \      / /  _ \|_ _|_   _| ____|    | | | |  _ \/ ___| 
         \ \ /\ / /| |_) || |  | | |  _| _____| | | | |_) \___ \ 
          \ V  V / |  _ < | |  | | | |__|_____| |_| |  __/ ___) |
           \_/\_/  |_| \_\___| |_| |_____|     \___/|_|   |____/ 
```
# Welcome
Welcome
https://discord.gg/AbHCDWRw
Challenge có đính kèm link discord.Sau khi tham gia ta vào channel welcome. Flag sẽ được hiện lên ngay trên đầu sau phần Welcome.
![Screenshot 2025-11-11 114656](https://hackmd.io/_uploads/rJFRkBxx-g.png)

Flag:
```
PIS{W3lc0m3_t0_Mini_CTF_2025!!!}
```


# Web exploitation
How to play ctf?
---
http://3.107.132.87:5000/

* Description:

    Hidden source? 5 Part ........

    Flag format: PIS{...}

    Author: MinLammmm
    
Sau khi vào challenge thì đề đã cho 1 gợi ý:
![Screenshot 2025-11-11 115723](https://hackmd.io/_uploads/r1UwfSel-l.png)

Khi vào tab Console ta thấy được mảnh flag đầu tiên:
![Screenshot 2025-11-11 120047](https://hackmd.io/_uploads/S1eSXHee-x.png)

Flag 1: PIS{hidden_

Tiếp theo đọc source code của file style.css thấy được mảnh flag thứ 2:
```
/* style.css */

/* PARTB: in comment để người chơi view-source hoặc Sources -> mở file CSS */
/* partB: in_ */

body { font-family: system-ui, Arial, sans-serif; background:#f7f7f7; color:#222; }

```
Flag 2: in_

Trong tab elements ta đồng thời thấy mảnh flag thứ 3 và 4:
```
 <!-- PARTC in a meta tag (view-source or Elements -> head) -->
  <meta name="x-flag-part-c" content="f12_">
  
<!-- PARTD stored in image alt attribute -->
    <img src="img/decoy.png" alt="find_" style="display:none">

```
Flag 3: f12_
Flag 4: find_

Để tìm thấy Flag 5 ta vào Network --> chọn main request:
![image](https://hackmd.io/_uploads/HyjpIBxeZx.png)
Flag 5 sẽ được giấu ở phần Response Headers

Sau khi thu thập đủ 5 part ta được flag hoàn chỉnh:
```
PIS{hidden_in_f12_find_me}
```

Robots Everywhere
---
http://3.107.132.87:5002/

* Description:
        Can you find and defeat the robots of garbarca?
        
    Flag format: PIS{...}
        
    Author: BgiGoo
    
Sau khi vào thì giao diện challenge là 1 mini-game lật thẻ:
![image](https://hackmd.io/_uploads/rJS_YHel-x.png)

Việc đầu tiên sau khi đọc tên challenge là mình liên tưởng đến file robots.txt sau đó thêm đuôi `/robots.txt` vào sau tên miền thì hiện ra:
![image](https://hackmd.io/_uploads/SkdMqrgxZe.png)

Ở đây có khá nhiều fake flag. Sau khi tìm hết thì mình tìm được đường dẫn `/garbarca6677` chứa:

`PIS{"UElTe0lfNE1fVzEzVVVVVVVVVVdXVVVVVVVVVVV9"}`

Cụm trong ngoặc đã được mã hóa nên mình lên CyberChef để decrypt nó:
![image](https://hackmd.io/_uploads/B16IoSleZl.png)

Flag:`PIS{I_4M_W13UUUUUUUWWUUUUUUUU}`

TeConCak vs KT
---
http://3.107.132.87:5003/

* Description:
Người không chơi là người không bao giờ thắng !!!! Muốn kiếm tiền hãy trở thành bet thủ.
Author: Minhlammmm
Challenge có đính kèm 1 file shop.rar

Giao diện challenge là 1 trang Resgister và Login:
![image](https://hackmd.io/_uploads/H1_02Heg-g.png)

Đăng kí tài khoản ta được cấp 900 coins. Sau đó đăng nhập vào tài khoản:
![image](https://hackmd.io/_uploads/SJzoTBelWx.png)

Nhìn sơ qua có là ta phải làm cách nào đó để có 1000 coins để mà mua flag. Bây giờ mình sẽ đọc source code mà challenge đã đưa.

Trong file `bet.php` mình phát hiện một đoạn code:
```
$winner = ($choice === 'T1') ? 'KT' : 'T1'; // rigged
        $new = $coins - $bet;

        $u = $mysqli->prepare('UPDATE coins SET coin=? WHERE uid=? AND coin>=?');
        $u->bind_param('iii', $new, $uid, $bet);
        $u->execute();

```
Cái phần bet nãy đã được lập trình cho dù bạn chọn bên T1 hay KT thì kết quả sẽ luôn trả về là cái còn lại --> Luôn luôn bị LOSE.

Ở mục `Profile` có giao diện set_coins nhưng chỉ cho set đến 999 coins quá 3 chữ số sẽ thông báo lỗi:
![image](https://hackmd.io/_uploads/BkgpWIleZx.png)



Đến với file `profile.php` có đoạn:
```
if (isset($_GET['new_balance']) && waf($_GET['new_balance'])) {
    $nb = $_GET['new_balance'];

    if (strlen($nb) > 3) {
        $msg = "<div class='notice error'>Only 1–3 chars allowed</div>";
    } else {
        $sql = sprintf("UPDATE coins SET coin=%s WHERE uid=%d", $nb, $uid);
        if ($mysqli->query($sql)) {
            $msg = "<div class='notice success'>Coins updated!</div>";
        } else {
            $msg = "<div class='notice error'>Update failed: " . htmlentities($mysqli->error) . "</div>";
        }
    }
}
```
Ở đây ta thấy phần `coin=%s` không có dấu ' vì thế giá trị sẽ được chèn thẳng vào SQL như một Numeric Literals. Vì thế quay lại trang profile thay vì nhập 1000 thì ta có thể nhập `1e3`:
![image](https://hackmd.io/_uploads/HyvU7Lxgbx.png)

Ta thành công có 1000 coins và đi mua flag thôi:
![image](https://hackmd.io/_uploads/BklcXIegWx.png)

Flag:`PIS{gre4t!!!!_th1s_1s_SQL_Inject10n_vuln3r4b1l1ty}`

Os Command
---
http://3.107.132.87:5005/

Description:
https://quantrimang.com/cong-nghe/mot-so-lenh-linux-co-ban-60400

Flag format: PIS{...}

Author: MinLammmm

Mình thấy challenge có đính kèm 1 trang Web liên quan đến Command của Linux nên đã thử lệnh `ls`:
![image](https://hackmd.io/_uploads/H1vPV8egWg.png)

Ta thấy 1 file tên là `d_flag_o_day_ne.txt`.Mình liền dùng `cat d_flag_o_day_ne.txt` thì hiện lên thông báo:![image](https://hackmd.io/_uploads/HkoREUlebg.png)

Ở đây mình không chắc là Challenge đã chặn các command hay là giới hạn kí tự nên mình đồng thời kiểm tra: 
![image](https://hackmd.io/_uploads/rksLSLggbl.png)
![image](https://hackmd.io/_uploads/HkqYSUxlZx.png)
![image](https://hackmd.io/_uploads/HJw9SUlg-l.png)

Như vậy ta có thể kết luận được là challenge đã giới hạn <5 kí tự.

Sau khi mình dọc bàn phím 1 hồi thì phát hiện kí tự `*` có chứa tên file `d_flag_o_day_ne.txt`:
![image](https://hackmd.io/_uploads/HJNvI8glZe.png)
Nhưng không thể dùng `cat *` vì nó chứa 5 kí tự bao gồm cả khoảng trắng. Nên mình dùng lệnh `od *` để dump cái file flag đó về dạng octal:
![image](https://hackmd.io/_uploads/rJKfP8eeWl.png)
Mình đã đưa ChatGPT đoạn octal này để decrypt ra số nguyên -> tách thành 2 bytes theo little-endian rồi ghép lại để được chuỗi bytes rồi decode UTF-8.:
```
#!/bin/bash
echo "PIS{B41_n4y_th4t_l4_e4syzzzz!!!!!!!!}"
```
Flag: `PIS{B41_n4y_th4t_l4_e4syzzzz!!!!!!!!}`

TeConCak vs KT (V2)
---
http://3.107.132.87:5004/

Description:
KT Vo Dich
LAY SOURCE CU MA DOC
Author: MinhLammmm

Vẫn là giao diện đó nhưng không còn dùng được `1e3` nữa. Dựa vào 2 hint:

Second order injection

MySQL user variable assignment

Ta có thể suy ra mình có thể inject vào SQL thông qua user register. Ở file`profile.php` username được chèn thẳng vào SQL:
```
$vuln_sql = "SELECT password FROM users WHERE username='$username' LIMIT 1";
@$mysqli->query($vuln_sql);
```
Sau đó gán biến username injection qua hàm  `WHERE`.

Dựa vào tài liệu này mình có thể tạo 1 payload để inject vào username: https://dev.mysql.com/doc/refman/8.4/en/user-variables.html

![image](https://hackmd.io/_uploads/SJaNAwll-e.png)

Mình đã thử dùng `hihi' OR @x:=1e3--` nhưng không nhận nên đã đổi thành `hihi' OR @x:=1e3#`.

Đăng nhập vào và qua phần profile ta nhập bừa 1 con số nào đó để nó hiện `?new_balance` ở trên tên miền:
![image](https://hackmd.io/_uploads/ryJfyOxgZe.png)

Sau đó thay giá trị 3 thành `@x`:
![image](https://hackmd.io/_uploads/SyVPJdgx-l.png)

Có tiền rồi thì mua flag thoai.Vì bài này challenge gặp vấn đề nên mình không nhớ format flag :(.

```
             _                _                    
            | |    ___  _   _(_) ___ ______  _____ 
            | |   / _ \| | | | |/ _ \_  /\ \/ / __|
            | |__| (_) | |_| | |  __// /  >  < (__ 
            |_____\___/ \__,_|_|\___/___|/_/\_\___|
```





















