Files
attack-defense-platform/exploits.old/README.md
T
2025-10-10 22:18:06 +07:00

180 lines
11 KiB
Markdown

# 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.
```rb
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](https://github.com/slim-template/slim/blob/5f7a7ffe43f3c91c2e63027491349ad1c7bfb507/test/core/test_code_evaluation.rb#L169) pada _framework_ Slim atau [_string interpolation_](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/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
```c
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:
1. Patch OOB access yang terdapat pada potongan kode C yang menjalankan kode brainfuck
2. 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](https://en.wikipedia.org/wiki/Brainfuck) dan [Brainfuck Code generator](https://copy.sh/brainfuck/text.html). 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](https://neuromancer.sk/std/secg/secp112r1).
Dikutip dari Wikipedia, berikut proses ECDSA signature generation dilakukan:
![](https://hackmd.io/_uploads/H1LAwvJ1a.png)
#### # 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:
```py=
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.
```py=
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.
```js
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:
1. **Validation Service**: Service ini digunakan untuk memvalidasi JSON yang dikirim oleh user sebelum dikirimkan ke `gemas-notes` service
2. **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:
```json!=
{
"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:
1. Mengubah parsing JSON agar tidak menggunakan module `jsonparser`
2. 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](https://paseto.io/).
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](https://eprint.iacr.org/2019/023.pdf), 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](https://www.rfc-editor.org/rfc/rfc6979) dalam membangkitkan nonce secara aman meskipun fungsi hash menggunakan jumlah bit yang berbeda.