Fungsi Hash Kriptografi (Bagian 1)

Fungsi hash adalah fungsi yang memetakan dari suatu data (bisa string atau apapun) ke sebuah data lain yang ukurannya biasanya lebih kecil. Ada fungsi hash untuk dipakai di struktur data hash table (outputnya adalah integer) dan ada fungsi hash untuk kriptografi outputnya berupa string alfanumerik dengan panjang tertentu.

Hash Table

Sebelum menjelaskan fungsi hash kriptografi, saya jelaskan dulu contoh fungsi hash biasa karena lebih sederhana. Penggunaan fungsi hash dalam kasus ini adalah untuk menyimpan data ke hash table, supaya gampang diakses lagi.

Misalnya kita punya array yang bisa menyimpan 100 elemen. Kita ingin menyimpan sebuah string, lalu ingin bisa menemukan kembali string itu dengan cepat nantinya, tidak memulai membandingkan satu per satu dari elemen pertama. Untuk melakukan ini kita bisa memakan fungsi hash. Sebuah string akan dimasukkan ke sebuah fungsi hash, hasilnya adalah sebuah angka n dari 0-99, lalu kita masukkan string ke array di indeks itu.

Ketika kita ingin mencari apakah sebuah string ada di array atau tidak, kita hash string tersebut, lalu kita cek apakah di elemen ke-n hasil fungsi hash tersebut ada elemennya. Dalam kasus tertentu, setiap string bisa dipetakan ke slot array yang berbeda.

Tentunya ada kemungkinan lebih dari satu string dipetakan ke satu lokasi, istilahnya terjadi collision. Jika ini terjadi, maka kita bisa menyimpan elemen di indeks n+1, jika sudah ada isinya ke n+2, dst. Sebaliknya ketika mencari elemen, jika isi array di posisi itu kosong artinya elemen tidak ada. Tapi jika di posisi itu ada isinya, kita perlu mengecek elemen berikutnya, jika tidak ada maka cek n+1, n+2 dst. Kasus ini tidak ideal, tapi masih lebih baik daripada mencari dari awal sampai akhir array.

Fungsi Hash

Bagaimana mengubah sebuah string menjadi sebuah angka yang kecil (dalam range tertentu, misalnya dalam kasus di atas 0-99)? cara termudah adalah dengan melakukan sebuah operasi, misalnya penjumlahan terhadap masing-masing huruf, lalu hasilnya di-modulo 100.

Menjumlahkan string saja sangat mudah, tapi sangat mudah juga terjadi collision: dua string yang hurufnya sama tapi posisinya beda akan dihash ke nilai yang sama. Cara yang lebih baik adalah dengan menggunakan bobot, misalnya dalam Java caranya adalah dengan menggunakan formula ini:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Contohnya jika kita punya string ABC (panjangnya 3), maka hasilnya adalah A (65) * 31*31 + B (66)*31 + C (67) = 64578. Sekarang kebetulan 2 hash yang sama lebih kecil, tapi tetap cukup mudah jika dilakukan dengan sengaja. Contohnya string “B#C” akan memiki hash yang sama dengan “ABC”. Ini bisa dicari dengan mudah karena dengan rumus di atas, jika saya ubah A menjadi B (bergeser 1) maka nilai hash akan bertambah sebesar (1*31*31 = 961), dan ini bisa dikompensasi dengan mengurangi karakter kedua sebanyak 31 (dari B menjadi #).

Sebagai catatan: fungsi hash code Java hanya akan menghasilkan angka 32 bit (akan dilakukan modulo jika lebih). Artinya jika kita punya 2^32 + 1 string yang unik, maka pasti ada 1 yang hashnya sama.

Fungsi hash ini belum cukup aman untuk tujuan kriptografi. Saya pernah menemui aplikasi yang memakai ini untuk fungsi hash penting, dan ini merupakan hal yang salah.

Fungsi Hash Kriptografi

Fungsi hash kriptografi berbeda dari fungsi hash biasa, tapi memiliki kesamaan. Di dalam keduanya kita ingin “mengkompress” data menjadi bilangan kecil. Dalam hash kriptografi, kita ingin agar:

  • jika data diubah sedikit saja, hashnya akan berbeda
  • dari sebuah nilai hash X, kita tidak bisa membentuk sebuah input sedemikian sehingga hashnya adalah X

Jika tiap kali diberikan sebuah hash X dan kita selalu bisa menemukan sebuah string sedemikian hingga hashnya X tertentu maka fungsi hash tersebut berhasi dipecahkan (broken).

Kegunaan hash ini:

  • Untuk verifikasi data yang besar. Jika hashnya tidak berubah, berarti data tidak diutak-atik
  • Untuk penyimpanan password

Untuk penyimpanan password, prinsipnya seperti ini:

  • ketika password dibuat, password akan dihash dan hashnya yang disimpan
  • ketika login, password yang dimasukkan akan dihash, dan nilai hashnya akan dibandingkan

Fungsi hash kriptografi biasanya minimal memiliki output 128 bit. Artinya jika kita mencoba 340282366920938463463374607431768211456 + 1 data yang unik, maka akan ada 1 yang hashnya sama. Sebagai latihan, cobalah membagi bilangan itu dengan jumlah detik dalam setahun, lalu asumsikan 1 detik bisa melakukan berapa operasi hash, dan kalikan dengan 1 milyar komputer di dunia, hasilnya merupakan bilangan tahun yang sangat besar.

Saat ini ada banyak fungsi hash dan biasanya akan menghasilkan string biner antara 128-512 bit. Atau jika dijadikan karakter heksa: antara 32 – 128 karakter heksa. Beberapa fungsi hash yang umum adalah MD5, SHA1, SHA256, SHA512.

Detail fungsi hash tidak saya bahas di sini, dan biasanya tidak penting detailnya bagi seorang programmer. Berbagai bahasa sudah memiliki library untuk melakukan hashing.Pemahaman diperlukan jika ingin mempelajari keamanannya atau ingin mengetahui bagaimana cara kerja berbagai serangan (seperti hash length extension attack).

Mari kita lakukan hal praktis saja, berikut ini contoh berbagai string yang dihash dan outputnya, perhatikan bahwa Perbedaan sedikit saja akan menghasilkan nilai hash yang sangat berbeda.

Cracking Hash

Cara cracking sebuah hash agar kembali menjadi passsword pada dasarnya ada dua:

  • Dictionary attack
  • Bruteforce attack

Jadi diberikan sebuah kamus kata, kita hash masing-masing kata dan cek apakah hashnya sama dengan yang kita cari. Dalam brute force, kita akan mencoba semua kemungkinan karakter seperti AAAA, AAAB, dst sampai semua simbol dicoba.

Beberapa situs sudah menyimpan hash dari database password yang umum, sehingga jika kita cari hashnya, maka kita akan mendapatkan passwordnya.
Tentunya menyimpan kombinasi hash dan password butuh penyimpanan yang besar, untuk mengatasi ini bisa digunakan Rainbow table.

Penutup

Topik hashing ini belum lengkap, dan masih akan diteruskan di bagian berikutnya. Topik yang belum dibahas antara lain:

  • salting
  • kesalahan pemakaian hash
  • HMAC

Kriptografi RSA Praktis

Topik kriptografi RSA sudah dibahas di banyak artikel dan video oleh orang lain, jadi di sini saya hanya ingin memberikan mengenai topik RSA secara praktis. Praktis di sini artinya saya akan memakai tool openssl dan kode Python untuk melakukan enkripsi.

Prinsip RSA adalah: bahwa kita bisa mencari 3 bilangan: n, e, dan d sedemikian hingga relasi ini terpenuhi.

{\displaystyle (m^{e})^{d}\equiv m{\pmod {n}}}

Jika diketahui e dan n, kita tidak bisa dengan mudah mencari tahu nilai d. Dalam RSA: public key adalah n dan e, sedangkan private key adalah d dan n.

Saya tidak akan menjelaskan secara matematis bagaimana menghasilkan key RSA ini. Penjelasannya bisa dibaca di Wikipedia, tapi ada beberapa hal dasar yang perlu diketahui:

  • n adalah perkalian dari dua buah bilangan prima p dan q.
  • Jika kita bisa memfaktorkan n, maka kita bisa mencari nilai private key.
  • Saat ini tidak ada algoritma efisien untuk memfaktorkan n

Mari kita coba hasilkan key RSA yang kecil . openssl minimum bisa menghasilkan key sangat kecil, sampai 16 bit, tapi tidak bisa melakukan enkripsi dengan key 16 bit karena adanya pengecekan security ekstra (nilai e > n). Jadi untuk contoh ini saya gunakan ukuran key 32 bit:

openssl genrsa -out private.pem 32

Nanti kita akan mendapatkan key yang sangat kecil dalam format base64 , seperti ini.

-----BEGIN RSA PRIVATE KEY----- MCwCAQACBQDLlcMZAgMBAAECBQCZk2iBAgMA7bsCAwDbOwICcwcCAjUFAgJMcw== 
-----END RSA PRIVATE KEY-----

Ini hanya contoh, ketika dijalankan ulang, perintah ini akan menghasilkan key baru. Karena hanya 32 bit, ada kemungkinan key yang dihasilkan bisa sama.

Catatan penting: RSA key yang disarankan saat ini adalah 2048 bit atau lebih. Penggunaan key 32 bit di sini hanya untuk penjelasan, supaya mudah diikuti dan dihitung manual.

Kita bisa mendapatkan public keynya dengan cara seperti ini:

openssl rsa -in private.pem -pubout -out public.pem

Contoh hasilnya seperti ini:

-----BEGIN PUBLIC KEY-----
MCAwDQYJKoZIhvcNAQEBBQADDwAwDAIFAMuVwxkCAwEAAQ==
-----END PUBLIC KEY-----

Di dasar teori RSA kita diberi tahu tentang bilangan p, q, N dsb. Tapi kenapa disimpan dalam bentuk teks seperti itu? Salah satu format standar penyimpanan key adalah PEM, di mana data diencode dengan menggunakan ASN.1. Mungkin lain kali saya akan membahas detail berbagai format key, certificate, dsb, tapi untuk saat ini saya akan membahas hal praktisnya saja.

Format ASN1 bisa diparse dengan asn1parse seperti ini:

$ cat private.pem | openssl asn1parse
0:d=0 hl=2 l= 44 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :00
5:d=1 hl=2 l= 5 prim: INTEGER :CB95C319
12:d=1 hl=2 l= 3 prim: INTEGER :010001
17:d=1 hl=2 l= 5 prim: INTEGER :99936881
24:d=1 hl=2 l= 3 prim: INTEGER :EDBB
29:d=1 hl=2 l= 3 prim: INTEGER :DB3B
34:d=1 hl=2 l= 2 prim: INTEGER :7307
38:d=1 hl=2 l= 2 prim: INTEGER :3505
42:d=1 hl=2 l= 2 prim: INTEGER :4C73

Tapi itu sulit dimengerti, kita bisa mengekstrak berbagai nilai dengan lebih jelas seperti ini:

Private-Key: (32 bit)
modulus: 3415589657 (0xcb95c319)
publicExponent: 65537 (0x10001)
privateExponent: 2576574593 (0x99936881)
prime1: 60859 (0xedbb)
prime2: 56123 (0xdb3b)
exponent1: 29447 (0x7307)
exponent2: 13573 (0x3505)
coefficient: 19571 (0x4c73)
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MCwCAQACBQDLlcMZAgMBAAECBQCZk2iBAgMA7bsCAwDbOwICcwcCAjUFAgJMcw==
-----END RSA PRIVATE KEY-----

Di sana bisa terlihat bahwa n (modulus) adalah 34155896571. Nilai e (public exponent) adalah 65537 dan nilai d (private exponent) adalah 2576574593. Dua bilangan prima p dan q ada di prime1 (p=60859) dan prime2 (q=56123). Nilai exponent1 adalah d mod (p-1) dan exponent2 adalah d mod (q-1) sedangkan coefficient adalah (inverse of q) mod p.

Berbagai nilai disimpan untuk memudahkan perhitungan walaupun redundan. Contoh: nilai exponent 1 adalah d mod (p-1) = 2576574593 mod (60859-1) = 29447, jadi sebenarnya jika exponent1 tidak disimpan, bisa dihitung dari nilai p dan q yang sudah ada. Bahkan untuk enkripsi/dekripsi saja, nilai d, e dan n sudah cukup. Nilai redundan ini kadang memudahkan atau mempercepat perhitungan tertentu dan ini merupakan hal standar yang diatur di  RFC 3447 (Section A.1.2 RSA Private Key Syntax).

Supaya lengkap, ini isinya jika kita periksa isi public key di atas:

$ cat public.pem | openssl rsa -pubin -text 
Public-Key: (32 bit)
Modulus: 3415589657 (0xcb95c319)
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MCAwDQYJKoZIhvcNAQEBBQADDwAwDAIFAMuVwxkCAwEAAQ==
-----END PUBLIC KEY-----

Sekarang kita bisa mengenkrip sebuah kata pendek. Contohnya saya buat file ini (parameter -n agar tidak ada karakter \n di file hasil):

echo -n Helo > input.txt

Atau jika dilihat representasi heksadesimalnya:

hexdump -C input.txt 
00000000 48 65 6c 6f |Helo|
00000004

Atau dalam bentuk bilangan: 0x48656c6f

Sekarang inputnya kita enkrip

cat input.txt | openssl rsautl -encrypt -pubin -raw -inkey public.pem >message.encrypted

Karena key sangat kecil (32 bit) kita hanya bisa mengenkrip data yang sangat kecil. Di sini saya memakai format “raw” (dengan adanya parameter -raw), alias tanpa padding sama sekali dan hasil datanya adalah “mentah” apa adanya tanpa header apapun. Sekarang mari kita lihat hasilnya:

$ hexdump -C message.encrypted 
00000000 1c fb ca d5 |….|
00000004

Hanya 4 byte (32 bit), atau dalam bentuk bilangan adalah: 0x1cfbcad5 atau 486263509 desimal. Rumus enkripsi RSA adalah:

 c \equiv m^e \pmod{n}

Sekarang kita bisa menghitung manual apakah benar enkripsi Helo (0x48656c6f) adalah 0x1cfbcad5. Untuk mudahnya kita gunakan Python:

>> print(hex(0x48656c6f**(65537) % (3415589657)))
0x1cfbcad5L

Hasilnya sesuai harapan, sama dengan hasil enkripsi openssl. Operasi perpangkatan lalu mod akan butuh waktu lama jika dilakukan pada bilangan yang lebih besar. Python punya fungsi built in untuk perpangkatan dengan modulus, seperti ini:

>> print(hex(pow(0x48656c6f, 65537, 3415589657)))
0x1cfbcad5L

Sekarang mari kita dekrip kembali message.encrypted

cat message.encrypted | openssl rsautl -decrypt -raw -inkey private.pem > result.txt

Bisa dicek bahwa output result.txt adalah Helo. Kita juga bisa mendekrip secara manual dengan Python

{\displaystyle c^{d}\equiv (m^{e})^{d}\equiv m{\pmod {n}}}

Atau dalam kode Python:

>> print(hex(pow(0x1cfbcad5, 2576574593, 3415589657)))
0x48656c6fL

Atau jika ingin dalam bentuk teks:

print(bytearray.fromhex("%08x" % (pow(0x1cfbcad5, 2576574593, 3415589657))))
Helo

Demikian artikel perkenalan RSA yang praktis. Dalam artikel ini belum dibahas mengenai hal yang penting yaitu: padding, proteksi password (key di atas tidak dienkrip) dan beberapa kelemahan RSA di kasus tertentu. Hal-hal tersebut rencananya akan saya bahas di tulisan lain.

Hex Editor

Saya beruntung dulu ketika kali pertama belajar komputer lebih dari 25 tahun yang lalu, saya hanya punya satu pilihan sistem operasi: DOS. Sistem operasi ini sangat sederhana dan bisa dimengerti sampai sangat detail. Waktu itu hanya ada 1 filesystem yang bisa dipakai untuk DOS: File Allocation Table (FAT).

PC Tools

Salah satu tool yang sangat membantu saya mendalami berbagai hal yang berhubungan dengan komputer adalah PC Tools. Software “ajaib” ini punya banyak fungsi, dan salah satunya adalah sebagai hex editor. Dengan hex editor ini dulu mudah sekali untuk mengubah string dalam sebuah program (misalnya iseng mengganti pesan error jadi bahasa Indonesia).

Hex editor ini juga berguna untuk memahami mengenai filesystem FAT. Misalnya jika tidak sengaja menghapus sebuah file, saya bisa mengedit sendiri FAT untuk mengembalikan huruf pertama file tersebut. Dalam FAT, jika file dihapus, hanya huruf pertamanya diganti dengan 0xE5, dan selama file belum ditimpa, maka bisa dengan mudah dikembalikan.

Sejak saat itu di berbagai sistem operasi, hex editor menjadi salah satu tool andalan. Berbagai varian tool ini telah membantu saya memahami banyak hal, dari mulai hal kecil misalnya mengecek apakah ada karakter spesial yang tidak terlihat dengan editor teks, sampai memahami format sebuah file.

Di Linux saya tidak memakai tool khusus, biasanya saya melihat representasi hexa sebuah file di command line dengan hexdump (dengan parameter -C). Jika ingin interaktif sayamenggunakan midnight commander (mc) yang merupakan tiruan dari Norton commander yang dulu saya pakai di DOS.

Hex viewer/editor di Midnight Commander

Emacs, editor favorit saya, juga memiliki fitur untuk melihat dan mengedit file dalam mode hex. Ini sangat berguna untuk mengedit file yang tidak terlalu besar (dalam orde megabyte). Jika filenya terlalu besar, emacs terasa lambat, tapi ini wajar karena emacs adalah editor teks yang tidak dirancang khusus untuk file biner berukuran besar.

hexl-mode di Emacs

Di Windows saat ini saya suka memakai HxD. Editor ini cukup lightweight, gratis dan dapat mengedit file berukuran besar dengan cepat. Software ini juga masih diupdate hingga saat ini. Fungsi-fungsi tambahannya (MD5, histogram, dsb) juga cukup berguna.

HxD di Windows

Sekarang ini tidak terlalu mudah untuk memahami sebuah sistem dengan menggunakan hex editor karena berbagai hal sudah sangat kompleks. Contohnya: filesystem EXT2/3/4 atau NTFS sudah terlalu rumit dibaca manual dengan hex editor.

Khusus untuk reverse engineering, sekarang ini sebenarnya banyak juga tool yang bisa membantu memahami format file, misalnya 010 Editor (komersial) dan Kaitai Struct (open source). Tapi tetap saja diperlukan banyak membaca sebelum bisa mulai, tidak seperti jaman dulu di mana semua masih sangat sederhana.

Masih memakai Emacs

Sekitar 8 tahun lalu saya menulis kalau saya mulai nyaman memakai Emacs. Selama ini saya masih sering mencoba-coba editor lain, termasuk juga kembali mencoba mendalami Vim karena saat ini Vim popularitasnya semakin naik dibandingkan Emacs. Tapi pada akhirnya saya masih memilih Emacs.

Ini cuma sekedar catatan pribadi, bukan untuk flamewar. Kalau tidak ditulis saya akan lupa (kalau tidak membaca posting saya sebelumnya, saya tidak ingat bahwa dulu sering memakai editor joe).

Saya mencoba berbagai editor dan IDE termasuk juga yang berbayar seperti Sublime Text dan Intellij Ultimate. Saya memakai IDE yang memudahkan development untuk bahasa atau platform tertentu misalnya .NET dengan Visual Studio, Python dengan Intellij, Android Studio untuk Android, dsb. Tapi untuk berbagai task editing, saya tetap kembali ke Emacs.

Pemakaian emacs yang cukup sering adalah untuk editing teks di komputer remote dan untuk fitur org-mode. Jika sering mengurus server, maka menguasai editor teks terminal merupakan suatu hal yang wajib. Kita bisa saja mengcopy file ke lokal, edit, upload lagi, atau menjalankan remote desktop, tapi keduanya membuang waktu (apalagi jika filenya besar). Jadi menguasai editor teks sederhana seperti Vim, Emacs, Nano, Pico dsb akan sangat membantu.

Editor yang terlalu sederhana seperti Nano dan Pico cukup untuk hal yang sederhana, tapi misalnya kita ingin fitur yang lebih advanced seperti split screen ini tidak bisa dilakukan. Split screen ini sangat sering dibutuhkan, misalnya kasus: ingin membandingkan dan copy paste bagian konfigurasi. Biasanya kita perlu menggabungkan dengan program semacam tmux atau screen untuk split screen (ini pun tidak mudah copy paste). 

Editor yang terlalu sederhana juga tidak mendukung syntax highlighting, misalnya untuk membantu mengedit file JSON atau file konfigurasi. Syntax highlighting bisa membantu mengurangi kesalahan fatal seperti misalnya lupa memberikan kutip tutup.

Jadi pilihan yang masuk akal untuk editing remote menurut saya adalah Vim atau Emacs. Fitur keduanya lebih dari cukup untuk berbagai keperluan editing file remote. Tapi bagi saya berbagai default Vim terlalu mengesalkan dan menurut saya kurang konsisten.

Salah satu contohnya seperti ini: saya memilih teks (dengan visual mode atau v), dan ingin mengganti semua karakter x menjadi z (dengan ESC, :s/x/z/g), defaultnya jika saya lakukan itu, maka SELURUH karakter di baris itu yang diganti (bukan hanya yang terpilih). Jika ingin hanya yang terpilih saja, maka saya harus menambahkan karaktertiga \%V, jadi :s/\%Vx/z/g. Menurut saya default yang tidak menggunakan selection ketika kita sedang memilih adalah hal yang aneh. Untuk mengetik \%V dibutuhkan menekan banyak tombol \, Shift 4, V, lepas shift.

Perintah Emacs namanya cukup mudah diingat, asalkan ingat parsial, kita bisa menekan TAB untuk autocomplete. Dalam contoh di atas, kita tinggal menekan, Alt-x (atau ESC-x), replace<TAB>. Kita bisa memilih: replace-string (menganti string dengan string lain, tanpa regex) atau replace-regexp (replace dengan regex). Di Vim search defaultnya selalu regex, jika tidak ingin regex harus memakai :sno. Ini adalah salah satu default yang menurut saya aneh.

Kedua editor bisa dikonfigurasi, dan bahkan mendukung scripting language untuk menambah fungsi tertentu. Dulu Vim hanya mendukung Vimscript, sebuah bahasa yang nggak standar (satu lagi bahasa yang perlu dipelajari plus berbagai fungsi di bahasa tersebut), sekarang Vim sudah mendukung skrip dalam berbagai bahasa (Lua, Ruby, dsb), tapi karena sudah terlanjur kebanyakan plugin ditulis dalam Vimscript, kebanyakan plugin masih tetap memakai Vimscript. 

Emacs memakai Lisp (elisp), jadi jika sudah tahu lisp maka tidak perlu lagi belajar bahasa baru, hanya perlu tahu berbagai fungsi yang disediakan oleh elisp dan perbedaan dialek Lisp-nya.

Fitur org-mode sangat berguna untuk banyak hal, dari mulai sebagai organizer sampai untuk menulis artikel (atau bahkan buku). Dokumen org-mode bisa diekspor jadi HTML, file open document, atau LaTex (dan dari LaTex menjadi PDF).

Kabar aneka peralatan elektronik lama

Posting ini sekedar untuk catatan mengenai status berbagai elektronik lama yang pernah dituliskan di sini. Beberapa yang diingat saja yang akan dituliskan. Beberapa benda elektronik yang sudah dibeli masih dipakai dan beberapa hanya disimpan saja.

Hal pertama adalah mengenai keyboard. Posting ini dituliskan menggunakan keyboard mekanis yang sudah dituliskan tahun 2013. Keyboard yang menurut saya cukup mahal ini sudah terpakai lebih dari 5 tahun. Rasanya masih cukup enak dipakai untuk mengetik, hanya saja kadang error dan harus cabut colok lagi baru terdeteksi lagi.

Tahun 2015 saya pernah beli tablet Windows harga murah, walaupun jarang dipakai tapi benda ini masih berfungsi dan masih bisa diupdate terus Windows 10-nya. Batere benda ini masih tahan beberapa jam. Saya termasuk kagum dengan ini karena saya pikir hanya akan tahan 1-2 tahun saja.

Sejak tidak membuat lagi aplikasi untuk anak-anak, saya tidak lagi memakai Tablet Xp-Pen yang saya beli tahun 2012. Benda ini masih berfungsi dengan baik, dan masih ada di sekitar meja saya. Hanya saja sampai saat ini belum ada niat lagi untuk memakainya. Sementara wireless router Asus RTN16 yang saya beli sekarang sudah tidak terpakai karena digantikan dengan Mini PC router.

Mini PC router yang dibeli tahun 2017 masih dipakai dan masih sesuai harapan. Benda ini masih relatif baru (belum 2 tahun). Setelah cerita terakhir router ini saya tambahi SSD 120 GB, dan sekalian jadi proxy server. Keyboard mekanis ekstra yang saya tuliskan di posting tersebut juga masih ada dan dipakai, walaupun ada 1 keycapnya yang hilang.

Sementara itu Pinebook yang dibeli tahun 2017 sudah jarang dipakai. Terakhir kali chargernya tidak mau jalan, dan harus cabut batere (harus dibongkar) baru mau jalan lagi. Walau demikian pinebook ini pernah membantu menyelesaikan pentesting sebuah aplikasi yang butuh layar lebar sementara tidak jalan di emulatir. Pinebooknya saya install Android dan layar besarnya cukup berguna.

Printer 3D yang dibeli tahun 2015 sekarang sudah jarang dipakai. Beberapa kali saya mencetak benda sederhana, tapi tetap kurang sabar dari mulai mencari model sampai menunggu printnya selesai. Saya merasa kegunaan terbesar dari benda ini adalah mengajari saya berbagai macam teori mengenai 3D printing.

Renungan hari ini: sebagian besar benda relatif mahal yang saya beli ternyata masih terpakai dan berguna, sebagian lagi memberi pelajaran berharga. Sepertinya yang banyak kurang terpakai justru benda-benda elektronik kecil yang sering saya beli karena iseng hanya beberapa USD saja.

Payload XSS non latin

Tadi saya melihat ada yang sharing payload XSS yang hanya menggunakan karakter dalam Hangul (alfabet bahasa Korea), tanpa huruf latin. Biasanya payload butuh huruf latin karena berbagai fungsi (termasuk fungsi “alert”) butuh karakter latin. Di tulisan ini saya akan menjelaskan cara kerja payload ini lalu membuat versi dengan aksara Jawa.

Payload utamanya seperti ini:

([,하,,,,훌]=[]+{},[한,글,페,이,,로,드,ㅋ,,,ㅎ]=[!!하]+!하+하.ㅁ)
[훌+=하+ㅎ+ㅋ+한+글+페+훌+한+하+글][훌](로+드+이+글+한+'(45)’)()

Saya tidak mengerti bahasa Korea, tapi kita bisa menggunakan search and replace untuk menggantikan tiap bagian dengan huruf latin seperti ini:

([,A,,,,B]=[]+{},[C,D,E,F,,G,H,I,,,J]=[!!A]+!A+A.K) [B+=A+J+I+C+D+E+B+C+A+D][B](G+H+F+D+C+'(45)' )()

Hasilnya: payload di atas tetap akan bisa jalan dengan output yang sama. Tapi bagaimana caranya, kok bisa? pertama kita pecahkan dulu menjadi beberapa bagian seperti ini:

(X) [Y][Y](Z)()

Bagian X adalah:

([,A,,,,B]=[]+{},[C,D,E,F,,G,H,I,,,J]=[!!A]+!A+A.K)

Bagian Y adalah seperti ini (di sini nilai B di kiri sama dengan di kanan)

[B+=A+J+I+C+D+E+B+C+A+D][B]

dan bagian Z adalah

G+H+F+D+C+'(45)'

Mari kita mulai bagian X, ini terdiri dari dua bagian, seperti ini (R=S, T=U)

Subbagian pertama adalah mengassign: [,A,,,,B] dengan []+{}. Di sisi kanan ekspresi [] + {} akan menghasilkan string "[object Object]". Di JavaScript kita bisa mengisi beberapa variabel sekaligus dengan cara: [A,B,C]=[1,2,3], (A=1, B=2, C=3) atau jika ada elemen di kiri dikosongkan, maka nilainya akan diabaikan. Ini istilahnya adalah Destructuring assignment.

Jadi subbagian itu akan mengisi A dengan huruf kedua para string yaitu huruf ‘o’ (huruf pertama adalah ‘[‘) dan B diisi dengan string ‘c’. Jadi bagian R=S bisa disederhanakan jadi [A,B]="oc".

Subbagian kedua di sisi kanannya berisi: !!A (akan menjadi string “true”), !A (akan menjadi string “false”), dan A.K yang akan mengakses property K dari object A. Karena properti ini tidak ada, hasilnya adalah “undefined”. Jadi subbagian kedua adalah mengisi variabel

[C,D,E,F,,G,H,I,,,J]="truefalseundefined""

Atau singkatnya akan mengisi variabel berikut:

 C = t
D = r
E = u
F = e
G = a
H = l
I = s

Jadi bisa kita sederhanakan:

[C,D,E,F,G,H,I] = "trueals"

Kalau digabung keduanya

([A,B]="oc", [C,D,E,F,G,H,I] = "trueals")

atau bisa juga disederhanakan lagi, intinya adalah mengisi variabel seperti ini

([A,B,C,D,E,F,G,H,I] = "octrueals")

Bagian Y seperti ini: dengan nilai B=’c’, A=’o’

[B+=A+J+I+C+D+E+B+C+A+D][B]

Jadi jika digabung menjadi:

["constructor"] ["constructor"]

Bagian terakhir Z, seperti ini: dengan nilai G=’a’, H=’l’, F=’e’, D=’r’ dan C=’t’

G+H+F+D+C+'(45)'

Jadi Z isinya adalah alert(45). Jika digabung penyederhanaan X,Y, Z di atas:

([A,B,C,D,E,F,G,H,I] = "octrueals") ["constructor"] ["constructor"] ("alert(45)")()

karena variabel A,B,C dst sudah disubstitusikan, jadi tidak terpakai lagi:

("octrueals") ["constructor"] ["constructor"]  
("alert(45)")()

String paling kiri sebenarnya tidak penting, karena objek string apapun boleh

("yohanes") ["constructor"] ["constructor"]  
("alert(45)")()

Kenapa itu bisa menampilkan alert?

Bagian pertama "string" ["constructor"] sama saja dengan "string".constructor, yang hasilnya adalah sebuah fungsi konstruktor untuk String. Sebuah fungsi juga merupakan instance sebuah kelas yaitu Function. Function juga memiliki construtor (yang juga merupakan sebuah fungsi yang bisa dipanggil).

Jadi "string".construtor.construtor adalah konstruktor untuk Function. Di Javascript kita bisa membuat fungsi dengan memakai konstruktor Function, seperti ini

f = Function.constructor("alert(1)")

lalu kita bisa memanggil fungsi f(). Atau bisa juga langsung:

Function.constructor("alert(1)")()

Jadi pada dasarnya payload XSS di atas adalah:

"string" ["constructor"] ["constructor"] ("alert(45)")()

Atau:

String.constructor["constructor"]("alert(45)")()

Atau

Function.constructor("alert(45)")()

Jadi sebenarnya payloadnya sederhana, karakter Hangul pun bisa digantikan karakter bahasa apapun. Membuat payload XSS dengan karakter Jawa atau emoji juga bisa.

Jika teks di atas tidak terbaca karena masalah font, seharusnya seperti ini tampilannya dalam bentuk HTML lengkap:

Solid State Drive (SSD)

Posting ini sekedar catatan untuk diri sendiri mengenai pemakaian SSD. Kalau tidak dicatat tidak akan ingat tentang mulai naiknya kapasitas penyimpanan. Dulu waktu punya Nokia 3650, MMC yang kami pakai cuma 16 MB, sedangkan sekarang memori internal HP saya saja sudah 128 GB.

Saya mulai memakai SSD tahun 2012, waktu itu harganya masih 3400 baht untuk kapasitas 60 GB. Sekarang harganya 750 baht untuk kapasitas 120 GB dan bisa lebih murah lagi jika beli merk nggak jelas di AliExpress. Kapasitas 60 GB sudah jarang ditemui di kota ini.

Setelah dipakai agak lama, ternyata saya cukup suka memakai Thinkpad X230, dan jadinya menginstall banyak program di ThinkPad tersebut. Tadinya 60 GB terasa cukup, tapi jika saya masukkan berbagai data (terutama email dan virtual machine) akhirnya terasa kurang juga. Jadi akhirnya kemarin beli SSD 240 GB dengan harga 1290 baht.

Dulu waktu saya mulai memakai SSD, belum semua sistem operasi mendukung TRIM (dan belum semua SSD mendukung perintah ini), tapi sekarang ini sudah jadi default di semua OS baru. Perintah TRIM memungkinan pemakaian SSD lebih awet karena controller SSD bisa diberitahu data mana yang sudah tidak terpakai, jadi bisa lebih mengoptimalkan algorima “wear leveling”. Penjelasan detailnya agak panjang, jadi bisa dibaca di berbagai artikel di web (misalnya ini).

Sekarang semua komputer saya sudah memakai SSD, minimal untuk OS-nya. Saya juga masih memakai HDD ntuk penyimpanan data yang besar. Saya sudah mencoba beberapa merk SSD, termasuk juga beberapa kali mencoba SSD merk China (King Dian), dan sejauh ini semuanya masih awet. Tapi hal ini bukan jaminan, adik saya punya pengalaman buruk dengan SSD dari China yang dibeli online (rusak dalam beberapa bulan), jadi mungkin ini untung-untungan. Untuk data yang penting, saya memilih SSD bermerk dengan garansi, dan tetap membackup data karena SSD bisa rusak tiba-tiba sewaktu-waktu.