Individual Review #5 — Jihad
Hi semuanya, kali ini saya akan berbagi pengetahuan yang saya miliki terkait penetration/stress testing, Automatic Data Seeding/Migration, dan Mock Test
Penetration dan Stress Test
Stress test?! Bikin test kok malah bikin stress? Bukan itu kok maksudnya, Stress test merupakan bentuk test yang digunakan untuk memeriksa performa aplikasi dengan nilai maksimum atau melebihi kapasitas request dan jobs. Dapat dikatakan suatu performa aplikasi dapat diuji oleh stress test. Salah satu penerapan stress test adalah functional test seperti selenium atau menggunakan Apache Benchmark untuk melihat performa suatu web app.
Implementasi Stress Test dalam Project AdHub
Kami menggunakan Apache Benchmark untuk melihat bagaimana respon web application yang sudah kami buat jika menerima cukup banyak request. Simulasi Test yang kami lakukan adalah AdHub akan menerima request sebanyak 100.000, dengan concurrency sebanyak 100, dan set waktu selama 60 detik.
ab -n 10000 -c 100 -t 60 http://bit.ly/AdHub
Report atau hasil dari eksekusi script diatas adalah:
- Request yang berhasil dijalankan sebanyak 11404 request dan semuanya berhasil
- Dalam waktu 60 detik total transfer data yang dilakukan sebanyak 58429 bytes
- Dengan longest request selama 3519ms
- Dengan rata-rata request perdetik sebanyak 190 request
Setelah memahami Stress Test, saya akan membahas mengenai Penetration Test atau yang biasa dikenal dengan Pentest. Pentest merupakan kegiatan dimana seseorang mencoba mensimulasikan serangan yang bisa dilakukan terhadap suatu jaringan tertentu untuk menemukan kelemahan yang ada pada sistem jaringan tersebut. Tester dalam pentest disebut sebagai pentester. Lalu pertanyaan yang muncul adalah untuk apa melakukan suatu pentest ketika sudah menerapkan TDD dan stress test?
Jawabannya adalah karena Dengan melakukan pentest, celah-celah keamanan yang ada dapat diketahui dan dengan demikian dapat diperbaiki secepatnya. Seorang pentester mensimulasikan serangan yang dapat dilakukan dengan membuat beberapa skenario, menjelaskan resiko yang bisa terjadi, dan melakukan perbaikan sistem tanpa merusak infrastruktur jaringan perusahaan tersebut. Ternyata cukup krusial yaa!
Implementasi Pentest dalam Project AdHub
Untuk mensimulasikan pentest saya menggunakan aplikasi pendukung yaitu Burp Suite yang dapat didownload di sini. Burp Suite merupakan suatu tools yang dapat membantu pentester dalam melakukan audit suatu web dan aplikasi ini tidak berbayar. Berikut akan saya berikan sedikit demonstrasi dalam menggunakan Burp Suite untuk melakukan pentest aplikasi AdHub kepada fitur Login dengan melakukan brute force login.
Proses Pentest:
- Buka aplikasi burp suite. Pilih temporary project lalu klik next dan klik start burp
- Tampilan Burp akan terlihat dengan banyaknya tab yang tersedia. Jika kalian menggunakan firefox buka menu settings, lalu pilih network settings dan gunakan ‘manual proxy config’ dengan http proxy 127.0.0.1 dengan port 8080.
- Setelah setelah melakukan setup terhadap proxy, kalian dapat membuka page yang ingin dilakukan pentest. Saya akan membuka http://152.118.201.222:21203/profile/
Link berikut merupakan link untuk login pada aplikasi AdHub - Setelah itu lihat aplikasi Burp kalian pada menu proxy. Burp akan menampilkan response dari request yang dilakukan. Untuk lebih lengkapnya saya akan berikan screenshot.
- Kemudian saya akan mencoba mensimulasi action login yang gagal atau password salah. Kemudian lihat kembali tampilan burp anda. Akan terdapat satu baris yang memperlihatkan email dan password yang saya simulasikan yaitu jihad@email.com dengan password 12345678
- Jika ingin melakukan brute force login dapat klik kanan pada tampilan response lalu pilih send to intruder lalu klik forward pada button diatas
- Kemudian kita dapat pindah menuju tab ‘intruder’ pada menu ‘positions’
- Untuk melakukan brute force login kita dapat memilih parameter atau payload apa saja yang diingin untuk menjadi input. Karna pada skenario ini kita hanya membutuhkan email dan password oleh karena itu kita dapat klik clear pada bagian kanan burp.
- Clear akan membersihkan argumen-argumen yang akan menjadi payload kita nanti. Lalu block value dari email dan password yang sudah diisikan sebelumnya
- Kemudian ubah attack type menjadi cluster bomb. Karena kita membutuhkan 2 value dalam melakukan brute force login yaitu email dan password selain itu dibutuhkan kombinasi yang tepat dalam melakukan brute force login.
- Setelah mengganti attack type, block value dari email lalu klik add pada sisi kanan dan lakukan yang sama kepada value dari password.
- Sekarang kita masuk kepada bagian yang terpenting yaitu payloads. Klik menu ‘payloads’ di samping menu ‘positions’
- Kalian akan melihat payload set yaitu 1 dan 2. Disini kita akan mensepakati payload 1 untuk email dan 2 untuk password.
- Pertama lakukan konfigurasi pada payload 1. Lihat pada bagian payload options, pada bagian itu kalian dapat menambahkan atau load file txt berupa email. Saya akan coba simulasikan daftar email yang ingin dilakukan brute force. Hasil dapat kalian lihat pada screenshot dibawah
- Input email dapat berupa file jika kalian memiliki dataset of email dalam bentuk txt
- Kemudian ganti ke payload 2. Lakukan hal yang sama pada payload 2 dengan payload 1 namun payload 2 merupakan list of password yang ingin ditebak.
- Setelah melakuakn konfigurasi terhadap setiap payload klik “Start attack” pada kanan atas burp. Proses brute force dilakukan.
- Dalam simulasi ini saya membuat akun dengan email jihadmjr@gmail.com dengan password asdqwe123. Dapat dilihat report dari hasil brute force yang sudah dilakukan terhadap 56 kombinasi email dan password
- Dapat dilihat pada request no 47 memiliki length sebanyak 533 dan berbeda dengan length yang dimiliki oleh 55 request lainnya. Karena pada request 47 merupakan kombinasi email dan password yang tepat
Kemudian tujuan dilakukannya pentest terhadap login apa? Tujuan atau alasan kenapa proses brute force dicoba adalah untuk mengantisipasi penyadap atau orang-orang yang berusaha mencoba menebak atau mengetahui email dan password seseorang. Lalu bagaimana solusi dari permasalahan ini? Solusi yang saya miliki adalah penggunaan captcha. Karena captcha bersifat acak dan dapat dikatakan aman untuk sekarang, sehingga dapat menghindari brute force login yang dapat dilakukan penyadap.
Automatic Data Seeding/Migration
Data Seeding merupakan suatu proses penginisialisasian data saat inisasi database. Data Seeding dalam proyek AdHub terdapat pada proses seeding akun superuser menggunakan script yang dibuat. Lalu selain itu apa sih tujuannya seeding? Seeding dapat bermanfaat ketika melakukan migrasi server. Contoh kasusnya adalah ketika AdHub sudah memiliki 10.000 user dengan iklan yang lebih dari 20.000 live. Namun suatu ketika AdHub ingin melakukan migrasi server atau perubahan system sehingga harus melakukan setup database dari awal. Secara manusiawi tidak mungkin dilakukan input satu persatu. Oleh karena itu dibutuhkan proses data seeding.
Django Seeding
Sistem database dalam django dapat dikatakan cukup mudah digunakan. Django sendiri sudah menyediakan dokumentasi yang cukup lengkap terkait seeding dan extract data. Dokumentasi lengkap django dapat dibaca di sini.
Terdapat dua command atau fungsi dapat proses seeding atau init data pada Django yaitu
- dumpdata
Dumpdata adalah perintah untuk melakukan proses extraction data yang sudah dibuat oleh models atau database django kedalam bentuk json. File json ini dapat berguna untuk arsip atau backup database jika terjadi sesuatu diluar kehendak terkait database.
Berikut contoh implementasi dari dumpdata:
python manage.py dumpdata iklan.iklan --indent 4 > iklan.json
isi dari file iklan.json:
[
{
"model": "iklan.iklan",
"pk": 1,
"fields": {
"judul": "asd",
"platform": 1,
"tanggal_mulai": "2019-04-19T17:00:00Z",
"tanggal_berakhir": "2019-04-24T17:00:00Z",
"deskripsi": "asd",
"image": "static/saved_image/img_1_AqBmSzA.png",
"link_iklan": "asd.com",
"pemasang_iklan": 1,
"nama_usaha": "Usaha iklan"
}
},
{
"model": "iklan.iklan",
"pk": 2,
"fields": {
"judul": "sada",
"platform": 1,
"tanggal_mulai": "2019-04-19T17:00:00Z",
"tanggal_berakhir": "2019-04-24T17:00:00Z",
"deskripsi": "asdas",
"image": "static/saved_image/img_2.png",
"link_iklan": "asda.com",
"pemasang_iklan": 1,
"nama_usaha": "Usaha iklan"
}
},
...
]
2. loaddata
Loaddata merupakan perintah untuk melakukan seeding atau input database dari file json. Proses seeding dapat memudahkan dalam proses pembuatan atau init database sehingga aplikasi tidak benar-benar kosong setelah rilis. Seeding dapat dilakukan pada saat terjadi perubahan server atau system yang berubah. Sehingga database akan tereset dari kosong. Jika AdHub sudah memiliki 10.000 user dan 20.000 iklan lebih yang sudah live, apakah admin akan memasukkan data tersebut satu persatu? Jawabannya tidak mungkin, oleh karena itu dibutuhkan data seeding agar memudahkan proses init atau pengisian data.
Berikut contoh aplikasi dari loaddata:
Saya akan mencoba menghapus data iklan yang terdapat pada iklan.json dan mengedit nama iklan menjadi “Nasi Goreng” dan “Ayam Bakar” lalu melakukan seeding kepada database AdHub.
Command untuk melakukan loaddata adalah
python manage.py loaddata <file.json>
Berikut contoh penerapannya
Kemudian saya mencoba membuat file json iklan kembali dengan data iklan yang baru
Dapat dilihat, terjadi proses seeding data pada database django dengan object pertama dan kedua adalah “Nasi Goreng” dan “Ayam Bakar” sesuai dengan skenario yang kita buat diawal
Dalam project AdHub proses migration sudah dihandle oleh Django. Terdapat perintah-perintah yang dapat melakukan proses migrasi data, yaitu
- makemigrations. Command ini digunakan untuk membuat migrasi baru berdasarkan perubahan yang telah dibuat di models atau dapat dilakuakn saat init database
- migrate. Command ini digunakan untuk mengaplikasikan migrasi
- showmigrations. Command ini digunakan untuk menunjukkan daftar migrasi di dalam project dan statusnya.
Proses migrasi pada Project AdHub sudah dilakukan otomatis pada saat proses deployment. Berikut potongan code pada CI kami
before_script:
- pip install virtualenv
- virtualenv env
- source env/bin/activate
- pip install -r requirements.txt
- python manage.py makemigrations
- python manage.py migrate
- python manage.py collectstatic --no-input
Pada potongan kode tersebut sebelum proses dijalankan terdapat proses untuk menyiapkan depedensi dan migrasi data. Sehingga pada saat runner sedang berjalan. Schema dan database sudah terbuat dan siap untuk dideploy maupun di test.
Mock Test
Mock and Stub sangat erat kaitannya dengan testing. Karena memang Mock & Stub merupakan salah satu komponen yang terdapat dalam testing. Lalu apakah Mock & Stub itu sendiri. Mock & Stub sebenarnya adalah dua hal yang berbeda.
Mock merupakan sebuah objek yang mereplika/imitasi dari objek yang sesungguhnya yang digunakan dalam lingkup testing. Dengan adanya Mockkita melakukan test terhadap code yang telah kita buat agar sesuai dengan apa yang kita prediksikan atau kita harapkan.
Pada Python untuk membuat objek Mock kita dapat menggunakan Mock Object Library yang disediakan python. Untuk menggunakannya hal yang pertama yang harus dilakukan adalah dengan menginstall library tersebut menggunakan ‘pip’. Berikut adalah perintah untuk menginstall unittest.mocklibrary:
pip install mock
Denga menggunakan mock kita dapat melakukan pengujian apakah suatu method dipanggil atau tidak, berapa kali method itu dipanggil dan sebagainya. Hal ini dapat dilakukan dengan memanfaatkan method assertyang ada pada mock object.
from unittest.mock import Mockmock = Mock()# memastikan apakah method dipanggil, jika tidak maka akan menghasilkan pesan error
mock.method.assert_called()# memastikan apakah method hanya dipanggil sebanyak satu kali, jika tidak maka akan menghasilkan pesan error
mock.method.assert_called_once()# memastikan apakah method dipanggil dengan argumen tertentu, jika tidak maka akan menghasilkan pesan error
mock.method.assert_called_with('param')# memastikan apakah method hanya dipanggil sebanyak satu kali dengan argumen tertentu, jika tidak maka akan menghasilkan pesan error
mock.method.assert_called_once_with('param)
Selain memeriksa apakah suatu method dari objek yang direplika dapat dipanggil, mock juga bisa mengontrol code behaviour dengan cara menentukan return value dari suatu method/functions. Contoh penerapannya adalah sebagai berikut.
import datetime
from unittest.mock import Mocktuesday = datetime.datetime(year=2019, month=1, day=1)
saturday = datetime.datetime(year=2019, month=1, day=5)datetime = Mock()def is_weekday():
today = datetime.datetime.today()
# Python's datetime library treats Monday as 0 and Sunday as 6
return (0 <= today.weekday() < 5)# Mock .today() to return Tuesday
datetime.datetime.today.return_value = tuesday
# Test Tuesday is a weekday
assert is_weekday()
# Mock .today() to return Saturday
datetime.datetime.today.return_value = saturday
# Test Saturday is not a weekday
assert not is_weekday()
Pada kode diatas kita akan melakukan test terhadap function is_weekday() dengan input merupakan object datetime. Untuk dapat melakukan mock, kita perlu melakukan replika dari object datetime, dengan begitu kita dapat menentukan return value yang kita inginkan dengan menggunakan .return_value=… pada mock object. Setelah kita menetapkan return value dari method .today() pada mock object dari datetime barulah kita akan menguji apakah hasil assertion dari function is_weekday sesuai dengan apa yang diharapkan berdasarkan return value dari mock object datetime yang telah ditentukan. Ketika return value yang ditetapkan adalah hari Selasa, maka ketika dilakukan assertion: assert is_weekday() tidak akan menimbulkan pesan error begitu juga ketika return value yang ditetapkan adalah hari Sabtu, assertion: assert not is_weekday() juga tidak akan menimbulkan pesan error, karena hari Sabtu bukan merupakan weekday.
Selanjutnya adalah mengenai Stub, Stub merupakan objek yang menyimpan data yang telah ditentukan yang akan digunakan saat pemanggilan selama test berlangsung. Stub ini biasanya digunakan ketika seseorang tidak ingin menggunakan data asli karena dikhawatirkan dapat mengganggu aktivitas lainnya. Dengan menggunakan stub data yang akan dipanggil merupakan data tiruan yang digunakan untuk testing. Contoh penerapannya adalah sebagai berikut:
import unittest
class ClassIWantToTest(object): def getData(self):
print "PRODUCTION getData called"
return "Production code that gets data from server or data file" def getDataLength(self):
return len(self.getData())class TestClassIWantToTest(unittest.TestCase): def testGetDataLength(self):
def mockGetData(self):
print "MOCK getData called"
return "1234" ClassIWantToTest.getData = mockGetData
myObj = ClassIWantToTest()
self.assertEqual(4, myObj.getDataLength())