Pembahasan ujian Registered Information Security Specialist, musim semi 2024 (Reiwa 6), PM Q1 — JWT alg=none, otorisasi API, dan mitigasi WAF sementara
· Go Komura · Registered Information Security Specialist, Spesialis Keamanan Terdaftar, API, Keamanan API, JWT, Autentikasi, Otorisasi, WAF, Log4Shell, Keamanan informasi, Kerentanan, IPA
“Kita memverifikasi tanda tangan JWT, jadi ID pengguna dapat dipercaya.”
Pernyataan itu hanya setengah benar.
Soal 1 sesi PM (sore) ujian Registered Information Security Specialist musim semi 2024 (Reiwa 6) dibangun di sekitar API yang dipanggil dari aplikasi ponsel.1 Setelah autentikasi berhasil, JWT diterbitkan, dan JWT itu dilampirkan pada panggilan ke API yang mengambil dan memperbarui informasi pengguna. Sekilas, ini susunan yang sepenuhnya biasa.
Namun, asesmen menemukan empat masalah berikut.
- Mengubah
algpada header JWT menjadinonemembuat JWT tanpa tanda tangan lolos. - Mempertahankan JWT yang sah tetapi mengubah
midke ID pengguna lain memungkinkan Anda membaca atau memperbarui informasi orang lain. - Menambahkan
status=paidyang tidak didokumentasikan mengubah pengguna tingkat gratis menjadi pengguna berbayar. - Kode autentikasi empat digit yang dikirim lewat email dapat di-brute-force tanpa batas jumlah percobaan.
Keempatnya tampak seperti “kerentanan di sekitar autentikasi”, tetapi penyebabnya tidak sama. Yang dipecahkan adalah batas yang terpisah: integritas token, otorisasi tingkat objek, otorisasi tingkat properti, dan pembatasan laju percobaan.
Bagian kedua soal menambahkan topik lain lagi. Kerentanan kritis diungkapkan pada pustaka sumber terbuka yang banyak dipakai, yang memungkinkan penyerang mengeksekusi kode dari jarak jauh dengan menyalahgunakan JNDI Lookup. Belum ada perbaikan maupun aturan WAF yang selesai. Sementara itu, soal menanyakan bagaimana mengonfirmasi dampak, di mana WAF harus melihat, dan mengapa mode WAF awal harus “deteksi” bukan “blokir”.
Artikel ini memakai jawaban model resmi2 dan komentar penilaian3 sebagai fondasi, dan menelusuri bukan hanya jawaban tiap soal melainkan mengapa itu jawabannya, dan seberapa lebih ketat Anda harus merancangnya dalam praktik.
flowchart TB
accTitle: Ikhtisar soal
accDescr: Menunjukkan batas kepercayaan yang dipecahkan di setiap tahap - kode autentikasi, JWT, otorisasi API, dan kerentanan pustaka
user["Aplikasi pengguna"]
auth["Kode autentikasi 4 digit"]
jwt["Penerbitan JWT"]
api["API pengguna"]
log["Keluaran log"]
vuln["Pustaka rentan"]
ext["Eksekusi kode jarak jauh"]
user --> auth
auth -->|Tanpa batas percobaan| jwt
jwt -->|Mengizinkan alg=none| api
api -->|Mempercayai mid| db1["Baca/perbarui data pengguna lain"]
api -->|status=paid| db2["Ubah status penagihan"]
api --> log
log --> vuln
vuln -->|JNDI/LDAP/HTTP| ext
Gambar 1: Ikhtisar soal. Batas kepercayaan yang berbeda dipecahkan di setiap tahap.
1. Kesimpulan lebih dulu
- Sifat API RESTful yang tidak menyimpan status sesi disebut statelessness. Ini tidak berarti server sama sekali tidak menyimpan basis data atau status pengguna
- Kode autentikasi empat digit punya 10.000 nilai yang mungkin. Pada 10 percobaan per detik, penyerang berhasil setelah rata-rata 5.000 percobaan, yaitu 500 detik — lebih pendek dari masa berlaku 10 menit, jadi kedaluwarsa saja tidak bisa menghentikannya
- Tindakan minimum terhadap
alg=noneadalah memastikanalgpada header JWT bukanNONE. Namun dalam praktik, Anda harus menetapkan himpunan algoritme yang diizinkan di sisi server - Meski JWT sah,
midpada permintaan tidak boleh dipercaya. Cocokkan ID pengguna di dalam JWT denganmid, atau, lebih aman, jangan terimamiddari klien sama sekali dan tentukan sasaran dari JWT - Menambahkan
status=paidadalah masalah Mass Assignment, di mana properti di luar spesifikasi diikat langsung ke objek internal. Pakai DTO pembaruan sebagai daftar izinkan, dan jangan biarkan pengguna mengubah status penagihan - Jawaban model untuk tindakan brute-force adalah logika yang mengunci akun begitu jumlah kegagalan beruntun melebihi ambang. Dalam praktik, tumpuk juga penundaan bertahap dan kontrol per-sumber
- Untuk mengonfirmasi dampak kerentanan kritis yang baru diungkapkan, daripada mengeluarkan perintah merusak, catat akses ke
index.htmlserver uji untuk memastikan eksekusi kode jarak jauh benar-benar mencapainya - Karena string serangan dibawa di header HTTP, sasaran inspeksi WAF adalah
Header. Sebagai ekspresi reguler yang menangani penukaran huruf, pakai sesuatu seperti\W[jJ][nN][dD][iI]\W - Manfaat memulai WAF dalam mode “deteksi” adalah mencegah lalu lintas bisnis yang sah diblokir oleh positif palsu. Ketika peringatan datang, telaah apakah itu serangan sungguhan, lalu pindah ke mode pemblokiran setelah aturan disesuaikan
- WAF hanyalah tindakan sementara; perbaikan akar adalah memperbarui pustaka yang terdampak ke versi yang sudah ditambal
2. Bagaimana skenario dipetakan ke soal
Skenarionya di Perusahaan G, yang sedang meluncurkan layanan kesehatan baru. Pengguna memasukkan data seperti makanan dan berat badan lewat aplikasi ponsel dan menerima penilaian risiko kesehatan serta saran diet. Sistem dibangun di cloud, menggabungkan gerbang API, pemrosesan berbasis peristiwa, dan basis data terkelola.
Naskah soal mengabstraksikan nama produk dan layanan spesifik. Artikel ini pun tidak mereproduksi diagram atau teks IPA, melainkan memparafrase hanya struktur yang diperlukan untuk memahami soal.
| Soal | Topik | Bab artikel ini |
|---|---|---|
| Soal 1 | Sifat API RESTful | Bab 4 |
| Soal 2(1) | Waktu brute-force kode 4 digit | Bab 5 |
| Soal 2(2) | JWT alg=none |
Bab 6 |
| Soal 2(3) | Mengakses pengguna lain lewat mid |
Bab 7 |
| Soal 2(4) | Celah yang menerima status di luar spesifikasi |
Bab 8 |
| Soal 2(5) | Tindakan anti-brute-force | Bab 9 |
| Soal 3(1) | Mengonfirmasi adanya kerentanan dengan aman | Bab 11 |
| Soal 3(2)(3) | Di mana WAF melihat, dan ekspresi reguler | Bab 12 |
| Soal 3(4) | Manfaat mode deteksi dan cara mengoperasikannya | Bab 13 |
Komentar penilaian mencatat bahwa tingkat jawaban benar secara keseluruhan sekitar rata-rata. Namun, komentar itu juga menunjukkan bahwa tingkat jawaban benar agak lebih rendah untuk tindakan pemalsuan JWT pada Soal 2(2) dan untuk mekanisme yang diperlukan pada server verifikasi di Soal 3(1). Keduanya tidak dapat dijawab dari kosakata saja. Anda harus menelusuri nilai mana yang diubah penyerang, proses mana yang dimasukinya, dan di mana nilai itu akhirnya dipercaya.
3. Ini bukan hanya satu “masalah autentikasi”
Menyusun seluruh soal menurut batas kepercayaan menghasilkan berikut.
[ID pengguna / kata sandi]
|
v
[Pemeriksaan kode 4 digit] ---- tanpa batas percobaan ----> brute force
|
v
[Terbitkan JWT]
|
v
[Pustaka JWT] ------- mengizinkan alg=none ------> pemalsuan ID pengguna
|
v
[API pengguna]
| |
| +-- meneruskan status utuh ----> celah otorisasi tingkat properti
|
+-- mempercayai mid -----------------------> celah otorisasi tingkat objek
[Log masukan eksternal]
|
v
[Pustaka rentan] ---- JNDI/LDAP/HTTP ------> eksekusi kode jarak jauh
Pembedaan terpenting di sini adalah berikut.
| Pemeriksaan | Pertanyaan yang diajukan | Contoh yang dipecahkan dalam skenario ini |
|---|---|---|
| Autentikasi | Siapa Anda | Brute-force kode 4 digit |
| Verifikasi token | Apakah informasi identitas itu dipalsukan | alg=none |
| Otorisasi tingkat objek | Bolehkah pengguna ini mengakses data pengguna ini | Menukar mid |
| Otorisasi tingkat properti | Bolehkah bidang ini diubah | status=paid |
| Batas masukan-ke-eksekusi | Apakah masukan eksternal ditafsirkan sebagai perintah | JNDI Lookup |
Lolos satu pemeriksaan tidak pernah menjadi alasan untuk melewatkan yang berikutnya. Pengguna dengan JWT yang sah tidak otomatis diizinkan membaca data orang lain. Pengguna yang diizinkan memperbarui datanya sendiri tidak otomatis diizinkan mengubah status penagihannya juga.
Begitu Anda dapat memisahkan tahap-tahap ini, jawaban tiap soal berhenti menjadi sesuatu yang dihafal.
flowchart LR
accTitle: Perbedaan autentikasi dan otorisasi
accDescr: Autentikasi mengonfirmasi subjek, otorisasi mengonfirmasi apa yang diizinkan subjek itu lakukan
auth["Autentikasi<br/>siapa Anda"]
authz["Otorisasi<br/>apa yang boleh Anda lakukan"]
auth --> authz
Gambar 2: Perbedaan autentikasi dan otorisasi. Autentikasi lebih dulu; otorisasi adalah pemeriksaan terpisah.
4. Soal 1 — Apa arti “stateless”
Soal 1 menanyakan salah satu prinsip rancangan API RESTful: sifat tidak melakukan manajemen sesi.
Jawabannya adalah stateless.
Stateless berarti server tidak perlu mengingat status percakapan permintaan sebelumnya, karena setiap permintaan sendiri membawa segala yang diperlukan untuk memprosesnya. Dalam soal ini, aplikasi ponsel menempelkan JWT pada header Authorization di setiap permintaan. Server memverifikasi JWT itu dan mengidentifikasi pengguna untuk permintaan itu darinya.
Salah baca yang umum adalah menafsirkan “stateless” sebagai “server tidak menyimpan status sama sekali”. Pada kenyataannya, ia biasanya menyimpan status berikut.
- Basis data yang menyimpan informasi pengguna dan data kesehatan
- Status penagihan
- Nilai, kedaluwarsa, dan hitungan kegagalan kode autentikasi
- Kunci penandatanganan JWT
- Informasi pencabutan, untuk rancangan yang memakai daftar pencabutan
- Log dan catatan audit
Yang tidak disimpannya adalah status sesi sisi server yang ada semata untuk meneruskan percakapan, sebagai prasyarat yang bergantung pada tiap panggilan API.
Bersifat stateless juga tidak otomatis meningkatkan keamanan. Mengirim JWT di setiap permintaan memang memudahkan penskalaan horizontal, tetapi jika verifikasi JWT salah, kesalahan itu juga menyebar merata ke setiap node. Sifat arsitektur dan kebenaran keamanan adalah dua hal yang berbeda.
5. Soal 2(1) — Kode empat digit dipecahkan dalam rata-rata 500 detik
API autentikasi mengirim angka empat digit lewat email begitu ID pengguna dan kata sandi cocok. Ia lalu menerbitkan JWT begitu ID pengguna dan kode empat digit cocok. Kode berlaku 10 menit sejak dibuat.
Dalam asesmen, 10 percobaan per detik dimungkinkan. Soal menanyakan berapa detik, rata-rata, yang dibutuhkan untuk menembusnya.
Perhitungannya adalah “setengah ruang kandidat”
Angka empat digit, termasuk nol di depan, punya 10.000 kemungkinan berikut.
0000, 0001, 0002, ... , 9999
Jika jawaban yang benar diambil secara seragam acak, penyerang yang mencoba kandidat berurutan tanpa pengulangan mencapai yang benar, rata-rata, setelah setengah ruang kandidat.
Rata-rata jumlah percobaan = 10.000 / 2 = 5.000
Rata-rata waktu = 5.000 / 10 percobaan per detik = 500 detik
Jadi isian b adalah 500.
Kasus terburuk membutuhkan hingga 1.000 detik, tetapi soal menanyakan rata-rata. Dan masa berlaku kode adalah 600 detik — lebih panjang dari rata-rata waktu tembus 500 detik. Itulah mengapa dinilai “kemungkinan besar dipecahkan”.
flowchart LR
accTitle: Skala waktu kode autentikasi 4 digit
accDescr: Mencoba 10.000 kandidat pada 10 per detik rata-rata 5.000 percobaan dan 500 detik, yang kurang dari masa berlaku 600 detik
A["10.000 kandidat"] -->|Rata-rata 10.000 / 2 = 5.000 percobaan| B["Rata-rata waktu tembus 500 detik"]
C["Masa berlaku 600 detik"] -->|500 detik kurang dari 600 detik| D["Dapat dipecahkan dalam masa berlaku"]
Gambar 9: Skala waktu kode autentikasi empat digit. Mencoba, rata-rata, setengah ruang kandidat memecahkannya dalam masa berlaku.
Memendekkan hanya waktu kedaluwarsa kalah jika ruang kandidat kecil
Kekuatan kode autentikasi ditentukan bukan oleh jumlah digit saja maupun masa berlaku saja.
Jumlah percobaan yang mungkin selama masa berlaku
= percobaan per detik x masa berlaku
= 10 x 600
= 6.000 percobaan
Mencoba nilai tanpa pengulangan secara berurutan, penyerang dapat memeriksa 60% dari 10.000 kemungkinan dalam masa berlaku. Menetapkan waktu kedaluwarsa tidak cukup sendiri jika jumlah percobaan tidak dibatasi.
NIST SP 800-63B yang berlaku mensyaratkan setidaknya enam digit untuk rahasia jangka pendek yang dipakai dalam autentikasi di luar pita, dan mewajibkan batas laju percobaan kapan pun rahasia punya entropi kurang dari 64 bit. Ia juga meminta email tidak dipakai untuk autentikasi di luar pita.4 Jawaban ujian bekerja dalam spesifikasi yang diberikan berupa kode empat digit yang dikirim lewat email, tetapi untuk rancangan baru dalam praktik, premis itu sendiri harus ditinjau ulang.
6. Soal 2(2) — alg=none adalah masalah “membiarkan penyerang memilih metode verifikasi”
JWT dalam soal ini terdiri dari tiga bagian: header, payload, dan tanda tangan.
base64url(header).base64url(payload).base64url(signature)
Header mencatat RS256 sebagai algoritme yang dipakai untuk menandatangani. Payload berisi ID pengguna, waktu terbit, dan kedaluwarsa.
Penilai mengubah dua hal berikut.
- Ubah
algheader dariRS256menjadiNONE. - Ubah ID pengguna di payload menjadi pengguna lain.
Mengirim JWT itu, verifikasi berhasil dan memungkinkan penilai menyamar sebagai orang lain.
flowchart LR
accTitle: Alur serangan JWT alg=none
accDescr: Mengubah alg menjadi none pada JWT yang sah dan menulis ulang ID pengguna membuat permintaan lolos
A["JWT sah<br/>alg=RS256<br/>user=user01"] -->|Ubah alg header menjadi none| B["JWT dipalsukan<br/>alg=none<br/>user=user02"]
B -->|Melewatkan verifikasi tanda tangan| C["Server menerimanya<br/>sebagai user02"]
Gambar 3: Alur serangan JWT alg=none. Penyerang memilih algoritme verifikasi.
none bukan salah ketik
RFC 7519 mendefinisikan “Unsecured JWT” — JWT tanpa tanda tangan maupun enkripsi, yang alg-nya adalah none.5 Jadi nilai none bukan sesuatu yang semata tidak ada dalam spesifikasi.
Masalahnya adalah bahwa API yang seharusnya hanya menerima JWT bertanda tangan menerima none yang ditentukan penyerang.
Ditulis secara konseptual, proses yang rentan tampak seperti ini.
1. Baca header JWT.
2. Lihat alg yang tertulis di header, dan pilih metode verifikasi.
3. Jika alg adalah none, jangan verifikasi tanda tangan.
4. Percayai ID pengguna di payload.
Kekuatan keamanan itu sendiri dipilih dari masukan yang dikendalikan penyerang.
Jawaban ujian
Soal menanyakan, masing-masing dalam 20 karakter atau kurang, data mana yang harus diverifikasi pustaka Q yang sudah diperbaiki, dan apa yang harus diperiksa verifikasi itu.
Jawaban model adalah sebagai berikut.
| Butir | Inti jawaban |
|---|---|
| Data yang diverifikasi | Nilai yang ditentukan pada alg header JWT |
| Apa yang diverifikasi | Bahwa itu bukan NONE |
Sebagai perbaikan langsung atas kerentanan yang diuraikan dalam soal, ini benar.
Dalam praktik, jangan puas dengan “apa pun kecuali NONE”
Di sini kita perlu memisahkan jawaban ujian dari rekomendasi praktis.
RFC 8725 menyatakan bahwa pustaka JWT harus membiarkan pemanggil menentukan himpunan algoritme yang diizinkan, dan bahwa tidak ada yang di luar himpunan itu boleh dipakai.6 Dengan kata lain, idenya adalah ini.
Pendekatan buruk:
Terima jika token.header.alg != "none"
Pendekatan baik:
Terima hanya jika terkandung dalam serverConfig.allowedAlgorithms
mis. allowedAlgorithms = ["RS256"]
Menolak hanya none masih dapat menyisakan algoritme lemah lain, atau kemungkinan kebingungan algoritme di mana skema kunci publik dikira skema kunci simetris. Prinsipnya adalah bukan menambah syarat negatif tentang apa yang diterima, melainkan menetapkan himpunan positif yang sempit tentang apa yang diizinkan.
Verifikasi JWT harus mengonfirmasi bukan hanya algoritme tetapi, tergantung kasus penggunaan, setidaknya yang berikut juga.
| Butir | Apa yang dikonfirmasi |
|---|---|
| Tanda tangan | Dapatkah diverifikasi dengan kunci dan algoritme yang diharapkan |
iss |
Apakah penerbit yang dipercaya |
aud |
Apakah token diterbitkan untuk API ini |
exp |
Apakah masih dalam masa berlakunya |
nbf |
Apakah belum sebelum waktu “tidak berlaku sebelum” |
sub atau ID pengguna |
Apakah subjek yang sah dalam aplikasi |
| Jenis token | Apakah ID token dikacaukan dengan access token, dll. |
Dalam soal ini nama kunci payload adalah user, tetapi dalam praktik Anda harus memakai sub standar atau mendefinisikan dengan jelas makna klaim kustom.
flowchart TB
accTitle: Verifikasi JWT yang aman versus tidak aman
accDescr: Verifikasi tidak aman bergantung pada alg, verifikasi aman memakai daftar izinkan sisi server
subgraph "Verifikasi tidak aman"
D1["Baca alg dari header JWT"]
D2["Terima jika alg adalah none"]
D1 --> D2
end
subgraph "Verifikasi aman"
S1["Algoritme yang diizinkan di konfigurasi server<br/>mis. RS256"]
S2["Pastikan alg header JWT<br/>ada di daftar izinkan"]
S3["Verifikasi tanda tangan, iss, aud, exp"]
S1 --> S2 --> S3
end
Gambar 4: Verifikasi aman versus tidak aman. Dalam praktik, tetapkan himpunan sempit algoritme yang diizinkan.
Base64url bukan enkripsi
Ada kesalahpahaman umum lain tentang JWT. Header dan payload direpresentasikan dalam base64url, tetapi itu bukan enkripsi. Siapa pun dapat mendekode dan membacanya.
Yang dijamin tanda tangan, dan hanya ketika verifikasi berhasil, adalah bahwa isi tidak diubah sejak diterbitkan. Itu tidak berarti informasi pribadi yang ingin Anda rahasiakan boleh dimasukkan ke payload JWT yang ditandatangani.
7. Soal 2(3) — Meski JWT sah, mengubah mid membaca data orang lain
Berikutnya adalah serangan yang tidak memalsukan JWT itu sendiri.
API pengguna menerima ID pengguna bernama mid pada GET atau PUT. Modul bersama P mengambil atau memperbarui, di basis data, informasi pengguna yang terikat pada mid itu.
Struktur serangannya sederhana.
ID pengguna di dalam JWT: user01 <- JWT yang ditandatangani dengan benar
mid permintaan: user02 <- diubah oleh penyerang
Tanda tangan JWT sah, jadi autentikasi berhasil. Tetapi API mempercayai mid=user02 sebagaimana diberikan, dan mengembalikan informasi user02.
Ini kasus buku teks dari apa yang OWASP API Security Top 10 2023 sebut Broken Object Level Authorization (BOLA). Kapan pun data diakses memakai ID objek yang ditentukan pengguna, otorisasi untuk objek spesifik itu harus diperiksa setiap kali.7
flowchart LR
accTitle: Serangan BOLA
accDescr: Memakai JWT yang sah sambil mengubah mid permintaan ke ID pengguna lain
A["Penyerang"] -->|JWT user01<br/>mid user02| B["API pengguna"]
B -->|Mempercayai mid| C["Mengembalikan data user02 dari DB"]
Gambar 5: Serangan BOLA. Autentikasi lolos, tetapi otorisasi tidak pernah diperiksa.
Jawaban soal
Garis bawah 2 pada Tabel 5 menanyakan, dalam 40 karakter atau kurang, pemrosesan yang ditambahkan ke panggilan ke modul bersama P.
Jawaban model adalah:
Logika yang memverifikasi apakah ID pengguna yang terkandung dalam JWT cocok dengan nilai
mid
Manfaat memverifikasi di dalam modul bersama P adalah bahwa pemeriksaan otorisasi yang sama mudah diterapkan pada GET maupun PUT, dan pada API masa depan yang memakai P juga. Menyalin perbandingan yang sama ke setiap layar atau endpoint secara terpisah berarti suatu saat akan terlewat.
Rancangan yang lebih aman adalah tidak menerima mid sama sekali
Untuk API yang hanya mengambil atau memperbarui informasi pemanggil sendiri, tidak perlu menerima ID pengguna dari klien sama sekali.
GET /users/me
Authorization: Bearer <JWT>
Di sisi server, subjek diekstrak dari JWT yang sudah diverifikasi.
principal = validateJwt(request.authorization)
userId = principal.subject
return repository.getUser(userId)
Hal yang sama berlaku untuk pembaruan.
principal = validateJwt(request.authorization)
input = validateProfileUpdate(request.body)
repository.updateProfile(
userId = principal.subject,
name = input.name,
age = input.age
)
Pemeriksaan perbandingan melindungi Anda jika Anda menulisnya. Tetapi rancangan yang tidak pernah menerima ID sasaran dari luar mengurangi keberadaan kelas bug di mana Anda lupa menulis perbandingan itu.
Jika administrator perlu mengoperasikan informasi pengguna lain, pisahkan sebagai berikut.
PUT /users/me Untuk pengguna umum
PUT /admin/users/{userId} Untuk administrator
Untuk rute administrator, wajibkan izin terpisah, pencatatan audit, dan, jika perlu, autentikasi ulang. Ini membuat batas kebijakan otorisasi jauh lebih terlihat daripada “tambahkan pengecualian ke API pengguna umum hanya untuk administrator”.
flowchart LR
accTitle: Cara mencegah BOLA
accDescr: Alih-alih memakai mid permintaan, tentukan atau periksa sasaran dari subject JWT
A["Pengguna"] -->|GET /users/me + JWT| B["API"]
B -->|Ambil sub dari JWT| C{"Jika mid ada<br/>apakah cocok dengan sub"}
C -->|Cocok| D["Kembalikan data sendiri"]
C -->|Tidak cocok| E["Tolak 403"]
B -->|Tanpa mid| F["Pencarian DB menurut JWT sub"]
Gambar 6: Cara mencegah BOLA. Jangan terima mid, atau periksa terhadap subject JWT.
Membedakan autentikasi dari otorisasi dalam satu kalimat
Baik di ujian maupun dalam praktik, rumusan berikut membantu.
- Autentikasi: siapa Anda
- Otorisasi: apa yang boleh dilakukan orang itu
Verifikasi tanda tangan JWT yang berhasil hanya membawa Anda sampai “subjek yang diwakili token ini dapat dipercaya”. Apakah “subjek itu boleh membaca user02” harus dikonfirmasi secara terpisah.
8. Soal 2(4) — status=paid adalah celah otorisasi tingkat properti
Spesifikasi API pengguna mendefinisikan yang berikut sebagai parameter pembaruan.
mid ID pengguna
name Nama
age Usia
Namun, penilai menambahkan nilai berikut, yang tidak ada dalam spesifikasi.
status=paid
Status pengguna tingkat gratis lalu berubah menjadi pengguna yang membayar.
Menurut soal, layanan L tidak memvalidasi parameter yang diterimanya; ia meneruskan semuanya langsung ke modul bersama P, yang dibangun agar dapat memperbarui basis data secara langsung.
Jawaban untuk isian c adalah modul bersama P.
flowchart TB
accTitle: Mass Assignment
accDescr: status=paid di luar spesifikasi ditambahkan dan diterapkan utuh ke objek internal
A["Spesifikasi API<br/>mid / name / age"] -->|Penyerang menambahkan status=paid| B["Isi permintaan"]
B -->|Diikat otomatis| C["Modul bersama P"]
C -->|Disimpan ke DB| D["Status penagihan diubah menjadi paid"]
Gambar 7: Mass Assignment. Properti di luar spesifikasi diterapkan utuh ke objek internal.
Perbedaan dari BOLA
Penukaran mid di bab sebelumnya dan penambahan status ini tampak serupa, tetapi granularitas yang dilindungi berbeda.
| Kerentanan | Yang diubah penyerang | Yang seharusnya diperiksa |
|---|---|---|
Penukaran mid |
Objek sasaran | Bolehkah pengguna ini mengakses rekaman pengguna ini |
Penambahan status |
Properti di dalam objek | Bolehkah pengguna ini mengubah bidang ini |
OWASP API Security Top 10 2023 memperlakukan yang terakhir sebagai Broken Object Property Level Authorization, memasukkan apa yang sebelumnya disebut Mass Assignment ke dalam kategori ini.8
“Memasukkan JSON langsung ke entitas” berbahaya
Implementasi yang rentan, secara konseptual, tampak seperti ini.
entity = repository.find(body.mid)
bindAllProperties(entity, body)
repository.save(entity)
Meski layar hanya punya bidang masukan untuk name dan age, penyerang dapat merakit permintaan HTTP secara langsung. Absennya bidang dari UI bukan batas keamanan.
Implementasi yang aman membuat bidang yang dapat diperbarui eksplisit.
input = parseExactSchema(body, fields = ["name", "age"])
entity = repository.find(authenticatedUserId)
entity.name = input.name
entity.age = input.age
repository.save(entity)
Dua hal penting di sini.
- Tipe masukan pembaruan seharusnya hanya menampung bidang yang boleh diubah pengguna.
- Daripada diam-diam mengabaikan bidang tidak dikenal di luar spesifikasi, tolak sebagai kesalahan jika memungkinkan.
Mengabaikan diam-diam bidang tidak dikenal menyembunyikan fakta bahwa serangan gagal, tetapi juga membuat Anda melewatkan kesalahan implementasi klien dan tanda-tanda serangan. Kecuali ada alasan kompatibilitas, menolak dengan skema ketat memudahkan investigasi.
flowchart TB
accTitle: Otorisasi tingkat properti
accDescr: DTO pembaruan hanya menampung daftar izinkan, dan properti tidak dikenal ditolak
subgraph "DTO pembaruan - daftar izinkan"
D1["name"]
D2["age"]
end
A["Isi permintaan"] -->|Validasi skema| B{"Hanya bidang<br/>yang diizinkan ada"}
B -->|Ya| C["Perbarui name/age entitas"]
B -->|Tidak| D["Kembalikan kesalahan"]
E["Layanan pembayaran<br/>notifikasi terverifikasi"] -->|Jalur khusus| F["Perbarui status=paid"]
Gambar 8: Otorisasi tingkat properti. Batasi bidang yang dapat diperbarui dengan daftar izinkan, dan ubah status penagihan hanya lewat jalur terpisah.
status hanya boleh berubah dari hasil pembayaran
status=paid bukan bagian dari profil pengguna. Itu status yang diturunkan dari fakta sisi server: bahwa pembayaran berhasil.
Pembaruan profil pengguna
-> hanya name / age yang dapat diubah
Notifikasi terverifikasi dari layanan pembayaran
-> cocokkan paymentId
-> cegah pemrosesan ganda
-> ubah status menjadi paid
Meski disimpan di kolom basis data yang sama, wewenang untuk mengubahnya dan jalur yang dipakai untuk mengubahnya adalah dua hal berbeda. Memakai entitas internal secara langsung sebagai tipe masukan API eksternal menghapus batas itu.
9. Soal 2(5) — Tindakan anti-brute-force menyimpan hitungan kegagalan sebagai status
Untuk brute-force kode empat digit, isian d pada Tabel 5 menanyakan, dalam 30 karakter atau kurang, pemrosesan yang masuk di situ. Ambangnya adalah 10.
Jawaban model adalah:
Logika yang mengunci akun begitu jumlah kegagalan beruntun melebihi ambang
Ini tidak bertentangan dengan statelessness dari Soal 1. Tidak menyimpan status percakapan panggilan API sebagai sesi server, dan mempertahankan hitungan kegagalan yang diperlukan untuk keputusan keamanan, adalah dua hal berbeda.
flowchart LR
accTitle: Dengan dan tanpa batas laju percobaan
accDescr: Tanpa batas, kode dipecahkan dalam rata-rata 500 detik, tetapi batas hitungan kegagalan sangat memperlambat serangan
subgraph "Tanpa batas"
A1["10 percobaan per detik"] -->|Sekitar 500 detik| B1["Autentikasi berhasil"]
end
subgraph "Dengan batas"
A2["Kunci setelah 10 kegagalan"] -->|Kecepatan serangan ambruk| B2["Akun terkunci"]
C2["Penundaan bertahap"] --> B2
end
Gambar 10: Dengan dan tanpa batas laju percobaan. Batas hitungan kegagalan secara praktis dapat menghentikan brute-force.
Dalam praktik, jangan andalkan semata penguncian permanen
Batas percobaan per akun diperlukan, tetapi jika penyerang tahu ID pengguna orang lain, mereka dapat sengaja gagal 10 kali untuk mengunci pengguna yang sah. Oleh karena itu, dalam praktik, gabungkan yang berikut.
| Kontrol | Peran |
|---|---|
| Hitungan kegagalan per akun | Menghentikan brute-force terhadap satu akun |
| Waktu tunggu bertahap | Mentoleransi kesalahan ketik pengguna sah sambil memperlambat serangan |
| Kontrol menurut IP sumber, perangkat, ASN, dll. | Menekan serangan yang mencoba sedikit kali terhadap banyak akun |
| Keputusan berbasis risiko | Menerapkan pembatasan lebih kuat untuk wilayah, perangkat, atau kecepatan yang tidak biasa |
| Memberi tahu pengguna | Membiarkan pengguna menyadari serangan atau kesalahannya sendiri |
| Prosedur pemulihan yang aman | Menjaga saluran buka-kunci agar tidak menjadi jalur serangan sendiri |
Lebih jauh, ketika kode dikirim ulang, hitungan kegagalan tidak boleh direset ke nol — jika tidak, penyerang dapat mengisi ulang anggaran percobaan setiap kali mereka memanggil API kirim ulang. NIST SP 800-63B yang berlaku juga mensyaratkan bahwa hitungan kegagalan tidak direset meski rahasia autentikasi baru dibuat.4
Jadikan kode autentikasi sekali pakai
Soal berfokus pada waktu kedaluwarsa, tetapi dalam praktik yang berikut juga diperlukan.
- Batalkan segera kode yang berhasil.
- Tolak penggunaan ulang kode yang sama.
- Jangan sisakan kode itu sendiri di log.
- Buat respons sedemikian rupa sehingga keberhasilan atau kegagalan pemeriksaan kode tidak dapat dipakai untuk menyimpulkan apakah pengguna ada.
- Pasang juga batas percobaan pada API pengiriman kode.
Selama rahasia pendek dipakai, keamanan tidak dapat diserahkan pada pembangkitan acak saja.
flowchart TB
accTitle: Tindakan untuk kode autentikasi
accDescr: Di luar jumlah digit dan kedaluwarsa, lindungi dengan batas percobaan, penolakan penggunaan ulang, notifikasi, dan lainnya
A["Kode autentikasi"] --> B["Tambah jumlah digit"]
A --> C["Pendekkan kedaluwarsa"]
A --> D["Batas laju percobaan"]
A --> E["Batalkan setelah berhasil"]
A --> F["Jangan reset hitungan kegagalan saat kirim ulang"]
A --> G["Jangan sisakan kode di log"]
A --> H["Kontrol per-sumber"]
Gambar 11: Tindakan untuk kode autentikasi. Gabungkan jumlah digit dan kedaluwarsa dengan kontrol percobaan dan praktik operasional.
10. Membedakan empat bagian Soal 2 dalam satu halaman
Poin-poin di Soal 2 yang mudah dikacaukan, disusun menurut nilai yang dikendalikan penyerang.
| Serangan | Nilai yang diubah penyerang | Yang tidak seharusnya dipercaya | Perbaikan akar |
|---|---|---|---|
| Pemalsuan JWT | alg header JWT, ID pengguna di payload |
Algoritme verifikasi yang dideklarasikan token sendiri | Tetapkan algoritme yang diizinkan di sisi server |
| Membaca informasi pengguna lain | mid permintaan |
ID sasaran yang ditentukan klien | Cocokkan dengan subject JWT, atau tentukan ID sasaran dari JWT |
| Menaikkan ke pengguna berbayar | status di luar spesifikasi |
Semua properti yang diikat otomatis | Jadikan properti yang dapat diperbarui sebagai daftar izinkan |
| Memecahkan kode 4 digit | Kandidat untuk otp |
Percobaan autentikasi tanpa batas | Tambahkan batas laju percobaan, penundaan, dan keputusan risiko |
Penting untuk tidak menggabungkan semuanya sebagai “validasi masukan”.
algadalah kebijakan kriptografis.midadalah otorisasi tingkat objek.statusadalah otorisasi tingkat properti.otpadalah ketahanan terhadap tebakan daring.
Meski dalam permintaan HTTP yang sama, alasan masing-masing harus dilindungi berbeda.
11. Soal 3(1) — Mengonfirmasi eksekusi kode jarak jauh tanpa menimbulkan kerusakan
Setelah layanan diluncurkan, kerentanan kritis V diungkapkan pada pustaka H, pustaka sumber terbuka yang banyak dipakai. Urutan peristiwa dalam soal adalah sebagai berikut.
- Penyerang menaruh string yang berisi JNDI Lookup ke header HTTP dan mengirimnya.
- Server sasaran mencatat nilai itu.
- Pustaka yang rentan mengevaluasi JNDI Lookup dan menanyakan server LDAP penyerang.
- Respons LDAP mengembalikan URL server HTTP penyerang.
- Server sasaran mengambil berkas kelas dan mengeksekusi perintah.
Dengan nama produk spesifik disembunyikan, ini terbaca sebagai serangan tipe Log4Shell (CVE-2021-44228). Penjelasan Apache sendiri pun menggambarkan kerentanan sebagai yang, jika penyerang mengendalikan pesan log atau parameter, mereka dapat mengeksekusi kode sembarang yang dimuat dari server LDAP.9
flowchart LR
accTitle: Alur konfirmasi kerentanan tipe Log4Shell
accDescr: Pakai callback yang tidak berbahaya untuk mengonfirmasi apakah rantai dari JNDI ke eksekusi kode jarak jauh benar-benar tembus
A["Penyerang"] -->|Suntikkan muatan jndi/ldap<br/>ke x-api-version| B["Server rentan"]
B --> C["Pemrosesan log"]
C -->|JNDI Lookup| D["Server LDAP jahat"]
D -->|Respons URL HTTP| E["Server HTTP jahat<br/>index.html"]
E -->|Catat GET| F["Server uji<br/>log akses"]
F -->|Konfirmasi keterjangkauan| G["Kerentanan dikonfirmasi"]
Gambar 12: Alur konfirmasi kerentanan tipe Log4Shell. Keterjangkauan dikonfirmasi dengan mencatat akses HTTP, bukan mengeluarkan perintah merusak.
Kode verifikasi hanya memicu akses HTTP yang tidak berbahaya
Perusahaan G menjalankan kode verifikasi yang tidak berdampak pada sistem, untuk mengonfirmasi apakah kerentanan V dapat dieksploitasi dari luar. Satu-satunya perintah yang dikeluarkan kode verifikasi adalah mengambil index.html server uji.
Soal 3(1) menanyakan apa yang perlu diimplementasikan pada server uji agar dapat mengonfirmasi bahwa perintah dieksekusi.
Jawaban model adalah:
Mekanisme yang mencatat dan memungkinkan Anda mengonfirmasi akses ke index.html server uji
Jika log akses server web mencatat GET dari server sasaran, itu mengonfirmasi, setidaknya, bahwa rantai berikut tembus.
Permintaan HTTP eksternal
-> pemrosesan log
-> JNDI Lookup
-> respons LDAP
-> pengambilan kelas
-> eksekusi perintah verifikasi
-> akses HTTP ke server uji
Mengapa “menampilkan teks di layar” tidak cukup
Sasaran serangan adalah server. Tidak ada jaminan bahwa apa pun berubah di layar peramban pengguna. Juga, meski kerentanan ada, komunikasi keluar di tengah jalan dapat diblokir oleh firewall.
Mencatat akses di sisi server uji menghasilkan bukti yang dapat diamati bahwa server sasaran benar-benar mencapai dunia luar.
Ketika melakukan verifikasi semacam ini dalam praktik, selalu amati yang berikut.
- Dapatkan otorisasi eksplisit dari pemilik sistem sasaran.
- Pakai metode verifikasi yang tidak berdampak pada produksi, atau dampaknya dapat diterima.
- Jangan pakai perintah merusak seperti tulis, hapus, atau perubahan konfigurasi.
- Kelola domain dan server verifikasi sendiri.
- Catat waktu verifikasi, sumber, sasaran, dan callback yang diharapkan.
- Bongkar server LDAP atau HTTP sementara serta kredensial setelah verifikasi.
“Mengonfirmasi bahwa eksekusi kode sembarang dimungkinkan” dan “mengeksekusi kode berbahaya sembarang” bukan hal yang sama. Jaga efek samping pada minimum yang diperlukan untuk memenuhi tujuan.
12. Soal 3(2)(3) — WAF menginspeksi header HTTP
WAF layanan N memungkinkan Anda memilih GET, POST, PUT, ANY, Header, COOKIE, atau Multipart sebagai sasaran inspeksi.
Kode serangan masuk ke nilai header HTTP bernama x-api-version. Jadi isian e dan f pada Tabel 6 keduanya Header.
Petakan lokasi yang diberikan dalam teks langsung ke sasaran inspeksi WAF
Ini kurang tentang pengetahuan umum dan lebih tentang membaca aliran data dalam naskah soal.
Di mana string serangan diletakkan:
header x-api-version
|
v
Sasaran inspeksi WAF:
Header
Bukan parameter GET maupun isi POST. Daripada melihat daftar fitur WAF dan memilih ANY karena “tampak seperti serangan”, jawablah dengan lokasi di mana naskah soal mengatakan penyerang menaruh nilai itu.
Menangani penukaran huruf
Usulan pertama, secara konseptual, adalah aturan berikut.
Header \Wjndi\W blokir
Header \Wldap\W blokir
Tetapi menukar huruf, seperti jNdI, menghindari pola yang hanya cocok dengan huruf kecil.
Jawaban model untuk Soal 3(3) adalah salah satu dari yang berikut.
\W[jJ][nN][dD][iI]\W
\W(j|J)(n|N)(d|D)(i|I)\W
Dalam buku soal, garis miring terbalik dapat tampak seperti tanda yen pada glif lokal Jepang, tetapi sebagai ekspresi reguler itu adalah \W. \W cocok dengan karakter apa pun selain alfanumerik dan garis bawah. Dalam sintaksis JNDI Lookup, karakter non-kata seperti ${ dan : muncul tepat sebelum dan sesudah jndi, dan pola ditulis untuk menangkap itu juga.
Ide yang sama dapat diterapkan agar sisi ldap juga tidak peka huruf.
\W[lL][dD][aA][pP]\W
Jangan perlakukan regex ini sebagai “tindakan Log4Shell yang lengkap”
Ujian meminta ekspresi reguler yang menangani teknik penghindaran yang ditunjukkan dalam naskah soal. Serangan dunia nyata dapat melibatkan pemisahan string, Lookup alternatif, pengodean, protokol lain, dan variasi lain yang sulit dicakup hanya dengan tanda tangan.
Oleh karena itu, posisi praktisnya adalah sebagai berikut.
- Secara sementara blokir pola serangan yang sudah diketahui dengan WAF.
- Selidiki apakah pustaka yang terdampak benar-benar ada.
- Batasi lalu lintas keluar LDAP, RMI, dan HTTP yang tidak perlu.
- Perbarui ke versi yang sudah ditambal.
- Setelah memperbarui, tetap periksa log dan selidiki apakah terjadi pelanggaran.
WAF adalah lapisan yang membeli waktu sampai versi yang ditambal tersedia.
flowchart TB
accTitle: Tempat WAF dalam gambaran
accDescr: WAF adalah lapisan mitigasi sementara, perbaikan akar adalah memperbarui pustaka ke versi yang ditambal
A["Kerentanan kritis diungkapkan"] --> B["Konfirmasi dampak"]
B --> C["Mitigasi sementara"]
C -->|Aturan WAF<br/>deteksi/blokir| D["Hentikan sementara pola serangan"]
C -->|Batasi lalu lintas keluar| E["Tutup jalur penyalahgunaan"]
D --> F["Perbarui ke pustaka yang ditambal"]
E --> F
F --> G["Tinjauan setelah fakta dan pencegahan"]
Gambar 13: Tempat WAF dalam gambaran. WAF hanya membeli waktu sampai tambalan tiba; perbaikan akar adalah pembaruan.
13. Soal 3(4) — Mengapa mulai dengan “deteksi”
Untuk aturan WAF yang diperbarui, Z, seorang Spesialis Keamanan Terdaftar, menyarankan mengatur mode ke “deteksi” daripada “blokir” untuk jangka waktu tetap setelah aturan masuk produksi.
Soal menanyakan, masing-masing dalam 25 karakter atau kurang, manfaat memakai mode deteksi dan apa yang harus dilakukan untuk meminimalkan kerusakan.
Jawaban model adalah:
| Butir | Inti jawaban |
|---|---|
| Manfaat | Dapat mencegah pemblokiran akibat positif palsu |
| Apa yang dilakukan | Telaah apakah itu serangan setiap kali peringatan diterima |
Mode deteksi bukan mode “tidak melakukan apa-apa”
Dalam mode deteksi, lalu lintas yang cocok dengan aturan tetap diloloskan, tetapi dicatat dan peringatan dinaikkan. Meski string jndi atau ldap kebetulan muncul di dalam panggilan API yang sah, bisnis tidak dihentikan segera.
Sebagai gantinya, sisi operasi perlu melakukan yang berikut.
Peringatan diterima
|
v
Periksa permintaan yang bersangkutan
|
+-- Lalu lintas sah -> persempit aturan, pertimbangkan pengecualian
|
+-- Serangan -> isolasi sasaran, lestarikan log, selidiki dampak, pindah ke pemblokiran
Jika tidak ada yang melihat peringatan, mode deteksi tidak punya efek protektif sama sekali. Deteksi hanya bekerja berpasangan dengan proses operasional yang mengamati dan menilai.
Jalur dari deteksi ke pemblokiran
Prosedur peluncuran yang khas adalah sebagai berikut.
- Jalankan mode deteksi terhadap lalu lintas nyata.
- Klasifikasikan hit sebagai positif palsu atau positif benar.
- Sesuaikan header sasaran, jalur, API, batas kata, dan seterusnya.
- Pastikan dampak pada lalu lintas sah dapat diterima.
- Beralih ke mode pemblokiran.
- Pantau jumlah pemblokiran dan dampak bisnis.
Ini, bagaimanapun, adalah prinsip untuk waktu biasa. Ketika kerentanan kritis, sedang dieksploitasi secara aktif, dan tidak ada alternatif, pemadaman akibat pelanggaran dapat dinilai lebih besar daripada yang disebabkan positif palsu, dan pemblokiran sejak awal dipilih sebagai gantinya. Dalam skenario ujian, mode deteksi dipilih lebih dulu agar dapat mengonfirmasi bahwa layanan dapat terus beroperasi seperti sebelumnya.
flowchart LR
accTitle: Dari mode deteksi WAF ke mode blokir
accDescr: Amati peringatan dalam mode deteksi, sesuaikan positif palsu, lalu pindah ke mode blokir
A["Mode deteksi"] -->|Lalu lintas nyata| B["Peringatan dinaikkan"]
B --> C{"Serangan atau<br/>positif palsu"}
C -->|Positif palsu| D["Sesuaikan aturan"]
D --> A
C -->|Serangan| E["Beralih ke mode blokir"]
E --> F["Pantau jumlah blokir dan dampak bisnis"]
Gambar 14: Dari deteksi ke pemblokiran. Amati dan sesuaikan lebih dulu, pastikan dampak dapat diterima, lalu pindah ke pemblokiran.
14. WAF adalah tindakan sementara; pembaruan adalah perbaikan akar
Dalam soal, situs resmi pustaka H belum punya perbaikan maupun solusi sementara, dan bahkan aturan WAF komprehensif penyedia cloud akan memakan waktu hingga 72 jam. Jadi Perusahaan G mengonfirmasi dampak sendiri dan secara sementara memblokir setidaknya pola yang sudah diidentifikasi.
Urutan ini adalah bentuk dasar respons insiden.
| Tahap | Tujuan | Respons dalam soal ini |
|---|---|---|
| Konfirmasi dampak | Menilai apakah organisasi sendiri benar-benar berisiko | Konfirmasi eksploitabilitas dari luar dengan callback yang tidak berbahaya |
| Mitigasi sementara | Membeli waktu sampai perbaikan tiba | Aturan WAF, deteksi/blokir, pembatasan lalu lintas keluar |
| Perbaikan akar | Menghapus penyebab yang rentan | Perbarui ke pustaka yang ditambal |
| Tinjauan setelah fakta | Memeriksa apakah sudah dieksploitasi | Selidiki log WAF, aplikasi, DNS, proksi, dan lainnya |
| Cegah terulang | Mempercepat keputusan berikutnya | Inventaris dependensi, SBOM, prosedur pembaruan, jalur kontak |
“Kami tidak tahu apakah kami memakainya” adalah sumber penundaan terbesar
Dalam soal, bahkan ketika Perusahaan G menanyakan Perusahaan F apakah memakai pustaka H, jawaban memakan waktu karena analisis konfigurasi terperinci diperlukan.
Dalam praktik, jika Anda baru mulai mencari berkas JAR setelah kerentanan kritis diungkapkan, respons Anda tertunda. Anda seharusnya sudah punya setidaknya yang berikut pada masa damai.
- Inventaris dependensi langsung dan transitif.
- Komponen dan versi yang benar-benar disertakan dalam artefak Anda.
- Layanan, kontainer, dan perangkat mana tempat mereka diterapkan.
- Prosedur untuk memperbarui pustaka dependen dan membangun ulang/mendistribusikan ulang.
- Jalur kontak untuk menyetujui perubahan darurat.
- Tujuan yang diizinkan untuk lalu lintas keluar, dan dampak memblokirnya.
- Di mana log disimpan dan cara mencarinya.
SBOM bukan tujuan itu sendiri. Ia adalah indeks untuk menjawab, dalam waktu singkat, “sistem berjalan mana yang terdampak kerentanan ini”.
Jangan berhenti menyelidiki setelah Anda memperbarui
Anda mungkin sudah diserang sekitar waktu kerentanan diungkapkan. Memperbarui ke versi yang ditambal menghentikan eksploitasi di masa depan, tetapi tidak menghapus kredensial yang sudah dikompromikan atau pintu belakang yang sudah ditanam.
Untuk kerentanan tipe Log4Shell, selidiki setidaknya sudut berikut.
- Permintaan HTTP yang berisi string mencurigakan yang menunjukkan JNDI atau LDAP.
- Komunikasi dari server aplikasi keluar ke LDAP, RMI, atau HTTP eksternal.
- Proses anak yang tidak biasa diluncurkan.
- Pembuatan JAR, kelas, skrip, atau executable yang mencurigakan.
- Akses ke kredensial cloud atau variabel lingkungan.
- Autentikasi, perubahan izin, dan transfer keluar sekitar waktu pembaruan.
Penting untuk tidak menyimpulkan “kami tidak diserang” dari log WAF saja. Ada jalur internal yang tidak pernah melewati WAF, dan log yang tidak disimpan di masa lalu.
15. Cara membaca yang memudahkan meraih poin di ujian
Soal ini kurang ujian pengetahuan dan lebih latihan membaca celah antara spesifikasi dan implementasi.
15.1 Pisahkan “spesifikasi” dari “implementasi” dalam tabel
Pada isu status, nilai yang absen dari spesifikasi API lolos dalam implementasi.
Spesifikasi:
mid / name / age
Implementasi:
kirim semua parameter yang diterima ke P
Begitu Anda dapat melihat celah ini, menjadi jelas bahwa isian c adalah modul bersama P.
15.2 Garisbawahi nilai yang diubah penyerang
Nilai yang diubah pada tiap serangan adalah sebagai berikut.
algheader JWT- ID pengguna di payload JWT
- Parameter API
mid statusdi luar spesifikasiotpAPI autentikasi- Header HTTP
x-api-version
Hampir setiap soal menanyakan “di mana nilai itu harus diverifikasi”.
15.3 Kembalikan jawaban ke istilah naskah soal sendiri
Dalam praktik Anda dapat menyebut ini “BOLA”, “Mass Assignment”, dan “rate limiting”. Tetapi yang diminta soal adalah pemrosesan konkret yang cocok dengan struktur naskah soal.
Contoh buruk:
Lakukan otorisasi secara memadai.
Contoh baik:
Verifikasi apakah ID pengguna yang terkandung dalam JWT cocok dengan nilai mid.
Contoh buruk:
Ambil tindakan anti-brute-force.
Contoh baik:
Kunci akun begitu jumlah kegagalan beruntun melebihi ambang.
Mengetahui nama abstrak saja tidak menghasilkan jawaban yang dapat dinilai dalam batas karakter.
15.4 Untuk WAF, telusuri “di mana diletakkan”
Sasaran inspeksi WAF diputuskan bukan dengan menebak dari jenis serangan, melainkan dari di mana string serangan diletakkan.
Diletakkan ke header x-api-version
↓
Sasaran inspeksi adalah Header
Catatan komentar penilaian bahwa tingkat jawaban benar Soal 3(1) agak rendah juga karena banyak jawaban tidak cocok dengan alur serangan pada Gambar 6. Sekadar menggambar ulang urutan serangan dengan panah sudah mengungkapkan apa yang harus diamati.
16. Daftar periksa untuk tinjauan API di dunia nyata
Daftar periksa untuk membawa soal ini kembali ke rancangan dan tinjauan kode yang sebenarnya.
Verifikasi JWT
- Algoritme tanda tangan yang diizinkan ditetapkan di konfigurasi server.
nonedan algoritme tak terduga ditolak.- Tanda tangan,
iss,aud,exp, dannbfdiverifikasi sesuai kasus penggunaan. - ID token, access token, dan refresh token tidak dikacaukan satu sama lain.
- Ada prosedur untuk rotasi kunci dan pencabutan.
- Informasi yang harus tetap rahasia tidak dimasukkan ke payload JWT.
Otorisasi tingkat objek
- Mengubah ID di dalam permintaan tidak dapat mencapai data pengguna lain.
- Otorisasi ditegakkan pada daftar, detail, pembaruan, penghapusan, dan unduhan sama rata.
- Otorisasi ditegakkan di lapisan bersama yang mencapai data, bukan di layar.
- Untuk API khusus-diri, Anda mempertimbangkan menurunkan ID sasaran dari token sebagai gantinya.
- Operasi administrator memakai kebijakan terpisah dari API pengguna umum.
Otorisasi tingkat properti
- Tipe masukan eksternal dan entitas basis data dijaga terpisah.
- Bidang yang dapat diperbarui dienumerasi sebagai daftar izinkan.
- Properti di luar spesifikasi ditolak atau diaudit.
- Status seperti izin, penagihan, persetujuan, dan kepemilikan tidak dapat diubah dari masukan pengguna.
- Respons juga mengecualikan properti rahasia yang tidak perlu.
Percobaan autentikasi
- Ada batas hitungan kegagalan per akun.
- Ada penundaan bertahap dan kontrol per-sumber.
- Hitungan kegagalan tidak direset ketika kode diterbitkan ulang.
- Kode autentikasi hanya dapat dipakai sekali.
- Kode autentikasi dan kata sandi tidak ditinggalkan di log.
- Prosedur buka-kunci/pemulihan bukan sendiri jalur autentikasi yang lebih lemah.
Kerentanan kritis pada pustaka dependen
- Layanan yang berjalan dapat dipetakan ke versi dependensinya.
- Ada prosedur untuk memverifikasi dampak dengan metode yang tidak berbahaya.
- Tindakan sementara seperti aturan WAF dan pembatasan keluar dapat diterapkan.
- Ada proses operasional agar orang yang bertanggung jawab meninjau peringatan deteksi.
- Ada jalur rilis darurat untuk memperbarui ke versi yang ditambal.
- Log diselidiki untuk kemungkinan eksploitasi sebelum pembaruan.
17. Dua wajah komponen bersama, seperti yang terlihat lewat soal ini
Soal ini menampilkan dua komponen bersama: pustaka pengelolaan JWT Q dan modul bersama P.
Komponen bersama punya manfaat besar.
- Memperbaiki satu tempat menyebarkan perbaikan ke setiap API yang memakainya.
- Logika otorisasi dan verifikasi tidak harus diduplikasi ke setiap fitur.
- Sasaran uji dapat disatukan.
- Format log dan audit dapat diseragamkan.
Di sisi lain, kesalahan juga menyebar ke seluruh sistem.
- Jika pustaka Q menerima
alg=none, setiap API yang memakai JWT menjadi rentan. - Jika modul bersama P menerima
midataustatussembarang, GET maupun PUT menjadi rentan. - Jika pustaka H yang rentan dipakai di fondasi, setiap rute yang mencatat header HTTP menjadi bagian dari permukaan serangan.
Oleh karena itu, yang harus dibagi bukan semata akses data. Perlu membagi invarian keamanan itu sendiri, dan memverifikasi komponen bersama itu secara ketat secara terpisah.
Misalnya, buat kontrak P sebagai berikut.
P.getOwnUser(authenticatedSubject)
P.updateOwnProfile(authenticatedSubject, ProfileUpdate{name, age})
Lebih aman untuk tidak mengekspos API tingkat rendah seperti berikut secara langsung ke pemanggil biasa.
P.getUser(arbitraryMid)
P.updateUser(arbitraryMap)
Yang terakhir hanya dibutuhkan oleh himpunan rute terbatas, seperti pemrosesan administratif. Menyerahkan kebebasan tingkat rendah itu ke setiap API menghasilkan rancangan yang bergantung pada setiap pemanggil memakainya dengan benar, setiap kali.
18. Ringkasan
Soal 1 PM musim semi 2024 (Reiwa 6) adalah soal yang membaca terpisah topik keamanan API satu per satu.
Memakai JWT tidak berarti autentikasi aman. Membiarkan penyerang memilih algoritme tanda tangan memungkinkan ID pengguna ditulis ulang.
Tanda tangan JWT yang sah tidak berarti otorisasi benar. Mempercayai mid permintaan memungkinkan pengguna sah mengakses informasi orang lain.
Bisa memperbarui objek sendiri tidak berarti setiap properti boleh diubah. Mengikat otomatis status internal seperti status memungkinkan izin atau status penagihan ditulis ulang.
Adanya kedaluwarsa pada kode autentikasi tidak berarti kode itu tahan brute-force. Anda perlu menghitung ruang kandidat dan kecepatan percobaan, dan membatasi jumlah kegagalan.
Memasukkan aturan ke WAF tidak berarti kerentanan diperbaiki. Deteksi dan pemblokiran hanya membeli waktu; Anda mengonfirmasi dampak dan pada akhirnya memperbarui pustaka.
flowchart TB
accTitle: Pemetaan kerentanan ke tindakan
accDescr: Memetakan setiap kerentanan ke batas kepercayaannya dan tindakannya
A["Pemalsuan JWT"] -->|Verifikasi token| B["Tetapkan algoritme yang diizinkan"]
C["Penukaran mid"] -->|Otorisasi tingkat objek| D["Cocokkan dengan subject JWT/mid tidak perlu"]
E["status=paid"] -->|Otorisasi tingkat properti| F["Jadikan DTO pembaruan daftar izinkan"]
G["Brute-force kode 4 digit"] -->|Kontrol percobaan autentikasi| H["Batas kegagalan/penundaan"]
I["Kerentanan tipe Log4Shell"] -->|Masukan ke eksekusi| J["Pembaruan pustaka/WAF"]
Gambar 15: Pemetaan kerentanan ke tindakan. Pisahkan perbaikan menurut batas mana yang dipecahkan.
Satu prinsip menembus seluruh soal ini.
Jangan pernah membiarkan keberhasilan pemeriksaan sebelumnya menjadi alasan untuk melewatkan batas kepercayaan berikutnya.
Artikel sebelumnya dalam seri ini membahas kerentanan XSS tersimpan pada Soal 1 PM musim gugur 2023 (Reiwa 5) dan pengeluaran data lewat Wi-Fi tamu pada Soal 2 PM musim gugur 2023 (Reiwa 5). Untuk pandangan tentang apa yang diperiksa di seluruh situs web, lihat juga Memakai “How to Secure Your Website” IPA sebagai daftar periksa.
flowchart TB
accTitle: Ringkasan akhir
accDescr: Menunjukkan bahwa keberhasilan pemeriksaan sebelumnya tidak pernah menjadi alasan untuk melewatkan batas kepercayaan berikutnya
A["Autentikasi berhasil"] --> B["Verifikasi tanda tangan JWT"]
B --> C["Otorisasi tingkat objek"]
C --> D["Otorisasi tingkat properti"]
D --> E["Batas laju percobaan"]
E --> F["Batas masukan-ke-eksekusi"]
F --> G["WAF/pembaruan pustaka"]
Gambar 16: Ringkasan akhir. Batas kepercayaan diperiksa secara bertahap, dan tidak satu pun boleh dilewatkan.
Tautan referensi
-
IPA, Spring 2024 (Reiwa 6) Registered Information Security Specialist Examination, PM Question Booklet. Naskah soal yang menjadi dasar artikel ini. ↩
-
IPA, Spring 2024 (Reiwa 6) Registered Information Security Specialist Examination, PM Model Answers. Jawaban model resmi untuk tiap soal. ↩
-
IPA, Spring 2024 (Reiwa 6) Registered Information Security Specialist Examination, PM Grading Commentary. Penjelasan tingkat jawaban benar dan kesalahan yang umum. ↩
-
NIST, SP 800-63B: Authentication and Authenticator Management. Menetapkan jumlah digit untuk rahasia jangka pendek, batas laju percobaan, hitungan kegagalan saat terbit ulang, dan tidak memakai email untuk autentikasi di luar pita, di antara persyaratan lain. ↩ ↩2
-
RFC Editor, RFC 7519: JSON Web Token (JWT). Spesifikasi JWT, termasuk Unsecured JWT dan
alg=none. ↩ -
RFC Editor, RFC 8725: JSON Web Token Best Current Practices. BCP yang menetapkan penetapan himpunan algoritme yang diizinkan, serta verifikasi penerbit, subjek, dan audience, di antara praktik lain. ↩
-
OWASP, API1:2023 Broken Object Level Authorization. Menjelaskan kebutuhan memeriksa otorisasi untuk setiap ID objek yang ditentukan pengguna. ↩
-
OWASP, API3:2023 Broken Object Property Level Authorization. Menjelaskan celah otorisasi tingkat properti, termasuk Mass Assignment, dan tindakannya. ↩
-
Apache Logging Services, Security. Menjelaskan dampak CVE-2021-44228, eksekusi kode lewat JNDI dan LDAP, dan versi yang diperbaiki. ↩
Artikel terkait
Artikel terbaru dengan tag yang sama untuk mendalami topik-topik terdekat.
Kedalaman virtualisasi Windows (Bagian 3) — Mesin virtual yang boot dalam hitungan detik: mengapa WSL2, Windows Sandbox, dan kontainer begitu ringan
Mengapa WSL2 dan Windows Sandbox start dalam hitungan detik dan terasa begitu ringan? Artikel ini menjelaskan mekanismenya, dari dynamic ...
Kedalaman virtualisasi Windows (Bagian 2) — Memori yang bahkan kernel pun tidak bisa lihat: cara kerja VBS, HVCI, dan Credential Guard
Pada instalasi bersih ke perangkat keras yang kompatibel, VBS diaktifkan secara bawaan dan memakai hypervisor serta SLAT untuk membuat is...
Kedalaman virtualisasi Windows (Bagian 1) — Di mana Windows Anda sebenarnya berjalan? Hypervisor dan partisi
Ketika Anda mengaktifkan Hyper-V, Windows host sendiri berjalan di atas hypervisor sebagai root partition. Artikel ini menjelaskan fondas...
Win32 Thread Pool API — konkurensi tanpa membuat thread, lewat CreateThreadpoolWork
Apakah Anda menebar panggilan CreateThread di seluruh kode native? Artikel ini menjelaskan Win32 thread pool API yang didesain ulang di V...
Named pipes dalam praktik — IPC standar Windows dari desain hingga keamanan
Panduan praktis tentang named pipe, komunikasi antarpproses standar di Windows. Artikel ini menata, dari sumber primer, pilihan antara mo...
Topik terkait
Halaman-halaman ini menempatkan topik dalam konteks layanan dan keputusan yang lebih luas.
Topik teknis Windows
Portal tentang pengembangan Windows, investigasi bug, dan pemanfaatan aset yang ada.
Layanan yang terkait dengan topik ini
Artikel ini berkaitan langsung dengan layanan berikut.
Pengembangan situs web
Karena pada API anggota dan integrasi ponsel, verifikasi JWT, otorisasi tingkat objek, dan pembatasan properti yang dapat diperbarui langsung menentukan keamanan sistem web itu sendiri.
Konsultasi teknis dan tinjauan desain
Karena mengidentifikasi celah otorisasi pada API yang ada, menilai jangkauan dampak pustaka dependen, dan merancang aturan WAF sementara lewat tinjauan desain semuanya termasuk lingkup konsultasi teknis.
Pertanyaan yang sering diajukan
Pertanyaan yang sering muncul dalam konsultasi tentang topik artikel ini.
- Mengapa penyerang bisa menyamar sebagai orang lain meskipun verifikasi tanda tangan JWT berhasil?
- Dalam soal ini, pustaka pengelolaan JWT menerima alg pada header JWT persis seperti yang ditentukan penyerang, dan memperlakukan JWT dengan alg=none sebagai sah tanpa tanda tangan sama sekali. Jadi menulis ulang ID pengguna di payload tetap lolos verifikasi. Jawaban ujian adalah memverifikasi alg pada header JWT dan memastikan nilainya bukan NONE. Namun dalam praktik, menolak hanya NONE tidak cukup. Tetapkan algoritme yang diizinkan — misalnya RS256 — di konfigurasi sisi server, agar algoritme yang dideklarasikan token tidak pernah dipakai langsung untuk memilih metode. Anda juga harus memverifikasi issuer, audience, kedaluwarsa, subject, dan seterusnya, sesuai kasus penggunaan.
- Apakah membandingkan ID pengguna di dalam JWT dengan mid permintaan sudah cukup sebagai tindakan otorisasi?
- Untuk jawaban ujian ini, itu cukup. Memverifikasi, di dalam modul bersama P, bahwa ID pengguna di JWT cocok dengan mid menghentikan serangan yang menyebutkan mid orang lain. Namun, untuk API yang hanya menangani informasi pemanggil sendiri, lebih aman dalam praktik untuk tidak menerima mid dari klien sama sekali, dan menentukan ID pengguna dari subject JWT yang sudah diverifikasi. Memakai GET /users/me atau PUT /users/me membuat logika perbandingan lebih sulit terlewat. API tempat administrator mengoperasikan pengguna lain harus dipisah ke endpoint sendiri dengan kebijakan otorisasi tersendiri.
- Mengapa validasi masukan biasa saja tidak bisa menghentikan serangan yang menambahkan status?
- Karena meski Anda memvalidasi panjang name atau rentang age, itu tidak berguna jika status — bidang yang seharusnya tidak pernah diterima — diikat otomatis dan diteruskan langsung ke objek internal. Masalahnya bukan format nilai; melainkan otorisasi tingkat properti, yaitu apakah pengguna boleh mengubah properti itu sama sekali. Definisikan hanya name dan age pada tipe masukan pembaruan, dan tolak properti yang tidak dikenal. Status penagihan hanya boleh diubah dari peristiwa yang dipercaya server, misalnya hasil sukses dari layanan pembayaran.
- Kode autentikasi empat digit kedaluwarsa setelah 10 menit — mengapa tetap berbahaya?
- Karena hanya ada 10.000 kandidat dari 0000 sampai 9999, dan pada 10 percobaan per detik penyerang berhasil setelah rata-rata 5.000 percobaan — 500 detik. Masa berlaku 10 menit adalah 600 detik, jadi mencoba kandidat tanpa pengulangan secara berurutan memungkinkan penyerang memeriksa 6.000 di antaranya dalam jendela itu. Waktu kedaluwarsa saja tidak bisa menghentikan brute-force. Ruang kandidat, kecepatan percobaan, dan batas jumlah percobaan harus dirancang bersama.
- Tindakan ujian adalah penguncian akun — apakah penguncian segera saja juga cukup dalam praktik?
- Tidak. Isian pada soal menuntut logika yang mengunci akun begitu jumlah kegagalan beruntun melebihi ambang, tetapi kunci tetap dan permanen saja memungkinkan penyerang sengaja mengunci akun orang lain sebagai denial-of-service. Dalam praktik, gabungkan hitungan kegagalan per akun dengan waktu tunggu bertahap, penilaian risiko sumber dan perangkat, notifikasi, dan prosedur pemulihan. Penting juga bahwa menerbitkan kode baru tidak mereset hitungan kegagalan kembali ke nol.
- Apa gunanya mengatur WAF ke deteksi, bukan pemblokiran?
- Artinya lalu lintas bisnis yang sah tidak dihentikan meski string normal keliru dinilai sebagai serangan. Dalam jawaban model, manfaatnya adalah mencegah pemblokiran akibat positif palsu, dan yang harus dilakukan adalah menelaah apakah itu serangan setiap kali peringatan diterima. Mode deteksi bukan pengaturan yang dibiarkan begitu saja. Mode ini dipakai sebagai masa observasi: Anda memeriksa log, menyaring positif palsu, menyesuaikan aturan, lalu pindah ke pemblokiran. Dalam keadaan darurat ketika kerentanan kritis yang sudah diketahui sedang dieksploitasi, wajar menimbang itu terhadap risiko ketersediaan dan memilih memblokir sejak awal.
- Apakah pustaka H dalam soal ini Log4j?
- Soal menyembunyikan nama produk, tetapi urutan serangan — JNDI Lookup, server LDAP, pengambilan kelas dari server HTTP, string yang disematkan di header HTTP, dan skor dasar CVSS v3.1 yang tinggi — terbaca alami sebagai abstraksi CVE-2021-44228, yang dikenal sebagai Log4Shell. Artikel ini menjelaskan korespondensi itu, tetapi ujian tidak mensyaratkan Anda menamai produk spesifik. Soal dapat dijawab semata dari prosedur serangan yang diberikan dan spesifikasi WAF.
- Apa yang harus dibawa kembali ke praktik dari soal ini?
- Bahwa berhasil autentikasi, JWT tidak diubah, diizinkan mengakses objek sasaran, dan diizinkan mengubah properti sasaran adalah pemeriksaan yang terpisah. Di atas itu, kode autentikasi pendek memerlukan batas laju percobaan, dan untuk kerentanan pustaka kritis Anda menjalankan konfirmasi dampak, pertahanan sementara, dan perbaikan akar secara paralel. Inti yang dibawa ke praktik: satukan otorisasi ke komponen bersama, jadikan skema masukan sebagai daftar izinkan, tetapkan syarat verifikasi JWT di sisi server, dan lacak pustaka dependen agar dapat diperbarui.
Profil penulis
Halaman perkenalan penulis artikel.
Go Komura
Direktur KomuraSoft LLC
Berspesialisasi dalam pengembangan perangkat lunak Windows, konsultasi teknis, dan investigasi bug, terutama pada proyek dengan sistem yang sudah ada dan bug yang sulit direproduksi.