HTTP QUERY mulai dibahas sebagai metode untuk operasi baca yang memerlukan payload terstruktur, terutama ketika query string pada GET terlalu panjang, terlalu kompleks, atau sulit divalidasi. Dalam konteks teknis RFC 10008, QUERY ditujukan untuk permintaan yang bersifat baca seperti GET, tetapi membawa input di body seperti POST. Kombinasi ini berguna, namun juga membuka area risiko baru pada gateway, proxy, cache, logging, dan kontrol keamanan per-endpoint.
Kalau tim Anda ingin memakai endpoint QUERY sebagai alternatif GET/POST untuk pencarian, filtering, atau query analitis, pendekatan amannya adalah: perlakukan QUERY sebagai metode baca yang explicitly hardened. Artinya, jangan mengandalkan asumsi default infrastruktur HTTP. Pastikan autentikasi dan otorisasi diterapkan per endpoint, body tervalidasi ketat, payload dibatasi ukurannya, kompleksitas query dikendalikan, dan seluruh jalur observability tidak membocorkan token atau data sensitif.
Apa itu HTTP QUERY, dan kenapa implikasi keamanannya berbeda?
Secara praktis, QUERY mencoba mengisi celah antara dua pola umum:
- GET: cocok untuk baca sederhana, mudah di-cache, tapi terbatas oleh panjang URL dan kurang cocok untuk payload terstruktur besar.
- POST: bisa membawa body kompleks, tetapi secara semantik sering dipakai untuk aksi non-idempoten, sehingga cache, audit, dan kebijakan keamanan sering diperlakukan berbeda.
QUERY mempertahankan niat operasi baca, tetapi memindahkan parameter ke body request. Dari sudut pandang keamanan, perubahan ini penting karena banyak komponen jaringan dan aplikasi diasumsikan sudah matang untuk GET/POST, tetapi belum tentu punya perilaku aman atau konsisten untuk QUERY.
Perubahan permukaan serangan ketika memakai QUERY
- Proxy dan load balancer mungkin belum mengenali QUERY untuk aturan routing, WAF, atau cache.
- Logging bisa tidak konsisten: sebagian alat mencatat method dan path saja, sebagian lain juga mencatat body mentah.
- Cache sering terbiasa mengidentifikasi GET lewat URL, sementara QUERY butuh strategi cache key berbasis body yang hati-hati.
- Framework middleware mungkin memperlakukan validasi, CSRF, auth, atau body parsing secara berbeda untuk method non-standar.
- Tool observability dapat menyimpan payload query lengkap yang berisi filter sensitif, identifier internal, atau token yang salah penempatan.
Catatan penting: RFC 10008 sebaiknya diperlakukan sebagai konteks desain dan interoperabilitas, bukan asumsi bahwa seluruh ekosistem HTTP Anda sudah mendukung QUERY dengan aman. Justru karena dukungan belum merata, hardening operasional menjadi lebih penting.
Kebijakan dasar: autentikasi dan otorisasi per endpoint QUERY
Kesalahan umum adalah menganggap endpoint baca lebih aman sehingga kontrolnya longgar. Padahal endpoint baca kompleks sering memberikan akses ke data agregat, histori, metadata, atau relasi internal yang sangat sensitif.
1) Wajib autentikasi eksplisit
Jangan mewariskan kebijakan dari GET secara implisit. Untuk setiap endpoint QUERY, definisikan dengan jelas:
- siapa yang boleh memanggilnya,
- credential apa yang diterima,
- scope atau role minimal yang dibutuhkan,
- apakah ada pembatasan tenant, organisasi, region, atau resource tertentu.
Praktiknya, lebih aman jika API gateway dan service backend sama-sama memverifikasi kontrol akses:
- Gateway melakukan autentikasi awal, validasi token, dan coarse-grained authorization.
- Backend melakukan fine-grained authorization berdasarkan resource, tenant, atau field yang diminta.
2) Otorisasi harus mempertimbangkan isi query, bukan hanya path
Pada QUERY, akses sering dipengaruhi oleh body request. Misalnya, pengguna boleh mencari data order milik tenant tertentu, tetapi tidak boleh mengubah filter untuk tenant lain. Jadi, otorisasi tidak cukup berdasarkan /reports/search saja; isi body juga harus diverifikasi.
Contoh kebijakan:
- Field
tenantIddi body harus cocok dengan tenant pada token. - Field seperti
includeDeleted,debugFields, atauinternalStatushanya boleh dipakai role tertentu. - Daftar field yang bisa di-sort atau di-filter dibatasi berdasarkan role.
- Permintaan lintas akun, lintas region, atau lintas data domain ditolak meskipun skema valid.
3) Tolak fallback yang ambigu
Hindari perilaku seperti:
- jika token tidak ada, lanjut sebagai anonim,
- jika body kosong, kembalikan semua data,
- jika filter tenant tidak ada, gunakan tenant default,
- jika role tidak cocok, cukup sembunyikan sebagian field tetapi tetap proses query mahal.
Untuk endpoint QUERY, fallback semacam ini berisiko menjadi celah enumerasi data atau denial-of-service.
Contoh kebijakan otorisasi yang praktis
policy: report-search-query
method: QUERY
path: /v1/reports/search
authentication:
required: true
accepted_schemes:
- Bearer
authorization:
required_scopes:
- reports:read
tenant_binding:
request_body_field: tenantId
token_claim: tenant_id
action: require-equal
restricted_fields:
includeDeleted:
allowed_roles: [admin, auditor]
internalStatus:
allowed_roles: [admin]
validation:
body_schema: report-search-v1
reject_unknown_fields: true
limits:
max_body_bytes: 16384
max_filters: 20
max_date_range_days: 31
max_sort_fields: 3
rate_limit:
key: token.sub + route
requests_per_minute: 60
observability:
log_request_body: false
log_redacted_fields: [tenantId, customerEmail]
cache:
enabled: false
reason: sensitive search criteriaFormat di atas bukan standar tertentu, tetapi berguna sebagai pola review internal. Intinya: untuk QUERY, kebijakan keamanan perlu mendeskripsikan lebih dari sekadar path dan method.
Risiko cache, proxy, dan logging pada body QUERY
Bagian ini yang paling sering diremehkan. Karena QUERY membawa body, perilaku infrastruktur terhadap request bisa berbeda dari GET yang sudah mapan.
Cache: jangan berasumsi aman atau bekerja otomatis
Pada GET, banyak sistem cache menggunakan URL lengkap sebagai cache key. Pada QUERY, jika body memengaruhi hasil, maka cache key juga harus mempertimbangkan body. Jika tidak, bisa terjadi:
- cache confusion: dua query berbeda menghasilkan cache key sama,
- data leak antar pengguna: hasil query sensitif terbaca oleh caller lain,
- cache bypass tak sengaja: karena komponen perantara tidak mendukung QUERY, performa dan proteksi berubah tanpa disadari.
Panduan praktis:
- Jika data sensitif atau hasil dipersonalisasi, nonaktifkan shared cache.
- Jika caching diperlukan, gunakan cache key deterministik yang menggabungkan method, path, identitas caller, dan representasi body yang sudah dinormalisasi.
- Jangan gunakan body mentah sebagai key tanpa normalisasi; urutan field JSON berbeda bisa memecah cache secara tidak perlu.
- Pastikan gateway, CDN, dan reverse proxy memang mendukung kebijakan tersebut untuk QUERY.
Proxy dan middleware: uji dukungan method QUERY secara eksplisit
Beberapa komponen hanya diuji matang untuk GET, POST, PUT, PATCH, dan DELETE. Method QUERY bisa:
- ditolak oleh allowlist method,
- diteruskan tanpa body,
- tidak masuk ke rule WAF tertentu,
- tidak dikenali oleh metrics atau access log parser.
Karena itu, sebelum produksi:
- uji end-to-end dari client sampai backend,
- verifikasi body QUERY benar-benar sampai utuh,
- cek rule auth, WAF, rate limit, dan audit log tetap aktif,
- pastikan error path juga aman dan tidak membocorkan payload.
Logging: body QUERY sangat mudah menjadi sumber kebocoran
Karena QUERY digunakan untuk pencarian kompleks, body sering berisi identifier pelanggan, email, nomor transaksi, rentang tanggal sensitif, atau bahkan token yang keliru ditempatkan developer. Jika body ini dicatat mentah di access log, trace, APM, atau error log, kebocoran bisa terjadi ke banyak sistem turunan.
Aturan aman untuk logging:
- Jangan log body mentah secara default untuk endpoint QUERY.
- Log metadata minimum: request ID, method, path, ukuran body, hasil validasi, durasi, status code, dan hash payload jika perlu korelasi.
- Redaksi field sensitif di level gateway dan aplikasi.
- Jangan pernah menerima token di query string atau body jika seharusnya ada di header
Authorization. - Pastikan exception handler tidak menyertakan payload penuh ke log error.
Validasi input terstruktur untuk endpoint QUERY
Kalau QUERY dipakai untuk operasi baca kompleks, input biasanya lebih kaya: filter bertingkat, operator, pagination, sorting, include relation, agregasi, atau ekspresi pencarian. Ini membuat validasi schema menjadi kontrol keamanan utama, bukan sekadar kenyamanan pengembang.
Prinsip validasi yang aman
- Schema ketat: tentukan tipe, enum, format, nilai minimum/maksimum, dan struktur nested.
- Tolak field tak dikenal: jangan diam-diam mengabaikan field asing, karena ini menyulitkan audit dan membuka celah bypass.
- Whitelist operator: batasi hanya operator yang benar-benar didukung, misalnya
eq,in,between. - Validasi semantik: bukan hanya bentuk JSON, tetapi juga arti bisnisnya, seperti rentang tanggal maksimum atau kombinasi field yang valid.
- Normalisasi input: urutan sorting, bentuk tanggal, huruf besar-kecil, dan nilai default harus konsisten sebelum diproses atau di-cache.
Contoh schema input yang lebih aman
{
"tenantId": "tnt_123",
"dateRange": {
"from": "2026-07-01",
"to": "2026-07-31"
},
"filters": [
{ "field": "status", "op": "in", "value": ["paid", "shipped"] },
{ "field": "channel", "op": "eq", "value": "web" }
],
"sort": [
{ "field": "createdAt", "direction": "desc" }
],
"page": {
"size": 100,
"cursor": "opaque-cursor"
}
}Yang perlu divalidasi dari contoh di atas:
tenantIdwajib dan harus cocok dengan klaim token.dateRangetidak boleh lebih dari batas yang diizinkan, misalnya 31 hari.filters[].fieldharus dari daftar yang disetujui, bukan nama kolom bebas.filters[].opharus dari enum operator yang didukung.valueharus cocok dengan tipe field target.page.sizedibatasi ketat untuk mencegah query mahal.sort.fieldhanya untuk field yang aman dan terindeks.
Jangan menerjemahkan input ke query database secara dinamis tanpa whitelist
Bug paling berbahaya biasanya bukan SQL injection klasik, tetapi query construction abuse. Misalnya, developer membiarkan caller menentukan nama field, operator, relasi, atau ekspresi sort yang lalu langsung diterjemahkan ke ORM atau query builder.
Lebih aman jika aplikasi memakai peta eksplisit seperti ini:
const allowedFilters = {
status: { type: 'enum', ops: ['eq', 'in'] },
channel: { type: 'string', ops: ['eq'] },
createdAt: { type: 'date', ops: ['between'] }
};
function validateFilter(filter) {
const rule = allowedFilters[filter.field];
if (!rule) throw new Error('unsupported field');
if (!rule.ops.includes(filter.op)) throw new Error('unsupported operator');
// validasi tipe value sesuai rule.type
}Pola whitelist semacam ini mencegah field internal, kolom yang tidak terindeks, atau ekspresi yang mahal dipakai sembarangan.
Batas ukuran dan kompleksitas payload: kontrol anti-abuse yang wajib
QUERY yang fleksibel mudah disalahgunakan untuk menghasilkan beban tinggi meskipun secara semantik hanya operasi baca. Karena itu, selain validasi bentuk data, Anda juga perlu mengendalikan ukuran dan kompleksitas.
Batas yang sebaiknya ada
- Maksimum ukuran body: cegah payload besar yang tidak masuk akal.
- Jumlah filter maksimum: misalnya batasi banyaknya item dalam
filters. - Kedalaman nesting maksimum: cegah struktur JSON terlalu dalam.
- Maksimum field sort/include: batasi variasi operasi yang memperberat query planner.
- Batas rentang waktu: rentang data terlalu panjang hampir selalu mahal.
- Batas page size: hindari respons besar dan scan berlebihan.
- Batas kompleksitas terhitung: beri skor pada operator mahal, wildcard, agregasi, atau relasi tambahan.
Contoh skor kompleksitas sederhana
score = 0
+ 1 per filter biasa
+ 3 per operator between
+ 5 jika meminta agregasi
+ 2 per field sort tambahan
+ 10 jika include relasi berat
reject jika score > 20Model ini tidak harus rumit. Tujuannya adalah menolak request yang secara sah secara sintaks, tetapi tidak sehat untuk sistem.
Trade-off yang perlu dipahami
- Batas terlalu ketat dapat merusak pengalaman pengguna untuk analisis yang valid.
- Batas terlalu longgar akan dipakai untuk scraping, enumerasi, dan resource exhaustion.
- Jika ada kebutuhan internal yang lebih berat, pertimbangkan endpoint terpisah dengan auth lebih kuat, antrean async, atau data mart khusus.
Rate limit, abuse prevention, dan proteksi secret
Karena endpoint QUERY tampak seperti operasi baca, tim kadang hanya menerapkan rate limit ringan. Ini berbahaya jika query dapat memicu scan besar, fan-out ke banyak service, atau agregasi mahal.
Strategi rate limit yang lebih tepat
- Basis identitas: gunakan kunci rate limit berbasis subject token, API key, tenant, dan route.
- Bedakan kelas endpoint: endpoint QUERY kompleks perlu limit lebih ketat daripada GET sederhana.
- Gunakan bobot: request dengan kompleksitas tinggi mengonsumsi kuota lebih besar.
- Terapkan concurrency limit: batasi jumlah request QUERY yang diproses bersamaan per caller atau tenant.
- Tambahkan timeout dan circuit breaker: agar query mahal tidak menahan resource terlalu lama.
Jangan biarkan secret bocor ke log
Salah satu risiko praktis terbesar adalah developer atau client mengirim token, credential, atau data rahasia di tempat yang salah. Aturan aman yang sebaiknya dipaksakan:
- Token akses hanya diterima di header
Authorization, bukan di URL, body, atau field payload. - Gateway menolak request yang memuat pola token di query string atau body yang tidak semestinya.
- Access log harus meredaksi header sensitif seperti
Authorization,Cookie, dan header kustom sejenis. - Tracing tidak boleh menyalin body penuh untuk endpoint sensitif.
Jika Anda perlu korelasi request untuk debugging, lebih aman menyimpan hash payload dan subset field yang sudah dipilih secara eksplisit daripada body mentah.
Aturan aman untuk observability pada endpoint QUERY
Observability yang baik bukan berarti mencatat semuanya. Untuk QUERY, tujuan observability adalah memahami perilaku sistem tanpa memperbesar blast radius data sensitif.
Apa yang sebaiknya dicatat
- request ID dan trace ID,
- method, path, status code, durasi, ukuran request/response,
- hasil autentikasi dan keputusan otorisasi,
- versi schema payload,
- skor kompleksitas,
- cache hit/miss,
- kategori validasi gagal, bukan payload mentah.
Apa yang sebaiknya tidak dicatat secara default
- body request penuh,
- header otentikasi, cookie, atau session identifier,
- field PII seperti email, nomor telepon, alamat, atau identifier pemerintah,
- hasil query yang berisi data pelanggan.
Kapan logging payload boleh dilakukan?
Kalau benar-benar dibutuhkan untuk debugging insiden:
- aktifkan sementara dengan scope sempit,
- hanya untuk lingkungan non-produksi atau tenant uji,
- redaksi field sensitif terlebih dahulu,
- batasi retensi dan akses operator,
- dokumentasikan alasan dan waktu aktifnya.
Checklist review API gateway untuk method QUERY
Berikut checklist praktis sebelum endpoint QUERY dibuka ke produksi.
Method dan routing
- QUERY masuk allowlist method di gateway, load balancer, dan WAF.
- Routing tidak menghapus atau mengubah body request.
- Backend framework benar-benar mem-parse body untuk method QUERY.
Auth dan authorization
- Autentikasi wajib untuk endpoint yang sensitif.
- Validasi token dilakukan di gateway.
- Backend memverifikasi klaim tenant/resource terhadap isi body.
- Field berisiko tinggi dibatasi berdasarkan role/scope.
Validasi dan pembatasan
- Schema payload terversi dan terdokumentasi.
- Unknown field ditolak.
- Batas body size dikonfigurasi.
- Batas filter, sort, page size, date range, dan nesting diterapkan.
- Skor kompleksitas dihitung sebelum query dieksekusi.
Cache dan proxy
- Diputuskan jelas: endpoint ini boleh di-cache atau tidak.
- Jika di-cache, cache key mempertimbangkan body yang dinormalisasi dan identitas caller.
- Diverifikasi bahwa proxy/CDN tidak melakukan perilaku tak terduga untuk QUERY.
Rate limit dan reliabilitas
- Rate limit berbasis identitas dan route aktif.
- Request berbobot tinggi mengonsumsi kuota lebih besar.
- Concurrency limit, timeout, dan cancellation tersedia.
- Response error untuk throttle konsisten dan tidak membocorkan detail internal.
Logging dan observability
- Request body mentah tidak dicatat secara default.
- Header sensitif dirahasiakan.
- Trace/metric memuat ukuran payload dan skor kompleksitas, bukan isi payload penuh.
- Log sanitization diuji dengan payload berisi pola token dan PII.
Perbandingan risiko QUERY vs GET vs POST untuk backend modern
GET
Kelebihan: semantik baca sudah mapan, dukungan cache dan tooling sangat baik, mudah dipantau.
Risiko utama: query string sering terekam di log, URL punya batas panjang praktis, payload kompleks sulit divalidasi rapi, parameter sensitif mudah bocor ke referer atau histori client jika salah desain.
Cocok untuk: pembacaan sederhana, filter kecil, endpoint yang memang aman direpresentasikan di URL.
POST
Kelebihan: body fleksibel, dukungan infrastruktur sangat luas, mudah dipakai untuk payload kompleks.
Risiko utama: semantik baca tidak eksplisit, cache sering tidak alami, audit dan policy bisa tercampur dengan operasi mutasi, beberapa tim cenderung memberi pengecualian keamanan karena menganggap semua POST sama.
Cocok untuk: saat QUERY belum didukung ekosistem Anda, tetapi Anda tetap butuh body terstruktur untuk operasi baca.
QUERY
Kelebihan: secara desain lebih tepat untuk operasi baca kompleks dengan body, lebih jelas daripada memaksakan POST untuk pencarian.
Risiko utama: dukungan toolchain belum sematang GET/POST, potensi masalah pada proxy/cache/logging lebih tinggi, middleware keamanan bisa tidak teruji untuk method ini.
Cocok untuk: backend modern yang menginginkan semantik baca lebih akurat dan siap melakukan verifikasi kompatibilitas infrastruktur secara menyeluruh.
Rekomendasi keputusan praktis
- Pilih GET jika input kecil, tidak sensitif di URL, dan ingin memanfaatkan cache standar.
- Pilih POST untuk operasi baca kompleks jika ekosistem Anda belum siap menerima QUERY secara aman.
- Pilih QUERY hanya jika Anda memang ingin semantik baca yang lebih tepat dan siap melakukan hardening penuh di gateway, proxy, cache, logging, dan backend.
Pola implementasi aman yang realistis
Jika tim Anda ingin mengadopsi QUERY sekarang, pendekatan yang paling aman biasanya bertahap:
- Mulai dari satu endpoint baca kompleks yang sudah jelas kebutuhannya.
- Definisikan schema request yang ketat dan terversi.
- Pasang auth wajib, tenant binding, dan field-level restrictions.
- Matikan shared cache lebih dulu; aktifkan kembali hanya jika desain cache key sudah terbukti aman.
- Nonaktifkan body logging default pada jalur produksi.
- Tambahkan rate limit berbobot dan skor kompleksitas.
- Uji end-to-end di gateway, WAF, reverse proxy, tracing, dan backend framework.
- Lakukan review abuse case: scraping, enumeration, wide date range, heavy sort, nested filters, dan payload anomali.
Dengan pendekatan ini, QUERY bisa dipakai secara praktis tanpa mengorbankan keamanan. Kuncinya bukan pada method semata, melainkan pada disiplin kontrol di setiap lapisan yang memproses request.
Penutup
Mengamankan endpoint QUERY berarti menerima bahwa operasi baca kompleks punya risiko yang setara seriusnya dengan operasi tulis, terutama saat body request mulai terlibat. Dalam konteks RFC 10008, QUERY memberi semantik yang lebih tepat untuk pencarian kompleks, tetapi keuntungan itu hanya layak diambil jika infrastruktur Anda siap.
Prioritas hardening yang paling penting adalah: autentikasi dan otorisasi per endpoint, validasi schema yang ketat, pembatasan ukuran dan kompleksitas payload, rate limit berbobot, proteksi secret dari log, dan observability yang minim namun cukup. Jika salah satu komponen itu belum siap, memakai POST untuk operasi baca kompleks sering lebih aman daripada memakai QUERY tanpa kontrol yang matang.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!