Belajar Memahami udev Di Linux

Salah satu tugas sistem operasi adalah mengelola perangkat keras yang terhubung pada komputer. Pada versi awal Linux, perangkat yang terhubung dengan komputer akan didaftarkan di directory /dev. Sebagai contoh, perangkat harddisk IDE zaman dulu (yang kini semakin langka) biasanya dikenali dengan nama seperti /dev/hda, /dev/hdb, dan seterusnya. Partisi di dalam harddisk pertama dikenali dengan nama seperti /dev/hda1, /dev/hda2 dan seterusnya. Pada harddisk SATA modern, perangkat harddisk memiliki nama seperti /dev/sda, /dev/sdb dan sebagainya. Bila saya mencolokkan perangkat USB Flash Drive (UFD), akan ada tambahan perangkat baru seperti /dev/sdc.

Lalu mengapa beralih ke udev? Komputer modern umumnya memiliki banyak port USB dimana pengguna bisa mencolok dan melepas perangkat kapan saja. Bila masih tetap memakai cara lama, maka nama sebuah perangkat di /dev akan sulit dicari karena bisa berubah tergantung pada urutan saat ia dikenali. Oleh sebab itu, Linux memakai udev untuk memetakan perangkat yang dikenali kernel dengan sebuah nama yang statis.

Bagaimana cara udev memetakan sebuah perangkat keras ke sebuah nama statis? Jawabannya adalah melalui rules yang ditulis oleh pengguna atau pembuat distro. Pengguna bisa menambahkan file rules di lokasi /etc/udev/rules.d. Distro Linux biasanya sudah dilengkapi dengan segudang rules untuk perangkat keras yang umum dipakai di lokasi /lib/udev/rules.d. Nomor di depan nama file dipakai untuk menentukan prioritas dari rules yang ada.

Sebagai contoh, berikut ini adalah salah satu baris di file /lib/udev/rules.d/60-persistence-storage.rules bawaan UBuntu:

# probe filesystem metadata of disks
KERNEL!="sr*", IMPORT{builtin}="blkid"
...
ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"

IMPORT akan mengerjakan sesuatu untuk memperoleh sebuah nilai yang nantinya dapat dibaca dengan ENV. Ia bisa mengerjakan program eksternal seperti pada IMPORT{program}, memanggil function built-in seperti pada IMPORT{builtin}, membaca isi file seperti pada IMPORT{file} dan sebagainya. SYMLINK akan membuat sebuah symbolic link sehingga perangkat sesuai dengan nama kernel tetap ada.

Sebagai hasilnya, saya bisa mencari nama partisi berdasarkan label, seperti pada:

$ ls /dev/disk/by-label/

Karena rules menggunakan SYMLINK, maka hasil yang saya jumpai adalah symbolic link ke nama seperti /dev/sda, /dev/sdb dan sebagainya. Dengan demikian, saya tetap bisa mencari perangkat berdasarkan cara lama (seperti /dev/sda) ataupun memakai cara yang lebih konsisten (seperti berdasarkan id, label, dan sebagainya).

Salah satu fitur menarik dari udev adalah ia bisa mengerjakan sebuah program pada saat perangkat dicolok atau dilepaskan dengan menggunakan RUN. Sebagai latihan, saya akan membuat sebuah rule yang akan mengerjakan program untuk menulis ke sebuah file setiap kali ada perangkat Samsung yang dicolokkan melalui USB.

Langkah pertama yang perlu saya lakukan adalah melihat informasi apa saja yang dikenali oleh kernel. Untuk itu, saya mencolokkan perangkat dan memberikan perintah:

$ lsusb
Bus 002 Device 003: ID xxxx:xxxx SanDisk Corp.
Bus 002 Device 005: ID xxxx:xxxx Samsung Electronics Co., Ltd
...

Berdasarkan informasi tersebut (Bus 002 Device 005), saya mengetahui bahwa perangkat dipetakan ke file /dev/bus/usb/002/005. Untuk melihat atribut apa saja yang ada, saya dapat memberikan perintah berikut ini:

$ udevadm info --name=/dev/bus/usb/002/005 --query=property
...
ID_VENDOR_ID=04e8
...

Nilai 04e8 adalah USB Vendor ID (VID) untuk Samsung. Selain memakai cara manual, saya juga bisa menemukan VID untuk seluruh pembuat perangkat USB dengan mencari nama perusahaan di http://www.usb.org/developers/tools/comp_dump. Sebagai informasi, setiap perusahaan yang ingin menciptakan perangkat keras yang memakai USB harus membayar sekitar U$5000 untuk memperoleh VID ini.

Saya kemudian membuat sebuah file baru di folder /etc/udev/rules.d dengan nama 10-latihan.rules yang isinya seperti berikut ini:

SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", RUN+="/home/snake/latihan.sh %p %E{ID_MODEL}"

Rules di atas akan mengerjakan script /home/snake/latihan.sh bila ada perangkat dengan ID_VENDOR 04e8 dihubungkan ke USB. Di dalam RUN, saya dapat memakai string substitution seperti %p yang akan diganti menjadi nama perangkat sesuai yang dikenali oleh kernel, %n mewakili nomor perangkat, dan %E{...} untuk mengakses property dari perangkat tersebut.

Langkah berikutnya, saya membuat sebuah script sederhana di lokasi /home/snake/latihan.sh yang isinya seperti berikut ini:

#!/bin/sh
echo `date`: Perangkat Samsung Ditemukan Pada "$@" >> /home/snake/log.txt

Sekarang, setiap kali sebuah perangkat Samsung dihubungkan ke PC melalui USB, akan ada baris baru di /home/snake/log.txt seperti:

Fri Feb 7 10:20:23 WIB 2015: Perangkat Samsung Ditemukan Pada /devices/xxx SAMSUNG_Android  

Menjalankan File ISO Linux Dari Live USB Tanpa Instalasi

Saya sudah lama meninggalkan CD/DVD sebagai media boot sistem operasi Linux. Sebagai gantinya, saya mem-boot Linux dari perangkat USB Flash Drive (UFD). Cara ini sangat praktis dan lebih cepat dibandingkan dengan memakai media CD/DVD. Tapi masalah yang kemudian timbul adalah bagaimana bila saya sering memakai beberapa distro Linux yang berbeda? Membeli 1 USB Flash Drive (UFD) baru khusus untuk 1 distro Linux adalah hal yang mubazir mengingat file ISO untuk Live USB biasanya memiliki ukuran kecil.

Saya bisa saja membuat beberapa partisi berbeda di UFD, lalu men-install distro Linux yang berbeda di masing-masing partisi yang ada. Akan tetapi, pada artikel ini, saya akan mencoba sebuah cara yang lebih ringkas. Saya akan men-boot Linux langsung dari file ISO yang dijumpai di UFD. Ini merupakan fitur baru dari GRUB 2. Mengapa memilih men-boot langsung dari ISO ketimbang men-install ke partisi? Salah satu keuntungannya adalah saya bisa melakukan upgrade cukup dengan mengganti ke file ISO terbaru.

Saat ini ada beberapa tools bagi pengguna awam untuk membuat Live USB yang membaca file ISO secara langsung. Tidak seperti end-user, sebagai seorang developer, saya perlu memahami mekanisme yang terjadi. Oleh sebab itu, saya akan mencoba mem-boot file ISO SystemRescue-Cd dan Fedora yang sudah saya download. Saya perlu meletakkan file tersebut pada sebuah partisi di UFD. Sebagai latihan, saya akan meletakkannya pada sebuah partisi NTFS di folder iso. Partisi ini adalah partisi pertama sehingga saya tetap dapat menggunakannya untuk baca tulis data di sistem operasi Windows (tidak seperti Linux, Windows hanya bersedia mengenali partisi pertama dari UFD). Btw, saya memakai NTFS karena FAT32 memiliki keterbatasan dimana file memiliki ukuran maksimal 4 GB.

Bootstrap loader adalah komponen sistem operasi yang dijalankan pertama kali pada saat komputer dinyalakan. Biasanya bootstrap loader di-install pada sektor pertama harddisk (disebut juga Master Boot Record) dan sektor pertama partisi (disebut juga Boot Sector). Btw, ini sedikit berbeda pada komputer baru yang sudah mendukung Unified Extensible Firmware Interface (UEFI) sebagai pengganti BIOS. UEFI mendukung layout partisi berbeda yang disebut GUID Partition Table (GPT). Karena saya adalah pengguna komputer lama yang masih memakai BIOS, maka saya akan tetap menggunakan partisi berbasis MBR.

Masing-masing sistem operasi memiliki boostrap loader-nya masing-masing. Sebagai contoh, sistem operasi Windows memiliki bootstrap loader yang disebut sebagai NTLDR. Pada Linux, ada beberapa pilihan seperti LILO (Linux Loader) dan GRUB. Hampir semua distro Linux modern sudah memakai GRUB sebagai bootstrap loader. Salah satu kelebihan GRUB adalah ia tidak hanya bisa dipakai untuk men-bootstrap Linux tapi juga sistem operasi lain seperti Windows. GRUB menawarkan banyak fasilitas berguna sehingga boleh dibilang ia adalah sebuah sistem operasi ‘mini’ untuk menjalankan sistem operasi lainnya. Pada artikel ini, saya akan menggunakan GRUB 2 sebagai bootstrap loader pada Live USB yang akan saya buat.

Saya akan mulai dengan melakukan mounting partisi di UFD dengan perintah seperti berikut ini:

# mkdir live_usb
# mount /dev/sdb1 live_usb
# ls live_usb/iso
Fedora-Live-Desktop-x86_64-20-1.iso  systemrescuecd-x86-4.4.0.iso

Partisi pertama pada UFD saya diwakili oleh /dev/sdb1 dan UFD secara keseluruhan diwakili oleh /dev/sdb. Terlihat bahwa partisi pertama saya (bertipe NTFS) hanya berisi 2 file ISO di folder iso.

Sekarang, saya siap untuk men-install UFD pada partisi pertama dengan menggunakan perintah berikut ini:

# grub-install --boot-directory=/mnt/live_usb /dev/sdb
Installing for i386-pc platform.
grub-install: warning: your embedding area is unusually small.  core.img won't fit in it..
grub-install: warning: Embedding is not possible.  GRUB can only be installed in this setup by using blocklists.  However, blocklists are UNRELIABLE and their use is discouraged..
grub-install: error: will not proceed with blocklists.

Mengapa saya mendapatkan pesan kesalahan seperti ini? Kode program yang bisa dikerjakan pertama kali oleh komputer adalah kode program Master Boot Record yang hanya berukuran 512 bytes! Sangat terbatas, bukan? Pada artikel Membuat Bootstraploader Untuk UFD, saya membuat sebuah bootstrap loader sederhana yang muat di MBR. Tapi sistem operasi modern memiliki bootstrap loader yang lebih kompleks. Oleh sebab itu, biasanya bootstrap loader dipisah menjadi dua tahap atau lebih. Kode program 512 bytes pertama akan membaca dan mengerjakan kode program bootstrap loader berikutnya. Pada GRUB 2, kode program tahap kedua ini disebut sebagai core.img. Dimana GRUB 2 meletakkan core.img? Belum ada konsep file system disini sehingga tidak bisa dalam bentuk file! Sebagai alternatifnya, GRUB 2 meletakkan core.img pada sektor setelah MBR dan sebelum boot sector partisi pertama. Saya memperoleh pesan kesalahan di atas karena letak boot sector partisi pertama yang terlalu ‘dempet’ dengan MBR sehingga tidak ada ruang untuk mengisi core.img.

Partisi pada UFD yang saya pakai di-format oleh Windows yang memberi terlalu sedikit jarak. Lalu apa yang harus saya lakukan? Salah satu solusi yang bisa saya tempuh adalah cukup dengan membuat ulang partisi dengan menggunakan GParted. Bila saya membuat partisi dengan GParted, nilai free space preceding (MiB) secara default adalah 1. Ini sudah cukup untuk kebutuhan GRUB 2. Saya kemudian kembali memberikan perintah grub-install seperti berikut ini:

# grub-install --root-directory=/mnt/live_usb /dev/sdb
Installing for i386-pc platform.
Installation finished. No error reported.

Perintah grub-install di atas akan menulis kode program bootstrap loader pada MBR dan sektor lainnya. Saya tidak bisa melihat hasilnya secara langsung tanpa memakai tool yang membaca partisi per sektor. Selain itu, grub-install akan membuat direktori \boot pada partisi pertama. Yang ini terlihat dengan jelas dan merupakan sebuah kelebihan GRUB 2. Mengapa demikian? Ingat kembali bahwa saya menggunakan partisi NTFS yang diciptakan untuk Windows! GRUB 2 bisa membaca dan menulis ke partisi NTFS dengan baik. Hal ini tidak berlaku untuk sebaliknya; Windows tidak mengenali partisi ext4 milik Linux tanpa driver tambahan!

Bila men-boot komputer dari UFD, saya akan memperoleh tampilan seperti pada gambar berikut ini:

Tampilan CLI milik GRUB

Tampilan CLI milik GRUB

Ingat bahwa saya belum men-install sistem operasi apapun pada UFD saya. Yang muncul adalah CLI milik GRUB, bukan BASH atau terminal milik sistem operasi Linux! Membuat bootstrap loader yang punya terminal dan perintah-nya sendiri adalah sebuah usaha yang luar biasa bila dilakukan oleh pihak yang juga membuat sistem operasi. Mengapa demikian? Hal ini karena kode program bootstrap loader akan dibuang dan tidak dipakai lagi begitu kode program sistem operasi berhasil dijalankan! Tentu saja pembuat sistem operasi akan lebih memilih fokus pada kode program sistem operasi ketimbang kode program bootstrap loader yang hanya dipakai sesaat saja. GRUB berbeda karena ia memang dirancang sebagai sebuah bootstrap loader universal yang bisa dipakai pada berbagai situasi tanpa harus terikat pada satu jenis sistem operasi. Oleh sebab itu, banyak pembuat sistem operasi amatir memilih untuk memakai GRUB sebagai bootstrap loader pada sistem operasi yang mereka buat ketimbang menulis kode program bootstrap loader baru.

Menjalankan sistem operasi yang masih berada dalam bentuk file ISO (tanpa di-install) disebut sebagai loopback booting. Hal ini dapat dilakukan dengan menggunakan perintah loopback dari GRUB 2 seperti pada perintah berikut ini:

grub> loopback iso /iso/systemrescuecd-x86-4.4.0.iso

Perintah di atas akan membuat sebuah device baru dengan nama iso yang mewakili isi file ISO (yang saya letakkan pada folder iso). Saya dapat mengakses iso layaknya sebuah partisi, misalnya saya bisa melihat isi direktori di dalam file ISO dengan perintah seperti:

grub> ls (iso)/isolinux/
altker32 altker64 boot.cat chain.32 f1boot.msg f2images.msg f3params.msg f4aru
n.msg f5troubl.msg f6pxe.msg f7net.msg ifcpu64.c32 initram.igz isolinux.bin iso
linux.cfg isolinux.old kbdmap.c32 maps/ membdisk menu.c32 netboot pxelinux.0 reb
oot.c32 rescue32 rescue64 vesamenu.c32

Untuk melakukan loading kernel Linux, saya perlu menggunakan perintah linux seperti berikut ini:

grub> linux (iso)/isolinux/rescue64 isoloop=/iso/systemrescuecd-x86-4.4.0.iso

Pada perintah di atas, saya menambahkan boot parameter isoloop yang berisi lokasi file ISO. Ingat bahwa GRUB sebagai bootstrap loader sama sekali tidak berhubungan dengan kernel Linux. Oleh sebab itu, kernel harus mencari sendiri file ISO yang saya pakai di seluruh partisi yang ada. Setelah itu, ia harus men-mount root (yang mengandung direktori sepeti /etc, dsb) yang ada di ISO. Tidak semua distro Linux mendukung loopback booting! Selain itu, masing-masing kernel juga bisa memiliki nama parameter (boot options) yang berbeda untuk menentukan nama file ISO.

Berikutnya, saya perlu melakukan loading initial ram disk dengan menggunakan perintah initrd seperti berikut ini:

grub> initrd (iso)/isolinux/initram.igz

initrd akan menciptakan partisi baru di memori berdasarkan file yang sudah dipersiapkan oleh pembuat distro Linux. Partisi ini berperan sebagai root awal yang sudah berisi ‘driver’ siap pakai sehingga kernel Linux dapat melakukan inisialisasi dengan baik.

Sebagai langkah terakhir, saya memberikan perintah boot untuk mulai menjalankan Linux:

grub> boot

Tidak lama kemudian, sistem operasi Linux pada distro SystemRescue-Cd berhasil dijalankan langsung dari file ISO tanpa instalasi sama sekali.

Percobaan pertama sukses, lalu bagaimana dengan Fedora? Saya segera me-restart komputer dan memberikan perintah seperti berikut ini di GRUB:

grub> loopback iso /iso/Fedora-Live-Desktop-x86_64-20-1.iso
grub> linux (iso)/isolinux/vmlinuz0 iso-scan/filename=/iso/Fedora-Live-Desktop-x86_64-20-1.iso root=live:CDLABEL=Fedora-Live-Desktop-x86_64-20-1 rd.live.image
grub> initrd (iso)/isolinux/initrd0.img
grub> boot

Tidak seperti pada SystemRescue-cd yang memakai isoloop, boot option sebagai pengenal file ISO di Fedora adalah iso-scan/filename. Selain itu, Fedora juga tidak mendukung root=auto sehingga saya perlu memberikan nilai parameter root untuk men-instruksi-kan kernel agar melakukan mounting root yang ada di file ISO.

Akan tetapi, saya tidak berhasil men-boot Fedora! Saya menemukan pesan kesalahan seperti berikut ini:

dracut-initqueue[331]: mount: unknown filesystem type 'ntfs'
...
Warning: /dev/disk/by-label/Fedora-Live-Desktop-x86_64-20-1 does not exist

Ini adalah contoh kasus dimana bootstrap loader terkadang bisa lebih canggih dari sistem operasi! GRUB bisa membaca partisi NTFS tanpa masalah. Akan tetapi Initrd pada Fedora tidak dilengkapi dengan driver NTFS sehingga ia tidak bisa mencari file ISO yang ada dalam partisi NTFS saya. Ingat bahwa bootstrap loader hanya bertanggung jawab untuk menjalankan kernel! Mereka tidak saling berkomunikasi. GRUB akan ‘mati’ dan ‘lenyap’ setelah Fedora berhasil dijalankan (ini adalah arti kata bootstrap; telur akan hilang setelah ayam muncul!). Jadi, Initrd Fedora bertanggung jawab membaca file ISO di partisi NTFS tanpa bantuan GRUB. Karena ia tidak mampu, maka saya memperoleh pesan kesalahan.

Salah satu solusi untuk permasalahan ini adalah dengan membuat partisi yang dikenali oleh Initrd Fedora. Sebagai contoh, saya membuat partisi baru dengan tipe EXT4 dan meletakkan file ISO pada partisi tersebut. Saya bisa melakukan loopback mounting untuk partisi kedua dengan menggunakan perintah seperti berikut ini:

grub> loopback iso (hd0,2)/Fedora-Live-Desktop-x86_64-20-1.iso
grub> linux (iso)/isolinux/vmlinuz0 iso-scan/filename=/Fedora-Live-Desktop-x86_64-20-1.iso root=live:CDLABEL=Fedora-Live-Desktop-x86_64-20-1 rd.live.image
grub> initrd (iso)/isolinux/initrd0.img
grub> boot

Sekarang, Fedora berhasil di-boot dengan baik melalui ISO tanpa instalasi pada partisi di UFD.

Tentu saja saya tidak ingin selalu memberikan perintah GRUB setiap kali hendak menjalankan distro Linux di Live USB. Untuk itu, saya perlu membuat sebuah file bernama grub.cfg di folder /boot (yang dihasilkan oleh grub-install) yang isinya seperti berikut ini:

menuentry "SystemRescue-Cd 64-bit" {
  loopback iso /iso/systemrescuecd-x86-4.4.0.iso
  linux (iso)/isolinux/rescue64 isoloop=/iso/systemrescuecd-x86-4.4.0.iso
  initrd (iso)/isolinux/initram.igz
}

menuentry "SystemRescue-Cd 32-bit" {
  loopback iso /iso/systemrescuecd-x86-4.4.0.iso
  linux (iso)/isolinux/rescue32 isoloop=/iso/systemrescuecd-x86-4.4.0.iso
  initrd (iso)/isolinux/initram.igz
}

menuentry "Fedora 20 64-bit" {
  loopback iso (hd0,2)/Fedora-Live-Desktop-x86_64-20-1.iso
  linux (iso)/isolinux/vmlinuz0 iso-scan/filename=/Fedora-Live-Desktop-x86_64-20-1.iso root=live:CDLABEL=Fedora-Live-Desktop-x86_64-20-1 rd.live.image
  initrd (iso)/isolinux/initrd0.img
}

Isi dari file grub.cfg adalah perintah-perintah yang sebelumnya sudah saya kerjakan. Kali ini, bila saya melakukan boot dari Live USB, saya tidak akan menemukan CLI GRUB lagi melainkan sebuah menu yang terlihat seperti pada gambar berikut ini:

Tampilan Menu GRUB

Tampilan Menu GRUB

Saya kini memperoleh sebuah Live USB tunggal yang dapat berisi banyak distro Linux. Ini adalah solusi yang lebih baik daripada harus menghabiskan sebuah UFD tunggal untuk setiap file ISO. Selain itu, karena saya meletakkan file ISO pada partisi NTFS, maka saya masih dapat memakai Live USB untuk penyimpanan data di sistem operasi Windows, seperti yang terlihat pada gambar berikut ini:

Partisi tetap dapat dipakai di Windows

Partisi tetap dapat dipakai di Windows

Saya hanya perlu berhati-hati agar tidak menghapus folder boot dan iso secara tidak sengaja.

Memakai DNSCrypt Untuk Menghindari DNS Injection

Selama ini saya tidak pernah memakai DNS server dari ISP, melainkan selalu memakai DNS server dari pihak ketiga. Alasannya adalah DNS server dari ISP sangat lambat dan tidak aman. Semua berjalan dengan lancar sampai ketika beberapa hari yang lalu, saya menemukan banyak masalah pada jaringan saya. Kode program yang menulis log kesalahan ke server chat Slack tiba-tiba mengeluh server tidak ditemukan. Saya juga mulai kesulitan mengakses server GitHub (terkadang sukses tapi terkadang gagal). Seperti masalah jaringan lain pada umumnya, saya mulai melakukan troubleshooting dengan memantau packet melalui Wireshark. Hasilnya, saya menemukan respon dari server milik ISP padahal saya tidak mengaksesnya.

Mengapa demikian? Banyak kemungkinan yang bisa saja terjadi di infrastruktur ISP (atau rahasia lainnya yang tidak saya ketahui karena saya bukan pegawai disitu). ISP bisa saja memakai transparant proxy yang melakukan filtering pada seluruh data yang keluar masuk. Tapi, saya akan mulai dengan memeriksa sesuatu yang lebih masuk akal, misalnya memeriksa DNS aktual yang saya pakai melalui situs https://www.dnsleaktest.com. Saya cukup terkejut ketika mendapati laporan bahwa DNS server yang dipakai adalah DNS server milik ISP. Loh, bukankah saya sudah memakai DNS server milik pihak ketiga? Mungkin sekali ISP telah mengubah setiap request DNS pada port UDP 53 menjadi merujuk ke server DNS milik mereka. Jadi, tidak peduli apapun DNS server yang saya tentukan di router, ISP secara diam-diam akan ‘menggantinya’ ke server DNS yang berbeda. Teknik ini sering kali disebut DNS Injection yang diimplementasikan dengan memakai Transparant DNS Proxy.

Salah satu cara untuk menghindari DNS Injection adalah dengan memakai DNSCrypt yang dikembangkan oleh OpenDNS. DNSCrypt memakai protokol DNSCurve yang ditujukan untuk menggantikan protokol DNS (yang sampai sekarang masih dipakai dimana-mana). Protokol ini lebih aman karena request DNS di-enkripsi sehingga upaya untuk memodifikasi respon dari server akan lebih sulit. Saat ini OpenDNS adalah penyedia terbesar untuk layanan DNS yang mendukung DNSCurve.

Saya segera membuka halaman http://dnscrypt.org/dnscrypt-proxy/download untuk men-download source DNSCrypt. Karena memakai sistem operasi Linux UBuntu, saya men-download file dnscrypt-proxy-1.4.0.tar.gz dan men-extract-nya.

DNSCrypt bergantung pada libsodium. Oleh sebab itu, saya perlu men-download source terbaru library tersebut di https://github.com/jedisct1/libsodium/releases. Setelah men-extract-nya, saya akan men-install library tersebut dengan memberikan perintah berikut ini:

# sudo ./configure
# sudo make
# sudo make install
# sudo ldconfig

Untuk memastikan libsodium telah ter-install, saya dapat memeriksanya dengan perintah berikut ini:

# sudo ldconfig -p | grep libsodium

Berikutnya, saya akan berpindah ke lokasi source code DNSCrypt dan men-install-nya dengan memberikan perintah berikut ini:

# sudo ./configure
# sudo make
# sudo make install

Binary DNSCrypt secara otomatis akan ter-install pada lokasi /usr/local/sbin. Untuk menguji apakah DNSCrypt dapat bekerja dengan baik, saya memberikan perintah berikut ini:

# dnscrypt-proxy --resolver-name=opendns --test=0

Agar lebih aman, saya dapat memakai parameter --user sehingga dnscrypt-proxy melakukan chroot() ke user dengan hak akses yang lebih terbatas. Untuk membuat user baru, saya dapat menggunakan perintah berikut ini:

# sudo adduser --disabled-login --no-create-home --system dnscrypt

Untuk menjalankan DNSCrypt sebagai user baru tersebut, saya dapat menggunakan perintah:

# sudo dnscrypt-proxy --resolver-name=opendns --user=dnscrypt --test=0

Berikutnya, saya ingin DNSCrypt dijalankan secara otomatis. Pada Linux UBuntu yang memakai Upstart, saya bisa menambah file baru di /etc/init dengan nama seperti dnscrypt-proxy.conf yang isinya adalah:

# DNSCrypt Proxy

description "DNSCrypt proxy using OpenDNS resolver"

start on net-device-up

exec /usr/local/sbin/dnscrypt-proxy --resolver-name=opendns --user=dnscrypt

respawn

Penggunaan respawn pada script Upstart di atas menyebabkan DNSCrypt proxy akan dijalankan ulang secara otomatis bila terjadi service tersebut mengalami kegagalan.

Sekarang, bila saya me-restart komputer, DNSCrypt akan tetap dijalankan secara otomatis. Saya bisa memeriksanya dengan menggunakan perintah:

# sudo status dnscrypt-proxy
dnscrypt-proxy start/running, process 199

Setelah DNSCrypt dijalankan, ia akan menyediakan layanan DNS biasa pada port 53. Saya perlu men-konfigurasi jaringan agar tidak lagi mengakses server DNS milik siapapun lagi karena pada akhirnya akan dialihkan ke server milik ISP. Saya perlu men-konfigurasi jaringan agar mengakses DNS di 127.0.0.l (localhost) pada port 53. Setelah menerima request di port ini, DNSCrypt akan melakukan koneksi ter-enkripsi ke port 443 milik server OpenDNS dan mengembalikan hasilnya ke pengguna.

Tapi ada satu masalah yang perlu saya selesaikan terlebih dahulu.

Pada versi Ubuntu baru, saya menemukan bahwa Dnsmasq akan dijalankan secara otomatis. Dnsmasq juga akan memakai port 53 pada 127.0.0.1 sebagai layanan DNS. Untuk itu, saya perlu mematikan layanan Dnsmasq karena tidak dibutuhkan lagi. Caranya adalah dengan mengubah isi file /etc/NetworkManager/NetworkManager.conf dan memberikan komentar pada baris berikut ini:

# dns=dnsmasq

Sebagai langkah terakhir, saya perlu mengatur masing-masing jaringan agar memakai DNS server pada lokasi 127.0.0.1, seperti pada gambar berikut ini:

Mengatur DNS untuk jaringan di Linux Ubuntu

Mengatur DNS untuk jaringan di Linux Ubuntu

Setelah me-restart jaringan, DNS injection dari ISP tidak lagi bekerja. Saya bisa memastikan diri memakai DNS resolver dari OpenDNS dan bukan milik ISP dengan membuka halaman http://www.opendns.com/welcome. Bila memakai DNS server dari OpenDNS, akan terlihat tanda centang besar.

Memakai Metasploit Framework Di Kali Linux

Metasploit Framework merupakan framework yang paling umum dipakai untuk menguji sebuah exploit. Mengapa dibutuhkan framework dalam membuat kode program exploit? Biasanya kode program exploit memiliki operasi yang umum seperti mengirim request HTTP, membuat server web sebagai pancingan bagi korban, dan sebagainya. Dengan adanya sebuah framework yang universal dan lengkap, tugas membuat kode program exploit menjadi lebih mudah. Selain itu, hal ini juga mempermudah pihak lain untuk menguji exploit yang telah ditulis dengan mudah.

Berdasarkan situs resminya, Metasploit terdiri atas beberapa versi, yaitu Framework, Community, Express, dan Pro. Seluruh versi selain versi Framework memiliki interface berbasis web yang dapat dipakai dengan mudah. Dari seluruh versi yang ada, hanya versi Framework dan Community yang gratis. Selain itu, pengguna versi Community perlu melakukan registrasi terlebih dahulu. Pada artikel ini, saya akan memakai versi Framework yang hanya menyediakan CLI (tampilan berbasis teks). Untuk menjalankannya, saya memilih menu Kali Linux, Exploitation Tools, Metasploit, metasploit framework.

Modul pada Metasploit dikategorikan menjadi encoder, nop generator, exploit, payload, dan auxiliary. Modul exploit mewakili sebuah celah keamanan yang akan diujikan. Celah keamanan ini memungkinkan penyerang untuk mengakses sistem yang diserang. Untuk itu dibutuhkan modul payload yang akan dikerjakan bila modul exploit berhasil menjalankan tugasnya, biasanya berupa shell. Modul auxiliary adalah sesuatu yang mirip seperti exploit tetapi tidak memiliki payload sehingga penyerang tidak dapat bermain-main dengan sistem sasaran secara leluasa (setidaknya untuk saat tersebut ;). Contohnya adalah operasi scanning, serangan yang hanya melumpuhkan server, membuat server palsu atau melakukan password cracking secara offline. Modul nop generator dan encoder dipakai untuk mengelabui sistem pertahanan milik sasaran (seperti antivirus dan IDS/IPS) sehingga sasaran tidak mengetahui bahwa dirinya sedang diserang.

Untuk melihat seluruh modul yang ada, saya dapat memberikan perintah seperti:

msf > show all

Untuk melihat modul untuk kategori tertentu, saya dapat memberikan perintah seperti:

msf > show exploits
...
msf > show auxiliary
...
msf > show payloads
...
msf > show encoders
...
msf > show nops
...

Sebagai latihan, saya akan mencoba mencari IP yang mewakili CCTV DVR di jaringan saya. Saat ini, sudah banyak CCTV DVR yang dapat diakses melalui web. Seberapa besar tingkat keamanan yang diberikan oleh perangkat CCTV DVR yang langsung terkoneksi ke internet? Untuk mencari tahu IP apa saja yang mewakili CCTV DVR, saya perlu menggunakan modul auxiliary scanner/misc/cctv_dvr_login dengan memberikan perintah berikut ini:

msf > use scanner/misc/cctv_dvr_login

Berikutnya, saya perlu melakukan konfigurasi untuk modul tersebut. Untuk melihat apa saja yang dapat diatur, saya memberikan perintah berikut ini:

msf auxiliary(cctv_dvr_login) > show options

Nilai RHOSTS saat ini masih kosong. Saya perlu mengisinya dengan nilai IP yang perlu di-scan. Sebagai contoh, bila saya ingin men-scan IP pada range 192.168.1.0 hingga 192.168.1.255, maka saya dapat memberikan perintah berikut ini:

msf auxiliary(cctv_dvr_login) > set rhosts 192.168.1.0/24

Karena modul auxiliary tidak membutuhkan payload, saya dapat langsung menjalankannya dengan memberikan perintah:

msf auxiliary(cctv_dvr_login) > exploit

Metasploit akan melakukan proses scanning.. Hasilnya adalah tidak ada IP CCTV yang ditemukan!! Hal ini karena perangkat CCTV DVR yang populer di wilayah geografi saya berbeda dengan yang ditemui si pembuat modul. Saya melihat bahwa perangkat CCTV DVR disini sering kali men-ekspos port 554 untuk keperluan streaming. Oleh sebab itu, saya dapat memeriksa apakah sebuah IP membuka port 554 dengan memakai modul auxiliary scanner/portscan/tcp memberikan perintah berikut ini:

msf auxiliary(cctv_dvr_login) > back
msf > use scanner/portscan/tcp
msf auxiliary(tcp) > show options
...
msf auxiliary(tcp) > set ports 554
msf auxiliary(tcp) > set rhosts 192.168.1.0/24
msf auxiliary(tcp) > set threads 5
msf auxiliary(tcp) > exploit

Metasploit pun melaporkan IP dengan port TCP 554 yang terbuka. Kemungkinan besar IP tersebut adalah IP khusus untuk CCTV DVR.

Saya sudah menemukan IP target. Langkah berikutnya adalah menebak password yang dipakai untuk login. Karena proses authentication biasanya dilakukan dengan menggunakan standar dari HTTP, maka saya dapat menggunakan modul auxiliary scanner/http/http_login seperti berikut ini:

msf auxiliary(tcp) > back
msf > use scanner/http/http_login
msf auxiliary(http_login) > show options
...

Sebuah merk CCTV DVR populer di wilayah geografi saya memiliki halaman administrasi berbasis web yang dilengkapi dengan proses login dan captcha. Sekilas terlihat bahwa proses bruteforce atau dictionary attack adalah hal yang tidak mungkin, bukan? Tapi masalahnya CCTV DVR tersebut juga mempublikasi situs web khusus untuk perangkat mobile yang dapat diakses tanpa captcha. Contoh URL yang dapat di-brute force tanpa harus melalui captcha adalah /cgi-bin/guest/Video.cgi?media=JPEG&channel=1. Oleh sebab itu, saya segera melakukan pengaturan seperti berikut ini:

msf auxiliary(http_login) > set auth_uri /cgi-bin/guest/Video.cgi?media=JPEG&channel=1
msf auxiliary(http_login) > set blank_passwords false
msf auxiliary(http_login) > set rhosts 192.168.1.135,200,300
msf auxiliary(http_login) > set stop_on_success true
msf auxiliary(http_login) > exploit
...

Pada perintah di atas, Metasploit akan mencoba melakukan dictionary attack untuk HTTP authentication pada IP 192.168.1.135, 192.168.1.200, dan 192.168.1.300. Bila berhasil, maka saya dapat dengan mudah login ke IP tersebut melalui browser untuk melihat live streaming maupun hasil rekaman CCTV. Pada percobaan ini, saya menemukan cukup banyak CCTV DVR yang dapat diakses dengan mudah karena pengguna memakai password default yang mudah ditebak.

Agar proses pencarian menjadi lebih mudah, saya dapat membuat sebuah modul baru dalam bahasa pemograman Ruby yang dapat mencari IP milik beberapa brand CCTV DVR yang populer (contoh di atas hanya berdasarkan pada perilaku sebuah brand terkenal) dan berusaha untuk login melalui web. Dengan demikian, saya tidak perlu mengulangi langkah di atas lagi setiap kali ingin melakukan pencarian. Ini adalah kelebihan Metasploit sebagai sebuah framework.

Kesimpulannya: Produsen CCTV DVR harus meningkatkan keamanan produknya. Sudah bukan rahasia lagi bila banyak firmware (istilah untuk program yang berjalan di hardware/elektronik) yang ditulis dengan kualitas rendah. Bug dan kesalahan ketik dapat dijumpai dengan mudah pada firmware yang beredar di pasaran. Masalahnya, pengguna akan jarang melakukan update firmware bila ada perbaikan bug (apa ini strategi pasar agar mereka membeli produk baru yang lebih aman? ūüėČ Pihak yang melakukan instalasi CCTV juga sebaiknya mengedukasi pengguna agar menggunakan password yang lebih aman dan lebih sulit ditebak. Selain itu, mengakses sistem milik orang lain tanpa seizin pemiliknya adalah perbuatan ilegal (mungkin pengecualiannya adalah bila segera memberi tahu pihak terkait atas celah keamanan yang dimilikinya).

Melakukan Fuzz Testing Dengan Kali Linux

Pada saat membuat program, developer mengharapkan pengguna memasukkan input sesuai dengan yang seharusnya. Pada kenyataannya, pengguna (terutama yang iseng) mungkin saja memberikan input yang tidak diharapkan. Lalu, apa yang akan terjadi dengan program bila pengguna memberikan input yang tidak diharapkan? Fuzz testing adalah pengujian yang dilakukan untuk menjawab pertanyaan tersebut. Fuzz testing adalah jenis pengujian black box dimana penguji memberikan berbagai jenis input yang tidak valid pada program.

Kali Linux mem-bundle beberapa tools untuk keperluan fuzz testing yang dapat ditemukan di menu Kali Linux, Vulnerability Analysis, Fuzzing Tools. Saya akan mencoba beberapa tools tersebut.

Tool pertama yang saya temukan, BED, adalah sebuah script Perl yang dipakai untuk menguji penanganan protokol. BED mendukung protokol seperti FTP, SMTP, POP, HTTP, IRC, IMAP, PJL, LPD, FINGER, SOCKS4, dan SOCKS5. Dengan demikian, BED tidak dipakai untuk menguji program seperti aplikasi web, melainkan menguji infrastruktur seperti web server, mail server, FTP server dan sebagainya. BED akan berhenti bila berhasil membuat server yang diuji menjadi down atau crash. Sebagai contoh, saya ingin menguji seberapa handal FTP server di router yang saya pakai. Karena kemampuan pemrosesan di router ekonomis yang terbatas dan jarang sekali upgrade firmware, saya pantas merasa ragu dengan keamanannya. Oleh sebab itu, saya dapat melakukan pengujian dengan perintah seperti berikut ini:

# bed -s FTP -u admin -v password -t 192.168.1.1

BED 0.5 by mjm ( www.codito.de ) & eric ( www.snake-basket.de )

+ Buffer overflow testing:

    ...

+ Formatstring testing:

    ...

* Normal tests
 + Buffer overflow testing:

    ...

 + Formatstring testing:

    ...

 + Unicode testing:

    ...

 + random number testing:

    ...

 + testing misc strings 1:

    ...

 + testing misc strings 2:

    ...

 + testing misc strings 3:

    ...

 + testing misc strings 4:

    ...

 + testing misc strings 5:

 ...


Script BED akan menguji dengan memakai input berupa overflow string ("A" x 1023 atau "\\" x 200), format string (seperti %s%s%s%s atau %.2048d), unicode string (seperti "x99" x 512), large number (seperti -268435455), dan misc string (seperti "/" atau "\r\n"). Khusus pada FTP, ia juga akan menguji apakah directory traversal dengan input seperti "/././.." dimungkinkan atau tidak.

Tool lainnya yang berada dalam kategori ini adalah powerfuzzer. Tool berbasis GUI ini dapat dipakai untuk menguji aplikasi web. Sebagai contoh, saya akan melakukan pengujian pada router saya yang memiliki halaman administrasi dalam bentuk aplikasi web. Saya dapat memberikan perintah berikut ini untuk menjalankan powerfuzzer:

# powerfuzzer

Saya mengisi bagian credentials dengan nama user dan password router. Setelah itu, saya mengisi Target URL dengan lokasi router yaitu di http://192.168.1.1 dan men-klik tombol Scan. powerfuzzer akan bekerja dan menampilkan hasil pemeriksaan setelah selesai. powerpuzzer pada dasarnya adalah script Python yang bekerja mengisi parameter yang dipakai pada parameter pada request GET dan POST dengan nilai yang tidak valid seperti lokasi file (misalnya /etc/passwd atau http://www.google.com/), script (misalnya "a;env", "a);env", dan "/e"), injeksi (dengan payload berupa "\xbf'\"("), javascript (untuk memeriksa XSS), dan string CRLF seperti "http://www.google.com\r\nPowerfuzzer: v1 BETA".

Menariknya, hasil pengujian menunjukkan terdapat celah keamanan XSS pada web administrasi router saya. Bukan hanya itu saja! Dengan mengirim payload tertentu menggunakan method POST pada URL tersebut, router akan crash dan di-restart kembali.

Selain memakai tools yang ada di kategori Fuzzing Tools, bila melakukan fuzz testing pada aplikasi web, saya dapat menggunakan tool yang ada di menu Kali Linux, Web Applications, Web Application Fuzzers. Disini saya dapat menggunakan tool yang lebih ‘user-friendly’ dan berbasis GUI seperti Burp dan Zed Attack Proxy (ZAP).

Fuzz testing pada Burp dilakukan dengan memilih tab Intruder dan memilih salah satu jenis payload yang diujikan seperti Illegal Unicode. Pada ZAP, saya dapat memilih tab Active Scan untuk mencari celah keamanan pada URL yang telah diperoleh oleh spider. ZAP akan melakukan beberapa pemeriksaan, termasuk diantaranya adalah Cross Site Scripting (XSS), SQL Injection dan CRLF injection. Untuk melakukan fuzz testing pada URL tunggal di ZAP, saya perlu memilih sebuah parameter atau header di bagian Request, kemudian men-klik kanan dan memilih Fuzz…. Pada dialog yang muncul, saya dapat memilih fuzzer yang akan dipakai, seperti jbrofuzz/Buffer Overflows, jbrofuzz/Format String Errors, jbrofuzz/Integer Overflows, jbrofuzz/SQL Injection, dan sebagainya.

Memakai Maltego Di Kali Linux

Definisi Open Source Intelligence (OSINT) berdasarkan departemen pertahanan (DoD) Amerika adalah inteligensi yang diperoleh dari informasi yang tersedia untuk publik yang dikumpulkan, diolah dan disebarkan kepada pihak tertentu untuk keperluan intelijen tertentu. Istilah open source disini tidak ada hubungannya dengan kode program. Secara gamblang, OSINT dilakukan dengan mengumpulkan data yang dapat diperoleh secara publik, misalnya sesuatu yang dapat dicari di Google. Berbeda dengan hasil pencarian search engine, sebuah layer presentasi untuk OSINT hanya menampilkan data yang relevan dan dalam format yang mudah ditelusuri sehingga pengguna dapat mencari hubungan dari hasil yang ditemukan.

Maltego adalah sebuah tools yang dibuat dari Java untuk keperluan OSINT. Tool ini telah tersedia di Kali Linux sehingga siap untuk dipakai. Maltego dibedakan menjadi versi komersial (commercial edition) dan versi gratis (community edition). Versi gratis yang tersedia di Kali Linux hanya dapat menampilkan maksimal 12 hasil transformasi dan membutuhkan proses registrasi. Sebagai sebuah front-end untuk server OSINT, Maltego versi gratis hanya dapat memakai layanan server milik Paterva.

Karena versi yang disediakan oleh Kali Linux adalah versi gratis dari Maltego, saya perlu mendaftarkan sebuah akun terlebih dahulu di situs https://www.paterva.com/web6/community/maltego/index.php.

Saya dapat menjalankan Maltego dengan memberikan perintah berikut ini:

# maltego

Pada saat pertama kali dijalankan, layar Welcome to Maltego! akan muncul. Setelah men-klik tombol Next, saya perlu email dan password sesuai dengan yang saya pakai pada saat mendaftar sebelumnya. Setelah men-klik Next, proses login akan dilakukan. Bila berhasil, saya akan memperoleh API key yang aktif selama dua hari (setelah itu, saya perlu mengaktifkannya kembali). Saya kemudian men-klik tombol Next dua kali. Pada langkah terakhir, saya memilih Run a machine (NEW!!) dan men-klik tombol Finish.

Pada dialog yang muncul, saya dapat memilih jenis pekerjaan yang akan dilakukan. Disini saya dapat memilih untuk mencari email address yang berkaitan dengan sebuah perusahaan atau seseorang, tweet yang mengandung kata tertentu, atau informasi lebih lanjut mengenai sebuah URL. Sebagai latihan, saya memilih Footprint L3 untuk mencari informasi lebih lanjut mengenai sebuah domain. Setelah men-klik tombol Next, saya dapat memasukkan nama domain, anggap saja test.com. Setelah itu, saya men-klik tombol Finish.

Saya akan menemukan window Running machine yang sedang bekerja di sisi kanan workspace. Selain itu, terdapat dialog yang memberikan panduan filter dimana saya harus memilih nama domain yang relevan dan men-klik tombol Next agar progress dapat berlanjut.

Maltego akan menampilkan informasi dalam bentuk tree dimana setiap node selalu terhubung ke node lainnya. Setiap node dapat disusun sedemikian rupa oleh pengguna agar mudah dibaca. Sebuah node dalam tree di Maltego disebut sebagai entity. Sebuah entity mewakili informasi seperti nama DNS, alamat email, akun Facebook, nomor telepon, dan sebagainya.

Melihat hubungan antar setiap entity saja tidak cukup. Bila saya men-klik kanan sebuah entity, saya akan menemukan menu Run Transform yang dapat saya pakai untuk menghasilkan sebuah entity baru dari yang sudah ada.

Sebagai contoh, saya ingin mencari tahu apa saja email (berdasarkan hasil search engine) yang berkaitan dengan entity berupa sebuah domain. Bila domain dimiliki oleh sebuah perusahaan, maka biasanya yang dikembalikan adalah alamat email karyawannya. Saya men-klik kanan entity domain tersebut, kemudian memilih Run Transform, Email addresses from Domain, To Emails @domain [using Search Engine]. Maltego akan menciptakan beberapa entity baru yang mewakili email yang ditemukan. Entity baru tersebut akan memiliki link (terhubung) ke entity domain (sebagai sumber transformasi).

Saya kemudian memilih salah satu dari entity yang mewakili email yang ditemukan. Saya kemudian men-klik kanan entity tersebut, memilih Run Transform, Related Email Addresses, All in this set. Maltego akan kembali membuat beberapa entity email baru yang merupakan email yang berhubungan dengan email yang saya pilih. Sama seperti pencarian melalui search engine, tidak selamanya hasil yang dikembalikan akurat, jadi saya masih perlu memilah mana yang relevan. Bila setelah penesuluran saya menemukan entity yang salah, saya dapat memilih entity tersebut beserta seluruh children-nya dengan men-klik tombol Select Children atau Add Children di menu Investigate lalu menekan tombol Del di keyboard. Setelah melakukan transformasi To URLs [Show search engine results], saya menemukan beberapa URL menarik yang berhubungan dengan si pemilik email.

Bila investigasi dilakukan pada entity berupa website, Maltego dapat menampilkan relasi ke entity lain dalam jenis BuiltWith Technology seperti entity Google Webmaster, jQuery, Quantcast Measurement, dan sebagainya.

Kesimpulannya: Saya dapat memperoleh semua informasi yang ada dengan menggunakan search engine, tool whois, menganalisa HTML dan sebagainya. Tetapi cara manual tentu saja lebih repot. Front-end OSINT seperti Maltego mempermudah pekerjaan saya dengan menyediakan cara gampang untuk memahami atau mencari pola dari sekian banyak informasi yang ada.

Mencari Password Dengan Kali Linux

Kali Linux adalah penerus distro BackTrack. Sama seperti BackTrack, distro ini dilengkapi dengan berbagai tools Linux untuk melakukan penetration testing. Dengan Kali Linux, pengguna yang melakukan pengujian keamanan tidak perlu repot men-install atau membuat kode program/script baru. Efek sampingnya: distro Linux seperti ini juga kerap disalahgunakan oleh script kiddie. Istilah script kiddie adalah sebutan untuk orang yang menjalankan tool dan mengikuti panduan tanpa memahami apa yang dilakukan oleh dirinya. Hal ini berbeda dari hacker yang memahami setiap aksi yang dilakukannya dan mampu membuat tool/script-nya sendiri. Dibutuhkan waktu bertahun-tahun untuk mempelajari jaringan komputer dan sistem komputer; script kiddie mengabaikan kenyataan ini dengan memakai tools atau panduan singkat yang ‘script kiddie’-friendly. Fakta bahwa script kiddie dapat men-download dan menjalankan tools yang ada di Kali Linux secara bebas menunjukkan bahwa ancaman terhadap keamanan komputer semakin besar.

Pada kesempatan ini, saya akan mencoba beberapa tool di Kali Linux yang dapat dipakai untuk mencari password (menguji apakah password aman). Sebagai percobaan, saya akan mencoba mencari password pada router yang saya pakai. Router tersebut (IP 192.168.1.1) memiliki interface web dengan memakai basic authentication dari HTTP.

Untuk mencari password router tersebut, saya dapat memakai tool yang ada di Applications, Kali Linux, Password Attacks, Online Attacks. Saya dapat menggunakan salah satu dari tool berikut ini: burpsuite, hydra, medusa, ncrack, patator, phrasendrescher. Tool tersebut pada dasarnya memiliki fungsi umum yang sama, hanya dibuat oleh pihak yang berbeda. Saya akan memakai tool hydra pada percobaan ini.

Secara garis besar, ada dua cara untuk menemukan sebuah password.

Cara pertama adalah dengan mencoba seluruh kombinasi password yang ada. Cara ini membutuhkan waktu yang sangat lama dan hampir mustahil bila pengguna memakai password yang panjang. Sebagai contoh, anggap saja pengguna membuat password 6 karakter yang terdiri atas huruf A sampai Z. Kombinasi password yang mungkin dapat dihitung dengan rumus 26^6 (26 x 26 x 26 x 26 x 26 x 26) dimana hasilnya adalah 308.915.776 kombinasi. Bila seandainya dalam 1 menit saya dapat memproses 600 kombinasi, maka waktu yang saya butuhkan untuk menemukan password adalah 514.859 menit atau 8.580 jam atau 358 hari. Butuh waktu hampir setahun. Ini masih belum menyertakan karakter seperti huruf kecil, angka dan simbol. Btw, kinerja brute force masih dapat ditingkatkan lagi dengan memakai mesin yang lebih cepat dan mendistribusikannya pada beberapa komputer yang berbeda.

Untuk melakukan brute force dengan hydra, saya dapat memberikan perintah seperti berikut ini:

# hydra -l admin -x 6:6:A 192.168.1.1 http-get /

Pada perintah di atas, saya menganggap nama user selalu adalah admin. Tool tersebut akan mencoba kombinasi 6 karakter dari seluruh huruf kapital A-Z. Bila saya ingin men-pause operasi brute force, saya dapat menekan tombol CTRL+C. Hydra akan membuat file hydra.restore di lokasi direktori yang sedang aktif. Untuk melanjutkan proses brute foce, saya cukup memberikan perintah berikut ini:

# hydra -R

Kesimpulannya: Walaupun teknik brute force memiliki hasil yang lebih pasti, ia membutuhkan waktu yang lama.

Cara kedua adalah dengan menggunakan daftar kata (dictionary attack). Pada metode ini, daripada mencoba kombinasi karakter yang mungkin, saya mencoba menggunakan password yang umum digunakan (misalnya berdasarkan daftar kata di kamus). Kali Linux sudah menyediakan daftar password umum di lokasi /usr/share/wordlists. Saya hanya perlu men-unzip-nya dengan perintah seperti berikut ini:

# cd /usr/share/wordlists/
# gunzip rockyou.txt.gz
# ls -l
total 136644
-rw-r--r-- 1 root root 139921507 Mar  3  2013 rockyou.txt

Selain itu, tool ncrack dilengkapi beberapa daftar password yang dapat saya pakai di tools lainnya. Saya dapat melihatnya dengan perintah seperti berikut ini:

# cd /usr/share/ncrack
# ls -hs
total 923K
6.5K common.usr
3.5K default.usr
512  minimal.usr
512  ncrack-services
402K top50000.pwd
46K  default.pwd
22K  jtr.pwd
385K myspace.pwd
58K  phpbb.pwd

Untuk menggunakan sebuah file berisi daftar kata sebagai password pada hydra, saya memberikan perintah seperti berikut ini:

# hydra -l admin -P /usr/share/wordlists/rockyou.txt 192.168.1.1 http-get /

Teknik ini tidak selalu berhasil, tetapi biasanya dicoba terlebih dahulu sebelum penyerang nekat menggunakan brute force.

Pada kategori Password Attacks, Online Attacks, juga ada tool seperti burpsuite, webscarab, dan zaproxy. Ketiganya adalah aplikasi Java dengan GUI yang bekerja sebagai web proxy yang dilengkapi fasilitas spider, scanner, dan sebagainya. Versi burpsuite yang ada pada Kali Linux adalah versi free edition dengan kemampuan yang lebih terbatas. Walaupun demikian, tab Intruder tetap dapat dipakai untuk mendefinisikan payload berdasarkan HTTP request yang di-capture oleh proxy tersebut. Pilih payload type berupa Brute forcer untuk melakukan brute force atau pilih Runtime file untuk melakukan dictionary attack berdasarkan file daftar kata. Sayangnya, pada versi free edition, terdapat batas waktu saat melakukan eksekusi ‘serangan’.

Kesimpulannya: Gunakan password dengan jumlah karakter yang panjang dan beberapa kombinasi karakter (huruf, angka, dan simbol) untuk menjaga password dari serangan brute force. Jangan memakai password umum seperti abc123, iloveu, h3av3n dan sebagainya karena mereka biasanya sudah terdaftar di kamus yang dipakai untuk dictionary attack. Selain itu, sebagai developer, jangan membolehkan pengguna untuk memasukkan password yang salah berkali-kali tanpa batas (karena bisa saja proses brute force atau dictionary attack sedang berlangsung).

Memakai System Call Linux Di Assembly

Untuk memanggil system call Linux, programmer assembly harus mengetahui nomor definisi system call yang disebut system call numbers.  Informasi ini dapat diperoleh dengan membaca file /usr/include/asm/unistd_32.h.  Berikut ini adalah contoh isi file tersebut:

#ifndef _ASM_X86_UNISTD_32_H
\#define _ASM_X86_UNISTD_32_H

/*
* This file contains the system call numbers.
*/

\#define __NR_restart_syscall      0
\#define __NR_exit          1
\#define __NR_fork          2
\#define __NR_read          3
\#define __NR_write          4
\#define __NR_open          5
\#define __NR_close          6
\#define __NR_waitpid          7
\#define __NR_creat          8
\#define __NR_link          9
\#define __NR_unlink         10
\#define __NR_execve         11
...
\#define __NR_inotify_init1    332
\#define __NR_preadv        333
\#define __NR_pwritev        334
\#define __NR_rt_tgsigqueueinfo    335
\#define __NR_perf_event_open    336

Isi file di atas menunjukkan bahwa pada sistem operasi Linux tersebut, terdapat 337 system call yang dapat dipanggil oleh programmer assembly, mulai dari 0 hingga 336. Setelah menemukan system call number, langkah berikutnya adalah menentukan apa saja yang dibutuhkan untuk memanggil system call tersebut.  Salah satu cara yang dapat dilakukan adalah dengan memanggil perintah man.  Walaupun ditujukan bagi programmer C, informasi yang ditampilkan oleh man cukup berguna bagi programmer assembly yang ingin memanggil system call tersebut.  Sebagai contoh, bila programmer ingin melihat informasi untuk system call ber-nomor 4 (didefinisikan sebagai __NR_write), maka ia dapat memberikan perintah:

$ man 2 write
NAME
write - write to a file descriptor

SYNOPSIS
\#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

...

Untuk mengerjakan system call di Linux, programmer assembly menggunakan INT dengan nomor interrupt 0x80.  Sebelum memberikan INT 0x80, nomor system call (sesuai dengan yang ada di file unistd_32.h) harus diletakkan terlebih dahulu di register EAX, sehingga kernel Linux dapat mengetahui system call apa yang akan dikerjakan.  Selain itu, bila ada, nilai parameter harus diberikan pada register tertentu dengan urutan seperti berikut ini:

  • Nilai parameter pertama di-isi pada register EBX
  • Nilai parameter kedua di-isi pada register ECX
  • Nilai parameter ketiga di-isi pada register EDX
  • Nilai parameter keempat di-isi pada register ESI
  • Nilai parameter kelima di-isi pada register EDI
  • Bila jumlah parameter lebih dari lima, EBX mengandung pointer ke lokasi memori yang berisi input parameter secara berurutan.

Pada system call write, informasi yang diberikan oleh man pages menunjukkan bahwa dibutuhkan tiga parameter, yaitu fd, *buf, dan count.  Dengan demikian:

  • Register EBX mengandung file descriptor (fd)
  • Register ECX mengandung pointer ke string yang akan ditampilkan (*buf)
  • Register EDX mengandung informasi jumlah karakter di string tersebut (count)

Nilai kembalian dari sebuah system call akan ditampung di register EAX.

Contoh kode program assembly secara lengkapnya akan menjadi:

$ vi test.s
.section .data
tulisan:
.ascii "Ini program pertama saya.\n"

.section .text
.globl _start
_start:
movl $4, %eax           # System call nomor 4 (write)
movl $1, %ebx           # Parameter 1: file descriptor = 1 (stdout)
movl $tulisan, %ecx     # Parameter 2: string yang dicetak
movl $26, %edx          # Parameter 3: jumlah karakter (26 huruf)
int $0x80               # Memanggil kernel Linux

movl $1, %eax           # System call nomor 1 (exit)
movl $0, %ebx           # Parameter 1: status code
int $0x80               # Memanggil kernel Linux

$ as -o test.o test.s
$ ld -o test test.o
$ ./test
Ini program pertama saya.

I/O Programming: Mengatur Lampu LED di Keyboard

Belakangan ini saya kerap bertemu dengan seorang dosen yang mengajar mata kuliah sistem operasi, dan kami sering terlibat dalam diskusi menarik.  Mengajarkan materi sistem operasi yang berorientasi praktek membutuhkan tantangan lebih besar.  Hal ini tidaklah berlebihan, karena kebanyakan teori sistem operasi tidak cukup berguna untuk dipakai dalam membuat sistem operasi.  Misalnya, dalam mata kuliah sistem operasi, hampir tidak pernah membahas tentang keyboard controller.  Tetapi, pada kenyataannya, pemahaman akan cara kerja keyboard controller wajib dibutuhkan dalam pembuatan sebuah sistem operasi.

Untuk membaca dan menulis informasi ke keyboard controller, seseorang perlu membaca dan menulis port 0x60 dan 0x64.  Dengan membaca port 0x64, programmer dapat mengetahui status keyboard controller.  Dengan menulis pada port 0x60, seseorang dapat mengirimkan perintah pada keyboard controller.  Misalnya, dengan mengirim nilai 0xED pada port 0x60, programmer dapat mengatur indikator LED apa saja yang nyala yang diwakili dengan nilai berikutnya yang dikirim pada port 0x60.

Pertanyaan pertama yang harus dijawab adalah platform apa yang harus dipergunakan oleh mahasiswa?  Bahasa pemograman yang dipergunakan dapat berupa assembly dan C, dimana bahasa C adalah pilihan yang lebih masuk akal.    Bila menggunakan platform Windows, maka mahasiswa akan memakai Visual C++, sebuah tools standar untuk pemograman low-level di Windows.  Sayangnya, penggunaan fungsi _inp() dan _outp() di Visual C++ dibatasi hanya pada pemograman driver saja.   Hal ini dilakukan dengan alasan keamanan, sehingga tidak sembarangan aplikasi boleh melakukan akses I/O yang notabene dapat berbahaya sekali.  Pilihan lain adalah menggunakan platform lain, misalnya menggunakan sistem operasi Linux.  Pada Linux, tersedia fungsi ioperm() yang memungkinkan program biasa melakukan operasi I/O.  Syaratnya adalah program tersebut dijalankan dengan hak akses super user.

Berikut adalah sebuah contoh program C di Linux yang membuat LED keyboard (LED indikator num lock, caps lock, dan scroll lock) menyala berurutan:

#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>

void kirimCommand(char command) {
  char c = 0;
  while (1) {
    c = inb(0x64);
    if ((c&2)==0) break;
  }
  outb(command, 0x60);
}

int main() {
  if (ioperm(0x60,5,1)) {
    printf("Program tidak memiliki hak akses\n");
    return -1;
  }
  printf("Perhatikan indikator LED di keyboard!\n");
  int i=0;
  char statusLED = 1;
  while (i<100) {
    kirimCommand(0xED);
    kirimCommand(statusLED);
    if (statusLED==4) statusLED=1; else statusLED<<=1;
    i++;
    sleep(1);
  }
}

Pada fungsi kirimCommand(char command) di atas, setiap kali sebelum mengirim command ke port 0x60, program akan memeriksa apakah buffer input sudah kosong.  Hal ini dilakukan dengan membaca status keyboard controller di port 0x64, dan memeriksa isi dari bit 2.

Variabel statusLED berisi pola LED yang akan dinyalakan nantinya.  Hanya tiga bit yang dipakai, yaitu bit 0 untuk LED Scroll Lock, bit 1 untuk LED Caps Lock, dan bit 2 untuk LED Num Lock.

Setelah itu, program dapat di-compile dengan gcc dan dijalankan, dengan memberikan perintah seperti:

$ gcc -o keyboard keyboard.c
$ sudo ./keyboard
[sudo] password for user:
Perhatikan indikator LED di keyboard!

Memakai Snort Sebagai IPS Di Notebook

Kedengarannya memang aneh, kenapa harus menjalankan Snort di notebook?  Bukankah biasanya Snort IPS dijalankan pada komputer server yang memiliki dua network card (NIC) terpisah?  Tapi, bukanlah hal mustahil untuk menjalankan Snort tanpa melalui bridging (dua network card).  Artikel ini mengasumsikan penggunaan DAQ module NFQ seperti yang dituliskan di artikel sebelumnya.  Artikel ini juga mengasumsikan penggunaan Linux UBuntu 10 LTS.  Setelah Snort berhasil dikonfigurasi dan dijalankan dengan baik, yang perlu dilakukan sekarang adalah melakukan pengaturan iptables.

Jika memakai Snort sebagai IPS pada notebook atau komputer yang dipakai untuk berselancar di Internet, pengguna harus memilih untuk mengorbankan rules di iptables atau tidak:

  • Seluruh packet yang masuk pertama kali akan diterima oleh modul Netfilter di Ubuntu.¬† Untuk pendeteksian secara maksimal, packet yang masuk dapat dengan segera dialihkan ke Netfilter Queue guna diolah oleh Snort.¬† Akan tetapi, packet tersebut tidak dicocokkan satu per satu dengan rules iptables lainnya lagi.
  • Atau, packet yang masuk dapat di-saring dulu dengan rules di iptables, baru kemudian packet yang lolos dialihkan ke Netfilter Queue untuk diolah oleh Snort.¬† Kekurangannya adalah Snort tidak memperoleh packet yang mengidentifikasikan serangan secara lengkap, karena beberapa packet mungkin sudah disaring terlebih dahulu oleh Netfilter.

Apapun metode yang dipakai, semuanya melibatkan penambahan rules di iptables untuk mengalihkan packet ke Netfilter Queue.  Yang membedakan adalah urutan/posisi rule tersebut.  Rules tersebut terlihat seperti:

iptables -A INPUT -j QUEUE
iptables -A OUTPUT -j QUEUE

Tentunya pengguna dapat menambahkan parameter lainnya sesuai kebutuhan dan selera, tetapi yang harus ada adalah -j QUEUE yang menunjukkan bahwa packet akan ditampung oleh Netfilter Queue.  Bila tidak aplikasi yang membaca queue, misalnya Snort sedang tidak berjalan, maka packet akan di-drop.

Bagi yang menggunakan ufw (uncomplicated firewall),  dapat langsung mengedit file yang ada di /etc/ufw/after.rules atau /etc/ufw/before.rules.  Jangan lupa mematikan dan menyalakan kembali firewall setelah melakukan perubahan pada file.  Sebagai contoh, seseorang dapat menambahkan baris berikut pada /etc/ufw/after.rules:

-A ufw-after-input -j QUEUE
-A ufw-after-output -j QUEUE

Langkah selanjutnya, karena Snort dipakai pada “perangkat desktop” yang menjalankan banyak program sehari-hari dan belum tentu stabil, pengguna sebaiknya menambahkan program Snort pada daftar daemo yang diproses oleh Upstart di Ubuntu.¬† Upstart adalah sebuah program bawaan di Ubuntu yang memiliki fungsi seperti /etc/inittab di UNIX.¬† Upstart dapat memantau proses Snort, dan bila oleh suatu hal, Snort harus berhenti dijalankan, Upstart akan secara otomatis “menghidupkan” Snort kembali.

Buat sebuah file baru di direktori /etc/init, misalnya /etc/init/snort.conf yang memiliki isi seperti berikut ini:

start on started ufw
stop on stopping ufw
respawn
exec /usr/bin/snort --daq nfq -D -c /etc/snort.conf -Q

Pada konfigurasi di atas, Snort akan dijalankan setelah ufw, dan akan dimatikan sebelum ufw dimatikan.  Hal ini dilakukan karena Snort memakai modul NFQ yang berkaitan erat dengan iptables.  Jangan lupa untuk menyertakan respawn yang berarti proses akan secara otomatis dihidupkan kembali bila tidak dimatikan melalui Upstart.

Setelah ini, restart komputer, dan berikan perintah seperti:

#initctl list
...
snort start/running, process 2084
...

Hal ini memperlihatkan bahwa Upstart telah menjalankan Snort secara otomatis begitu notebook/komputer rumah dijalankan, dan akan terus menjaga agar proses Snort senantiasa aktif.