---
# System prepended metadata

title: Bypass WAF with bytes character
tags: [ctf, nginx, qnqsec ctf, flask app, bypass]

---

# Introducion
Vừa rồi mình chơi giải QnQSecCTF 2025 thì có 1 chall `airspeed` rất hay về kỹ thuật bypass WAF nên tiện mình viết bài này nhằm mục đích lưu trữ và chia sẻ với những ai chưa biết ^^
>Note: bài viết này chỉ đề cập đến những vấn đề chính trong thử thách.

# Analyst
Nếu đã từng đụng đến Path Traversal thì chắc hẳn các bạn cũng biết đến kỹ thuật bypass với ký tự bytes ví dụ như null byte `\x00` chẳng hạn. Bạn có thể xem chi tiết bài viết này [Null Bytes Injection](https://mh4ck3r0n3.github.io/posts/2025/04/02/file-path-traversal-validation-of-file-extension-with-null-byte-bypass/) để hiểu rõ hơn.
- Khi đọc file cấu hình nginx trong source thì mình thấy rằng target là đường dẫn `/debug` nhưng mình không thể cố truy cập vì bị chặn -> HTTP Response 403.
- Đường dẫn `/debug` là target vì khi vượt qua được lớp WAF thì mình có thể injection để RCE.
    > How to bypass WAF reverse proxy ?

![post-example](https://hackmd.io/_uploads/B1hrokICgg.png)

Có thể thấy rẳng request được gửi đi sẽ bị chặn lại và đá về mã 403 nếu Nginx bắt gặp endpoint `/debug` cũng như nó sẽ không đến được Flask Server. Mấu chốt ở đây là mình sẽ phải đánh lừa giữa thằng Nginx vs Flask để tụi nó hiểu sai luồng truy cập.
- Thử chích null bytes vào sau endpoint thì server trả về trang 404 của frontend. Requests thông thường sẽ URL Encode nên server hiểu là không tồn tại đường dẫn đó -> 404 Not Found.
- Đến đây mình sẽ thử hạ cấp bằng cách viết script cho request chạy qua socket vì đơn giản bản thân socket nó là phiên bản thấp hơn và sẽ gửi đúng các ký tự đi mà không thông qua URL Encode.
- Khi viết script python mình để là `/debug + bytes([0])` <=> `/debug\x00` nhưng Flask Server sẽ hiểu là 1 null bytes và block -> 403 Forbidden. <br>
    => Giải thích kỹ 1 chút thì mọi request đều phải đi qua Nginx hay reverse proxy để lọc và kiểm tra. Khi đưa đường dẫn `/debug\x00` thì nó không nằm trong blacklist nên Nginx sẽ chuyển request đến Flask Server và thằng Flask mặc định hiểu rằng đây là 1 ký tự nguy hiểm dẫn đến block trả về trang 404.
    >Flask Server liệu có validate chặt chẽ khi cho phép các bytes khác ?

💡 Đến bước này mình sẽ thử brute force `bytes([X])` với X là từ 0 -> 256 và kết quả cho chall này là mình tìm được bytes `\x85` khi dừng loop tại 133 (mình test thì còn dính một vài ký tự khác) sau đó server phản hồi nội dung như trong source và khi bypass WAF thành công thì chuyện sau đó là tìm cách để khai thác RCE các thứ :v

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

<br>
<b>Cảm ơn các đã dành thời gian đọc bài viết của mình ^^</b>










