11 KiB
Gemastik XVI: Attack-Defense Write-Up
art (solved by 18/20 teams)
# Summary
Diberikan web service dimana peserta bisa menampilkan sebuah ASCII art sesuai dengan inputan text yang diberikan.
# Attack
Terdapat ruby slim server side template injection pada route /art/:word. Hal ini terjadi karena parameter word di-concat secara langsung tanpa adanya proses sanitasi user input terlebih dahulu.
get '/art/:word' do
return Slim::Template.new{ '<iframe height="100%" width="100%" frameborder="0" src=https://asciified.thelicato.io/api/v2/ascii?text=' + params[:word] + '></iframe>' }.render
end
# Defense
Defense dapat dilakukan dengan cara menggunakan template parameter pada framework Slim atau string interpolation pada bahasa pemrograman ruby.
gemas-fetcher (solved by 9/20 teams)
# Summary
Diberikan website yang akan melakukan request ke url yang diberikan oleh user menggunakan curl, wget, dan module python urllib.request. Sebelum mengirimkan request, url yang diberikan akan divalidasi terlebih dahulu dengan beberapa pengecekan yang salah satunya adalah pengecekan scheme. Untuk mendapatkan scheme dari url yang diberikan user, backend menggunakan module python urlparse. Apabila scheme dari url yang diberikan adalah file atau ftp maka user akan mendapatkan sebuah error message jika scheme itu tidak boleh digunakan.
# Attack
Module python urlparse terdapat sebuah CVE (CVE-2023-24329) yang dapat digunakan untuk melakukan bypass pengecekan tersebut. Dengan menambahkan sebuah whitespace di depan url, urlparse akan menganggap url yang diberikan tidak memiliki scheme apapun, sehingga pengecekan yang dilakukan dapat dibypass. Dari ke-3 method yang berikan (curl, wget, urllib.request), hanya urllib.request yang berhasil digunakan untuk melakukan request dengan url yang memiliki whitespace di depannya.
# Defense
Cara termudah untuk memitigasi CVE tersebut adalah dengan menghapus whitespace yang ada di depan url sebelum melakukan parsing menggunakan urlparse.
hirnfick (solved by 4/20 teams)
# Summary
Terdapat sebuah service web dimana peserta dapat menjalankan potongan kode program esoteric langiuage brainfuck. Pada backend, potongan kode brainfuck dijalankan menggunakan sebuah program C yang memiliki celah keamanan Out-of-Bound access (OOB) pada array data. Dengan menggunakan celah tersebut, peserta dapat menugbah alur program sehingga mendapatkan Remote Code Execution.
Attachment yang diberikan kepada peserta tidak terdapat source code dari program C yang menjalankan kode brainfuck, namun peserta diharapkan dapat menggunakan alat-alat yang tersedia (seperti disassembler atau decompiler) untuk rekonstruksi source code dari sebuah file binary.
# Attack
int debug = 0;
char data[1024] = {0};
char code[1024] = {0};
...
int main() {
// get brainfuck code from user input and execute
...
if (debug) {
puts(data);
}
}
Pada saat eksekusi potongan kode brainfuck, terdapat OOB pada array data[1024]. Dengan celah OOB tersebut, nilai debug dapat diubah menjadi truthy/selain 0 dan fungsi puts() dapat diubah juga menjadi system() dengan mengubah Global Offset Table pada program yang sedang berjalan. Sehingga memungkinkan program untuk mengeksekusi system(data) atau mendapatkan akses Remote Code Execution.
# Defense
Peserta diberikan beberapa opsi untuk melakukan defense:
- Patch OOB access yang terdapat pada potongan kode C yang menjalankan kode brainfuck
- Implementasi brainfuck interpreter menggunakan python pada web server
Pada pengecekan SLA, patch yang diterapkan oleh peserta harus melewati beberapa set pengecekan Input/Output pada brainfuck interpreter. Input yang diberikan diambil dari beberapa potongan kode yang terdapat pada laman Brainfuck Wikipedia dan Brainfuck Code generator. Jika Output tidak sesuai, maka pengecekan dianggap gagal.
burvesigner (solved by 1/20 teams)
# Summary
Terdapat web service yang mana peserta dapat melakukan login sebagai role guest. Ketika peserta melakukan login, service akan meng-generate suatu signature yang digunakan sebagai token oleh user tersebut dengan menggunakan algoritme variasi Elliptic Curve Digital Signature Algorithm (ECDSA) dengan kurva secp112r1.
Dikutip dari Wikipedia, berikut proses ECDSA signature generation dilakukan:
# Attack
Pada poin ke-3, nonce k yang digunakan pada proses signature generation harus suatu angka secure random. Namun pada challenge ini, nonce yang digunakan oleh service bukanlah nilai secure random, sehingga peserta dapat memanfaatkan kondisi ini untuk melakukan signature forgery dengan role yang berbeda. Peserta harus melakukan signature forgery dengan role admin untuk berhasil mendapatkan flag (attack) tim lain.
Berikut potongan kode program yang memiliki kerentanan pada proses signature generation:
def sign(self, msg):
self.set_keys()
k = (int(time() * 1337) << self.u) + self.v
R = k * self.C.G
s = (self.hash(msg) - self.x * R.x) * pow(k, -1, self.C.q) % self.C.q
sig = b"".join(map(self.to_bytes, [R.x, R.y, s]))
return urlsafe_b64encode(sig)
Terlihat bahwa nonce k dibangkitkan dengan formula t * 2^u + v dimana nilai t memungkinkan untuk di-bruteforce oleh peserta dalam waktu yang singkat, nilai u merupakan konstanta, dan nilai v merupakan random number berukuran u bits.
Dengan mengumpulkan setidaknya 2 buah signature (melakukan login guest sebanyak 2 kali), maka peserta dapat melakukan eliminasi 2 persamaan untuk mendapatkan nilai nonce k dan private key yang digunakan oleh service.
# Defense
Dengan mengubah nonce k menjadi nilai secure random, peserta seharusnya sudah berhasil melakukan defense pada service mereka. Sebagai poin tambahan, terdapat implementasi yang kurang tepat pada proses signature generation. Pada proses signature generation, fungsi hash yang digunakan oleh service adalah CRC32.
def hash(self, msg):
return crc32(msg)
Hal ini bukanlah best practice mengingat CRC seharusnya hanya digunakan sebagai checksum pada pengecekan integritas suatu data, namun hal ini tetaplah sulit dan kompleks untuk di-exploit dalam durasi yang singkat seperti durasi kompetisi babak final ini. Implementasi yang merupakan best practice adalah dengan menggunakan fungsi hash yang telah teruji aman seperti fungsi hash SHA.
xl (solved by 0/20 teams)
# Summary
Diberikan web service dimana peserta bisa melakukan convert file excel (xlsx) ke format json.
# Attack
Terdapat celah Local file inclusion ketika menggunakan options type=file karena tidak ada pengecekan type buffer pada library yang digunakan. Berikut potongan kode dimana maintainer library sudah aware terhadap problem ini tetapi tidak diimplementasikan.
case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options);
# Defense
Peserta dapat melakukan defense dengan berbagai cara, seperti memberikan default value type sebagai buffer atau menghapus parameter options karena parameter options tidak digunakan sama sekali oleh service ini.
gemas-notes (solved by 0/20 teams)
# Summary
Soal terdiri dari 2 microservice:
- Validation Service: Service ini digunakan untuk memvalidasi JSON yang dikirim oleh user sebelum dikirimkan ke
gemas-notesservice - Gemas Notes (Notes Service): Actual service yang digunakan untuk mengolah notes (
Create Read Update Delete)
Perbedaan behavior JSON parser yang digunakan kedua microservice dapat dimanfaatkan untuk mengeksploitasi celah Blind SQL Injection yang terdapat pada service gemas-notes.
# Attack
Apabila terdapat 2 key yang sama dalam sebuah JSON, contohya {"id":1,"id":2,"data":"halo"}, module golang jsonparser yang digunakan service gemas-notes akan selalu menggunakan data yang pertama (id=1), sedangkan module python jsonschema yang digunakan validation-service untuk melakukan validasi akan selalu menggunakan data yang kedua (id=2). Karena perbedaan behavior ini, peserta dapat memanfaatkannya untuk melakukan bypass terhadap validasi yang dilakukan oleh validation-service untuk mengeksploitasi celah Blind SQL Injection yang terdapat pada endpoint /notes/count di dalam service gemas-notes. Final payload exploitnya adalah sebagai berikut:
{
"count_by": "title",
"keyword": "<SQLi Payload Here>",
"keyword": "hehe"
}
# Defense
Untuk defense, peserta hanya diberikan akses SSH ke service gemas-notes, sehingga terdapat 2 hal yang dapat dilakukan:
- Mengubah parsing JSON agar tidak menggunakan module
jsonparser - Menggunakan prepared statement untuk patch celah SQLi
pasta (solved by 0/20 teams)
# Summary
Terdapat web service dimana peserta dapat melakukan register user dan login user. Ketika user melakukan login, service akan membangkitkan token dengan spesifikasi format yang terinspirasi dari PASETO.
Token tersebut selanjutnya dapat digunakan user sebagai mekanisme autorisasi. Jika role dari user adalah admin maka user akan mendapatkan flag di endpoint /flag. Maka, objektif user disini adalah melakukan signature forgery agar dapat mengubah token user dari role user ke role admin.
# Attack
Dalam implementasi signing-nya, service menggunakan algoritma ECDSA dengan metode pembangkitan nonce yang deterministik, yaitu dari hasil HMAC(d, m) dimana d sebagai HMAC secret adalah private key dan m adalah pesan yang akan di-sign.
Fungsi hash dan kurva yang digunakan tergantung dari versi token yang dipilih oleh user, dimana:
- version 1: kurva P-224 dengan SHA-224
- version 2: kurva P-256 dengan SHA-256
- version 3: kurva P-384 dengan SHA-384
- version 4: kurva P-521 dengan SHA-512
Jika kita perhatikan, version 4 menggunakan kurva P-521 dan fungsi hash SHA-512, dimana jumlah operasi bits yang digunakan berbeda. Hal ini mengakibatkan pembangkitan nonce menggunakan SHA-512 mengalami bias sebanyak 9 bits. Mengutip dari paper ini, kita dapat melihat masalah ini sebagai Hidden Number Problem (HNP) untuk mendapatkan private key.
Dibutuhkan sekitar 100 sampai 110 signature dengan m yang berbeda untuk mendapatkan private key yang akurat dari HNP. Jadi, peserta perlu membuat sebanyak 100 user yang berbeda, lalu login satu per satu menggunakan user tersebut.
# Defense
Kita dapat memitigasi celah ini dengan menggunakan mekanisme pembangkitan nonce yang terstandarisasi. Untuk deterministic nonce, kita dapat menggunakan RFC-6979 dalam membangkitkan nonce secara aman meskipun fungsi hash menggunakan jumlah bit yang berbeda.
