Menghasilkan $35.000 dari bug bounty private pages GitHub
(robertchen.cc)Kisah seorang siswa kelas 12 SMA yang punya waktu luang karena Covid lalu berburu bug bounty dan menerima $35.000 dari bug bounty pada private pages GitHub.
Ia melaporkan bug bounty pada private pages GitHub, dan ada dua bonus CTF.
-
$10.000: membaca flag dari
flag.private-org.github.iotanpa interaksi pengguna. Jika flag ini bisa dibaca dari akun di luar organisasiprivate-org, ada bonus tambahan $5.000. -
$5.000: membaca flag dari
flag.private-org.github.iomelalui interaksi pengguna.
Alur autentikasi
GitHub Pages di-host pada domain terpisah, github.io, sehingga cookie autentikasi milik github.com tidak dikirim ke server private pages. Karena itu, autentikasi private pages tidak dapat mengetahui identitas pengguna tanpa integrasi tambahan dengan github.com. Karena itu, GitHub membuat alur autentikasi kustom.
-
Saat mengunjungi private page, server memeriksa keberadaan cookie
__Host-gh_pages_token. -
Jika cookie tidak ada atau tidak valid, server private page akan mengalihkan ke
https://github.com/login. -
Pengalihan ini juga menetapkan nonce pada cookie
__Host-gh_pages_session.- Cookie ini menggunakan prefiks cookie __Host- sehingga JavaScript dari luar domain host tidak bisa menetapkannya.
-
/loginmengalihkan ke/pages/auth?nonce=&page_id=&path=. -
Di sini dibuat cookie autentikasi sementara yang diteruskan dari parameter
tokenkehttps://pages-auth.github.com/redirect. -
/redirectmeneruskan kehttps://repo.org.github.io/__/auth. -
Endpoint terakhir ini menetapkan cookie autentikasi
__Host-gh_pages_tokendan__Host-gh_pages_idpada domainrepo.org.github.io. -
Di sini nonce dari
__Host-gh_pages_sessionyang telah ditetapkan sebelumnya juga diperiksa.
Path permintaan asli dan ID page masing-masing disimpan dalam query parameter path dan page_id, dan nonce juga disimpan dalam parameter nonce.
Eksploitasi
Return CRLF
-
Kerentanan pertama adalah injeksi CRLF pada parameter
page_iddihttps://repo.org.github.io/__/auth. -
Ditemukan bahwa parsing
page_idmengabaikan karakter whitespace dan nilai ini langsung ditetapkan ke headerSet-Cookie. -
Parsing bisa dirusak dengan injeksi CRLF tradisional, tetapi tidak ada dampak lain.
-
Karena header
Location:ditempel setelah headerSet-Cookie, meskipun itu redirect 302, header Location diabaikan dan body dirender.
Serangan
-
Dari kode GitHub Enterprise, diketahui bahwa server private page diimplementasikan dengan openresty nginx.
-
Dengan menambahkan null byte, XSS berhasil dilakukan. Null byte ini harus berada di awal body, jadi serangan injeksi header tidak bisa digunakan.
-
Dari sini, menjadi mungkin menjalankan kode JavaScript arbitrer di domain private page.
-
Sekarang yang tersisa adalah mencari cara untuk melewati nonce.
Melewati nonce
-
Dari hasil observasi, ditemukan bahwa sibling private pages dalam organisasi yang sama bisa saling menetapkan cookie.
-
Cookie yang ditetapkan di
private-org.github.iodikirim keprivate-page.private-org.github.io. -
Jika perlindungan prefiks
__Host-bisa dilewati, nonce dapat dengan mudah dilewati. -
Tidak semua browser mendukung ini, dan IE tidak mendukung prefiks
__Host-. -
Namun saat mencari cara yang lebih baik, muncul ide yang menarik.
-
Setelah memeriksa bagaimana cookie menangani huruf besar-kecil, ditemukan bahwa
__HOSTdan__Hostdiperlakukan berbeda, dan GitHub private pages mengabaikan huruf besar saat mem-parsing cookie. -
Menjadi mungkin menentukan nonce lewat JavaScript.
-
Ia pun menerima bonus $5.000.
Cache poisoning
-
Respons endpoint
/__/auth?di-cache berdasarkan nilai integer daripage_idyang dipalsukan. -
Dengan ini, jika cache poisoning berhasil lewat payload XSS, maka pengguna yang tidak berinteraksi pun akan terdampak.
-
Jika penyerang menyerang
unprivileged.org.github.iountuk meracuni autentikasi, payload XSS akan di-cache. -
Karena cookie dibagikan pada domain induk
org.github.io, penyerang juga bisa menyerangprivileged.org.github.io.
Private page publik
-
Untuk mendapatkan bonus $15.000, serangan ini harus bisa dilakukan oleh pengguna yang bukan anggota organisasi.
-
Serangan ini dimungkinkan oleh salah konfigurasi yang menetapkan private page pada repositori public.
- Maksudnya adalah membuat pages dari repo private lalu mengubah repositorinya menjadi public.
-
Private page dengan salah konfigurasi ini membuat semua pengguna melewati alur autentikasi dan memberi pengguna di luar organisasi hak baca.
Belum ada komentar.