[Cyber Jawara 2018 Qualification] – Login Form

Diberikan sebuah website dengan source code sebagai berikut:

Website ini mengharuskan kita untuk memasukkan input yang akan divalidasi dan memunculkan flag.

Pertama, mari kita lihat fungsi login.

Fungsi login tersebut menerima 2 parameter yakni username dan hash. Dalam fungsi tersebut akan dilakukan validasi jika variabel username berisi “CJ” dan variabel hash berisi “81eb1cf42dc766553d51bc73d70adebe8607031b” maka fungsi tersebut akan return true. Sebaliknya jika tidak maka akan return false. Hmm, terlihat biasa saja.

Berikutnya mari kita melihat fungsi render_login_page.

Disini terlihat bahwa fungsi tersebut hanya memunculkan isi dari file “template.html”. Tidak begitu berpengaruh.

Berikutnya mari kita lihat fungsi init.

Wah, panjang sekali isi fungsinya xD. Sebaiknya kita coba melihat fungsi tersebut per bagian.

Pertama untuk bagian ini terlihat bahwa jika variable $_SERVER di array QUERY_STRING mempunyai isi (informasi lebih lanjut mengenai $_SERVER dapat dilihat di http://php.net/manual/en/reserved.variables.server.php), maka akan dilakukan parsing dengan menggunakan fungsi parse_str yang ada di PHP (informasi lebih lanjut mengenai parse_str di PHP dapat dilihat di link http://php.net/manual/en/function.parse-str.php ). Fungsi ini nantinya akan berguna untuk kita menyelesaikan soal ini.

Sekarang, mari kita lihat validasi berikutnya.

Validasi ini hanya berfungsi untuk set variabel action jika isi variabel action tidak kosong.

Ke validasi berikutnya.

Berlanjut dari validasi sebelumnya, jika variable action  memiliki value ‘login’ maka akan menjalankan isi dari if statement.

Lalu untuk didalam validasi tersebut ada validasi lagi dimana jika hasil parse_str tadi di bagian username dan password tidak kosong, maka variabel username dan password akan di set dari $query[‘username’] dan $query[‘password’].

Lanjut ke validasi berikutnya.

Di validasi ini, jika isi dari variabel username dan password tidak kosong, maka isi dari variabel password akan di hash dengan menggunakan metode hashing SHA1. Setelah itu, akan ada validasi lagi dimana jika isi dari variabel hash tidak kosong DAN hasil dari fungsi login adalah true, maka flag akan di print.

Lalu bagaimana kita mendapatkan flag? Apa yang dapat kita gunakan untuk mendapatkan flag padahal hash yang ada di source tidak dapat dilihat plaintext-nya.

Nah mari kita bahas bagian yang vulnerable dari source code ini.

Pada code bagian ini, dilihat bahwa fungsi parse_str hanya berisi 1 parameter. Jika kita lihat dari laman http://php.net/manual/en/function.parse-str.php dapat diketahui bahwa parse_str pada dasarnya menerima 2 parameter, namun untuk parameter kedua itu tidak wajib (opsional). Apa bedanya jika kita isi parameter kedua dan jika kita tidak mengisi parameter kedua?

Berikut ilustrasinya:

 

Dari contoh diatas terlihat bahwa hasil dari parse_str dimasukkan ke dalam sebuah dictionary yang punya referensi nama. Sedangkan bila kita tidak mengisi parameter kedua.

 

Dari contoh diatas dapat diketahui jika kita tidak mengisi parameter kedua, maka nama parameter yang dikirim dari client akan menjadi nama variable itu sendiri setelah di parse.

Lalu apa yang bisa kita lakukan dari informasi diatas?

Jika kita review:

  1. parse_str dari php tidak di isi parameter keduanya
  2. Validasi ke flag meminta $username berisi ‘CJ’ dan $hash berisi ’81eb1cf42dc766553d51bc73d70adebe8607031b’

Dari kedua informasi tersebut kita bisa mengirimkan variable hash dan username yang diisi dengan value username ‘CJ’ dan hash ’81eb1cf42dc766553d51bc73d70adebe8607031b’. Tapi ingat, jangan mengisi variable password. Kenapa? Karena jika diisi maka kita akan terkena validasi di:

Sehingga value dari variabel hash akan berubah. Dengan kita mengirimkan payload seperti

action=Login&username=CJ&hash=81eb1cf42dc766553d51bc73d70adebe8607031b

Sudah cukup untuk membawa kita ke flag.

Leave a Reply

Your email address will not be published. Required fields are marked *