fikriauliya / realcount

Realcount pilpres 2014
10 stars 13 forks source link

Current abuse detection algorithm can be abused easily :D #12

Open fikriauliya opened 9 years ago

fikriauliya commented 9 years ago

FYI, saat ini abuse dieliminir dengan match entry dari user lain untuk TPS yang sama. Hanya jika ada > 1 entry yang SAMA, maka isian itu akan counted.

For example, untuk TPS #101, user A first entered [Prabowo: 15, Jokowi: 16, Broken: 2]. Input ini saja belum dianggap valid. Kemudian jika ada user B entered [Prabowo: 15, Jokowi: 16, Broken: 2], maka input itu baru dianggap valid. Tapi jika user B enterd [Prabowo: 105, Jokowi: 216, Broken: 2], maka semua input TPS #101 dianggap invalid.

Algo ini bisa Eve abuse dengan enter random numbers ke semua TPS, maka semua input akan invalidated :P. Ini bisa diprevent dengan ambil majority vote. Tapi sekali lagi bisa diabuse jika Eve, Mallory, dan Charlie kerja sama melakukan itu semua.

Saya rasa solusinya tetap butuh manual human report untuk hal ini.

rulimanurung commented 9 years ago

Saya rasa solusinya yang paling baik (tanpa melibatkan manual judgment) tetap majority vote, tetapi kita buat susah untuk Eve, Mallory, dan Charlie bekerjasama. Karena TPS yang dikerjakan diassign secara random, dan mereka tidak bisa specify TPS mana yang mau diisi, maka sulit untuk mereka berkoordinasi.

Lihat poin 1.1.1.2 di https://docs.google.com/document/d/1M8nVgVARp4ymg5G7NPnGqR3qvh5TiPYjXM8FIMKuH_I/edit?usp=sharing :-)

rulimanurung commented 9 years ago

BTW, untuk kasus A dan B meng-entry nilai yang berbeda, solusinya adalah panggil n-th crowdsourcer. Saya punya ide begini: jadi pertama-tama kita lakukan 1 pass supaya semua TPS di-entry. Lalu kita lakukan 2nd pass supaya semua TPS dapat 2nd opinion sebagai validator. Selanjutnya, kita assign TPS untuk dikerjakan berdasarkan fungsi prioritas, di mana kita hitung rasio majority vote / all votes, dan pilih yang paling minimal untuk dikerjakan. Mis. ada TPS yang ada 2 entry dan klop, maka rasionya 1 (2/2), tapi untuk TPS dengan differing opinion, rasionya 0.5 (1/2). Diprioritaskan. Selanjutnya, ketika ada tiebreaker menjadi 0.66 (2/3), tapi kalau ternyata malah beda lagi, menjadi 0.33 (1/3). Tanpa intervensi, fungsi ini akan meng-assign TPS yang paling perlu di-resolve secara otomatis :-)

rulimanurung commented 9 years ago

BTW @fikriauliya mohon maaf di https://www.facebook.com/ruli.manurung/posts/10152252276276279 tadi pagi saya sempat bilang ada "kesalahan" dalam coding, tapi rupanya anda sudah mengimplementasikan data entry validation dengan second opinion ini. Saya sudah ralat statusnya. Maaf ya :-)

fikriauliya commented 9 years ago

"Karena TPS yang dikerjakan diassign secara random, dan mereka tidak bisa specify TPS mana yang mau diisi" => satu orang bisa bikin banyak sekali bots yang secara periodik keep mengisi random value (within reasonable range) untuk tiap TPS yang disodorkan. Agar attacknya tidak terdetect dengan mudah, jumlah bots yang dibikin perlu banyak, dan masing2 bots hanya mengisi ~100-200 TPS. Jika ingin mensabotase 100,000 TPS (which is large enough), hanya perlu 500 bots. (solusi: CAPTCHA, tapi membuat proses pengisian jadi lebih lama, dan membuat user tidak nyaman)

Moreover, satu lagi celah: current user's assigned tps_id sekarang adalah hidden value di HTML Form yang akan di POST dalam satu request yang sama dengan isian vote yang dinilai. Siapapun bisa dengan mudah mengganti value tersebut sehingga bisa pick tps_id yang ingin di abuse. Design awal saya, current_user's tps_id disimpan di server side session. Hanya belum sempat diimplementasikan saja waktu itu :)

Saya argument saya ini terlalu berlebihan untuk aplikasi simple seperti ini, mungkin tidak ada yang berpikir jauh seperti itu (background saya di IT Security, jadi kepikiran ide2 jahil ini :P). Nevertheless, ini bisa jadi masukan yang bagus untuk sistem crowdsourcing secara general.

rulimanurung commented 9 years ago

Good point. Saya nggak kepikiran serangan pasukan bots. CAPTCHA menjadi wajib, tetapi mungkin tidak harus untuk setiap form. Mungkin setiap n TPS dengan n random tapi cukup besar (>25? 50?) .

SeiryuZ commented 9 years ago

Moreover, satu lagi celah: current user's assigned tps_id sekarang adalah hidden value di HTML Form yang akan di POST dalam satu request yang sama dengan isian vote yang dinilai. Siapapun bisa dengan mudah mengganti value tersebut sehingga bisa pick tps_id yang ingin di abuse. Design awal saya, current_user's tps_id disimpan di server side session. Hanya belum sempat diimplementasikan saja waktu itu :)

Sorry baru nimbrung lagi. Untuk yang ini kita bisa pakai HMAC based authentication. Saya sering implementasi ini untuk authentication user action

Workflow nya seperti ini

  1. Setiap kali user di kirimkan data TPS untuk di isi. Kita generate authentication key yang di derive dari (tps_id + user_id)
  2. Ketika form di submit, dia akan submit dengan request.POST dengan parameter tps_id dan authentication_key yang di generate di no.1
  3. Form hanya akan valid apabila authentication key nya match (Kita check tps_id dan user_id yang submit form apakah menghasilkan authentication_key yang sama dengan yang di kirim di no.2)

Jadi karena untuk setiap action (setiap submit form tps) dia akan generate authentication_key berbeda, orang ga bisa asal tembak TPS yang dia mau.

Kodenya kurang lebih kayak gini, copas dari stackoverflow functionnya (http://stackoverflow.com/questions/4084979/ruby-way-to-generate-a-hmac-sha1-signature-for-oauth)

def hmac_sha1(data, secret=HOST_KEY)
    require 'base64'
    require 'cgi'
    require 'openssl'
    hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))
    return hmac
end

authentication_key = hmac_sha1("#{tps_id}#{user_id}", secret='SECRET_KEY_RAILS_APP')

Karena orang lain bisa lihat secret_key nya yang sekarang, sebaiknya sekarang kita masukkan ke .gitignore dan di server heroku diubah, atau kita pakai os.ENVIRONMENT untuk simpen secret_key yang baru nya