Websitenya baru dibuat, tetapi member-nya sudah banyak. Kedengarannya seperti kabar baik, sampai saya membuka artikel dan melihat ribuan komentar.

Semuanya dari akun yang tidak saya kenal. Menghapusnya satu per satu tidak mungkin, dan menghapus per halaman hanya bisa sekitar 40 item sekali jalan. Akhirnya saya memakai WP Bulk Delete untuk membersihkan semuanya sekaligus. Sementara itu, setiap pendaftaran palsu tetap memicu notifikasi register, dan notifikasi itu terus terkirim.

Sejak itu, di hampir semua website yang saya bangun, form register tidak saya buka untuk umum. Saya ingin setiap akun punya alasan untuk ada.

Prinsipnya sederhana: akun dibuat ketika ada sesuatu yang dimiliki. Pesanan, akses kelas, langganan, atau keanggotaan. Kalau belum ada yang dimiliki, belum perlu ada akun.

Dua cara akun lahir
Pintu terbuka

Register untuk umum

  1. Form register publikSiapa pun bisa mengisi, termasuk bot.
  2. Akun langsung dibuatBelum ada yang dimiliki.
  3. Akibatnya
    • Ribuan komentar spam
    • Notifikasi terkirim ke data palsu: kredit email habis, nomor WhatsApp kena ban
    • Celah Subscriber+ terbuka untuk siapa saja
Pintu dijaga

Akun dari transaksi

  1. CheckoutAda sesuatu yang ingin dimiliki.
  2. Verifikasi email dan WhatsAppVerifikator adalah sumber kepercayaan.

    Tidak valid, timeout, atau disposable: ditolak. Order palsu berhenti di sini.

  3. Order dan akun dibuatBerisi pesanan atau akses yang jelas.
  4. Notifikasi sampai ke orang sungguhanPemilik bisnis bisa tenang melihat order masuk.

Yang sebenarnya terjadi saat pintu register dibuka

Di WordPress, membuka register cukup satu centang: Anyone can register di pengaturan umum. Dari luar terlihat tidak berbahaya. Paling-paling ada beberapa akun spam.

Masalahnya, centang itu mengubah siapa saja yang bisa melewati batas “sudah login”. Dan di banyak sistem, batas itulah yang paling banyak dipercaya.

Lima alasan saya menutupnya

1. Celah “khusus pengguna login” berubah menjadi celah publik

Laporan kerentanan plugin WordPress sering diberi label Authenticated (Subscriber+). Artinya, penyerang harus punya akun, minimal level Subscriber. Label itu sering dibaca sebagai “risikonya kecil, harus login dulu”.

Tetapi kalau siapa pun bisa mendaftar, syarat itu tidak berarti apa-apa. Penyerang cukup register, lalu memanfaatkan celahnya. Situs yang tidak membuka register tidak otomatis kebal. Namun ia tidak memberikan kunci pintu itu kepada semua orang.

2. Bot akan datang, dan mereka tidak lelah

Form register publik adalah target otomatis. Ribuan komentar tadi hanyalah gejala yang terlihat. Di belakangnya, akun palsu memenuhi database dan membuat pelanggan asli sulit ditemukan di antara nama-nama acak.

3. Setiap pendaftaran palsu memicu notifikasi, dan notifikasi ada harganya

Setiap register mengirim sesuatu: email selamat datang, konfirmasi, atau pesan WhatsApp. Untuk email, akibat yang paling terasa adalah kredit pengiriman yang habis untuk alamat palsu. Kalau terus berlanjut, reputasi domain pengirim ikut terancam, dan email penting seperti invoice bisa masuk spam.

WhatsApp lebih keras. Nomor yang mengirim notifikasi register ke ratusan nomor tidak dikenal terlihat seperti nomor spam. Nomor pengirim saya akhirnya kena ban, minimal ban sementara. Padahal nomor yang sama dipakai untuk melayani pelanggan yang sungguhan.

4. Data pribadi tanpa tujuan adalah beban

Akun berisi nama, email, kadang nomor telepon. Menyimpan data orang tanpa memberikan layanan apa pun hanya menambah tanggung jawab, tanpa menghasilkan apa-apa.

5. Akun kosong membingungkan penggunanya sendiri

Orang yang mendaftar lalu login ke akun tanpa isi akan bertanya, “terus saya ngapain di sini?”. Akun yang lahir dari pembelian langsung punya jawaban: pesanan, file, atau akses yang sudah dibayar.

Model pengganti: akun lahir dari transaksi

Untuk ecommerce atau membership, saya memilih akun dibuat otomatis saat checkout. Pembeli tidak perlu mengisi form register terpisah. Akun muncul karena ada transaksi, dan isinya jelas sejak awal.

Tetapi memindahkan pintu tidak sama dengan menjaganya. Pernah dalam satu malam masuk 34 order. Awalnya saya senang: kok laku banyak? Lalu saya sadar semua data pendaftarnya palsu. Bot tidak perlu membayar untuk membuat order yang menunggu pembayaran, dan setiap order tetap membuat akun serta mengirim notifikasi. Ada website lain yang dalam satu malam menerima sekitar 300 order palsu.

Jadi checkout juga punya jebakan yang perlu ditutup:

  • Data pembeli harus diverifikasi sebelum order dibuat. Tanpa itu, checkout hanyalah form register dengan nama lain.
  • Email belum tentu milik pembeli. Siapa pun bisa checkout dengan email orang lain. Akun yang terbentuk sebaiknya baru bisa dipakai setelah pemilik email membuktikan kepemilikannya.
  • Jangan kirim password lewat email. Kirim tautan untuk membuat password sendiri.
  • Email yang sudah terdaftar. Tautkan pesanan ke akun yang ada, tetapi jangan otomatis me-login-kan pembelinya. Kalau tidak, checkout bisa menjadi jalan pintas masuk ke akun orang lain.

Verifikator adalah sumber kepercayaan

Verifikasi email tidak cukup hanya mengecek format. Alamat bisa terlihat valid, domainnya ada, tetapi kotaknya tidak pernah menerima apa pun. Ada juga alamat sekali pakai (disposable) yang memang valid, hanya saja dibuang setelah dipakai.

Kebijakan saya sederhana: kalau verifikator bilang tidak valid, atau tidak memberi jawaban sampai batas waktu, alamat itu ditolak.

Kebijakan ini memang menimbulkan keluhan. Ada pembeli yang protes emailnya disebut bodong, padahal domainnya valid. Ternyata server email mereka tidak merespons verifikator sampai timeout. Saya tetap meminta mereka memakai alamat lain, dan alamat gratis seperti Gmail tidak masalah. Kalau verifikator saya jadikan sumber kepercayaan, saya tidak bisa membuat pengecualian setiap kali jawabannya tidak nyaman.

Salah ketik justru kasus yang paling mudah. Verifikator bilang tidak valid, dan pengguna akan memeriksa lagi apa yang ia ketik.

Ternyata website lain juga mengalaminya

Setelah itu saya tahu masalah yang sama dialami banyak pengguna Sejoli lain. Order palsu, member palsu, dan notifikasi yang terbuang. Dari situ lahir Addon Sejoli Register Form Builder, produk saya sendiri: form register untuk Sejoli dengan verifikasi email yang menolak alamat palsu maupun disposable, serta verifikasi WhatsApp agar nomor yang masuk benar-benar aktif.

Pengguna WooCommerce juga banyak mengalaminya. Untuk kasus-kasus itu saya menyelesaikannya dengan snippet kustom, bukan plugin. Artinya, yang penting adalah prinsipnya. Bentuk solusinya bisa menyesuaikan.

Kapan register terbuka memang wajar

Ada situs yang memang butuh pendaftaran tanpa transaksi: komunitas, forum, kelas gratis, atau B2B yang memerlukan persetujuan. Untuk situs seperti itu, register boleh dibuka, asalkan ada pengamannya:

  • verifikasi email yang menolak alamat tidak valid, timeout, dan disposable;
  • verifikasi nomor bila nomor WhatsApp memang dibutuhkan;
  • pengaman bot seperti Turnstile atau honeypot, ditambah pembatasan laju (rate limit);
  • role default serendah mungkin;
  • persetujuan manual bila komunitasnya kecil.

Di luar WordPress

Saya belajar ini di WordPress, tetapi prinsipnya tidak terikat stack.

Di WordPress Prinsipnya Di aplikasi lain
Celah plugin Subscriber+ Batas “sudah login” adalah garis pertahanan Endpoint yang hanya mengecek login, bukan hak akses. OWASP menempatkan Broken Access Control di peringkat pertama
Bot memenuhi daftar user dan komentar Akun gratis adalah sumber daya yang bisa disalahgunakan Pendaftaran berulang untuk memanen kredit trial, termasuk kredit API AI
Order palsu dari checkout Transaksi yang belum dibayar tetap menghasilkan data dan notifikasi Pre-order, booking, atau trial tanpa kartu yang diserbu bot
Email disposable Identitas harus memakai saluran yang benar-benar dimiliki Penyalahgunaan trial, multi-akun, referral palsu
Nomor WhatsApp pengirim kena ban Setiap pendaftaran memicu biaya dan risiko reputasi OTP via SMS/WhatsApp yang dipicu bot, dan Anda yang membayar

Bedanya, di WordPress risiko sering datang dari kode pihak ketiga yang tidak kita kendalikan. Di aplikasi yang kita tulis sendiri, risikonya pindah ke kode otorisasi kita sendiri. Polanya tetap sama.

Ringkasnya

Sebelum membuka pendaftaran, tanyakan satu hal: apa yang akan dimiliki orang ini setelah punya akun? Kalau jawabannya belum ada, pintunya belum perlu dibuka. Kalau sudah ada, pintunya tetap perlu dijaga.

Setiap pemilik bisnis layak merasa tenang ketika melihat order masuk, tanpa bertanya-tanya berapa di antaranya yang sungguhan.

Sumber & referensi

Dwindi Ramadhana

Belajar web secara otodidak, dari template Blogspot sampai plugin WordPress. Sejak 2021 membuat produk sendiri, dan sekarang membangun lintas stack. Yang saya tulis di sini adalah pelajaran dari proses itu.

Tentang saya →