1 poin oleh GN⁺ 2023-07-04 | 1 komentar | Bagikan ke WhatsApp
  • Nginx, server web serbaguna dengan pangsa pasar dominan sejak 2004
  • Konfigurasi Nginx yang keliru dapat menyebabkan kerentanan keamanan dan kebocoran data
  • Memperkenalkan NavGix, alat otomatis untuk mendeteksi kerentanan pada Nginx
  • Kerentanan ini dapat memungkinkan akses ke file dan direktori di luar cakupan yang dimaksud
  • Studi kasus terhadap Bitwarden dan HPC Toolkit milik Google menunjukkan tingkat keparahan kerentanan ini

1 komentar

 
GN⁺ 2023-07-04
Komentar Hacker News
  • Sebagai referensi, gixy (pemeriksa konfigurasi nginx) memang mendeteksi masalah ini: https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
    Dan NixOS secara otomatis menjalankan gixy pada konfigurasi yang dihasilkan olehnya, lalu menolak build sistem jika ada masalah

    • Jika web server memerlukan alat tambahan agar pengguna bisa menghindari jebakan seperti ini, mungkin default-nya perlu ditinjau ulang
    • Saya belum tahu soal gixy, lalu mencobanya di home server dan ternyata menemukan satu kerentanan. Saya memakai $uri pada redirect 301
    • Saya pernah mencoba Nix, dan sejauh ini kelihatannya cukup bagus
      Tapi saya penasaran apakah ada pencari opsi yang lebih baik. Saya kurang suka harus mencari di seluruh ribuan opsi; saya ingin melihat hanya paket seperti ssh dan opsi yang sesuai dengannya, tapi terlalu banyak hasil yang tidak relevan ikut muncul
    • NixOS sudah tidak lagi menjalankan Gixy. Lihat https://github.com/NixOS/nixpkgs/pull/209075
  • Mungkin ini pertanyaan bodoh, tapi adakah alasan bagus nginx harus mengizinkan naik ke direktori induk dengan .. di path URL? Ini cuma terlihat seperti perilaku yang menunggu masalah
    Edit: Saya agak bingung tentang apa yang sebenarnya terjadi pada kerentanan aslinya. Sepertinya http://localhost/foo../secretfile.txt ditafsirkan seperti /var/www/foo/../secretfile.txt, tetapi pada server yang tidak rentan, kenapa http://localhost/foo/../secretfile.txt tidak ditafsirkan dengan cara yang sama? Saya tidak paham kenapa .. di dalam path hanya bekerja pada kondisi tertentu

    • Ini masalah yang sudah sangat lama dikenal di nginx, dan merupakan vektor serangan yang umum di CTF: https://book.hacktricks.xyz/network-services-pentesting/pent...
    • Masalahnya adalah URL bukanlah path yang sebenarnya. URL adalah alamat abstrak untuk suatu resource, yang bisa berupa direktori, file, executable, stream, dan lain-lain
      Dalam kasus ini, sebagian URL ditafsirkan sebagai direktori oleh nginx (http://localhost/foo) karena cara pemetaannya ke filesystem lokal di konfigurasi. Karena itu tampak menunjuk ke direktori, saat nginx membangun path lengkap untuk resource yang diminta, hasilnya menjadi "${mapped_path}/../secretfile.txt", dan meskipun itu tidak masuk akal dari sudut pandang URL, itu tetap valid di filesystem lokal. URL hanyalah string, bukan elemen path nyata, jadi posisi slash pada dasarnya tidak penting
      Ini adalah masalah yang sangat umum di web server secara umum sejak web pertama kali muncul. Pemetaan URL langsung ke path file populer karena berawal dari file server sederhana dengan indeks, tetapi segera berubah menjadi lingkungan campuran di mana URL bukan lagi path, melainkan pengenal aplikasi. Sebagian path dipakai untuk menunjuk aplikasi, dan sisanya dianggap parameter atau argumen
      Dan secara umum, menghormati . atau .. dari URL untuk objek filesystem biasanya tidak masuk akal. Aplikasi saya merapikan path request agar dipetakan dengan benar. Browser memperlakukan URL seperti path saat membuat tautan relatif, jadi penggunaan trailing / juga harus diperhatikan dengan hati-hati. Di sisi server, itu bisa menunjuk ke resource dengan makna yang berbeda
    • Dalam use case yang “normal”, ini tidak diperlukan. Rasanya lebih masuk akal kalau ada flag seperti allow_parent_traversal on; di location, dan itu menjadi perilaku yang harus diaktifkan secara eksplisit
    • Dugaan saya, NginX mungkin akan memeriksa "/foo/bar/.." lalu melarangnya atau menormalkannya menjadi "/foo/". Tetapi "/foo/bar.." adalah nama file yang sepenuhnya valid, jadi tampaknya lolos dari pemeriksaan semacam itu
    • Kapan .. bekerja dalam suatu path sepenuhnya bergantung pada izin file
      Dalam kasus ini, andaikan dari direktori indeks web (../index.html) ada izin untuk membaca file hingga ke direktori root (/), maka karena kita bisa naik sampai root, kita sekarang juga bisa melihat semua file yang world-readable dan dapat diakses dari root, misalnya /etc/passwd
      Bayangkan garpu bercabang tiga, dengan web server berada di cabang paling kanan. Jika bagian gagang tempat cabang-cabang itu bertemu adalah filesystem, maka ketika web server punya izin mengakses file dan direktori dari cabang kanan hingga ke gagang, setelah mencapai gagang itu ia bisa terus mengakses file di cabang-cabang lain juga
  • Saya tidak mengerti kenapa ini tidak dianggap sebagai kerentanan nginx. Perilaku ini benar-benar absurd, tampaknya tidak punya tujuan yang berguna, dan bisa langsung dieksploitasi

    • Itu dilakukan demi kecepatan. Substitusi teks sederhana jauh lebih cepat daripada memeriksa apakah path diakhiri slash dengan benar
      Perlu diingat juga bahwa Nginx menjadi populer berkat benchmark yang menunjukkan bahwa ia lebih “web scale” daripada Apache2
  • Ada pemikiran seperti ini: menambahkan opsi mirip Linux capability yang menghapus opsi .. dari parser nama file di kernel Linux.
    Di aplikasi web, sejak zaman masih memakai modem telepon, berbagai cara bypass untuk menyisipkan dua titik terus bermunculan. Seperti halnya kernel Linux menangani berbagai kategori bug ruang pengguna lainnya, mungkin sudah waktunya mencari cara untuk menutup masalah ini sekaligus

    • Ada RESOLVE_BENEATH di https://man7.org/linux/man-pages/man2/openat2.2.html
      FreeBSD punya fungsi ini di openat(2) biasa lewat O_RESOLVE_BENEATH
    • Kalau begitu, terlalu banyak hal yang akan rusak sehingga ini bukan sesuatu yang waras untuk dilakukan
      Cukup jalankan nginx sebagai pengguna terpisah dengan hak yang sangat terbatas, atau jalankan di Docker. Ditambah pembaruan rutin, biasanya 90% masalah keamanan sudah teratasi
    • /some/../path hampir 100% seharusnya dilarang. Tidak ada use case yang masuk akal selain “seseorang menulis kode yang jelek dilihat”
      ../some/path setidaknya kadang memang punya arti
      Meski begitu, sepertinya tidak akan seguna yang dibayangkan. Banyak aplikasi sudah lebih dulu mengurai .. sebelum menyerahkannya ke sistem operasi
    • Tidak banyak bedanya. Kode sering menormalkan path sebelum menyentuh API filesystem
    • Di sisi kernel ada sistem lain yang kita andalkan, yaitu sistem perizinan
      Jika Anda menyajikan file dari folder ke web, framework web harus memastikan tidak keluar dari folder root publik yang menjadi tanggung jawabnya. Jika membuatnya sendiri, Anda harus mempertimbangkan segala macam situasi termasuk hal seperti ini
  • “Google VRP Team memberi hadiah 500 dolar atas penemuan kerentanan ini. Mereka menilai dampaknya pada aplikasi tidak cukup serius untuk mendapat hadiah yang lebih besar”, jadi email akun GCP dan kunci privat yang terekspos cuma dihargai 500 dolar? Apa-apaan ini. Sangat Google sekali

  • Untungnya hal-hal yang bocor masih tetap terenkripsi. Bahkan perusahaan yang memang bergerak di bidang ini pun tidak kebal terhadap kebocoran, jadi sejujurnya ini skenario terbaik yang bisa diharapkan

  • Judulnya sudah cukup banyak diedit. Judul aslinya adalah Hunting for Nginx Alias Traversals in the wild
    Judul kiriman HN menonjolkan kerentanan Bitwarden, tetapi di dalam tulisannya kasus Google juga dibahas

    • Bagus, judulnya sudah dikembalikan. Judul kirimannya adalah “Leaking Bitwarden's Vault with a Nginx vulnerability”
  • Jika yang dibutuhkan hanya penyajian file statis yang aman secara konsisten dengan penggunaan resource seminimal mungkin, apa pilihan terbaik saat ini? Dulu saya pasti akan memilih Nginx, tetapi dari sudut pandang keamanan saya penasaran apakah alat yang lebih sempit tujuannya dan lebih sedikit kemungkinan konfigurasinya akan lebih baik

    • Saya memakai https://static-web-server.net/
      Lintas platform, ditulis dengan Rust, konfigurasinya sederhana, dan punya default yang aman. Ada juga image container yang diperkeras dan modul NixOS yang diperkeras
      Saya tidak merekomendasikan Caddy. Image Docker resminya secara default berjalan sebagai root [1], dan juga tidak menyediakan unit file systemd yang benar-benar tersandbox dengan baik [2]
      [1]: https://github.com/caddyserver/caddy-docker/issues/104
      [2]: https://github.com/caddyserver/dist/blob/master/init/caddy.s...
      Edit: merapikan ungkapan
    • Sedikit promosi, Caddy sangat bagus untuk ini. Menyediakan HTTPS otomatis, ditulis dalam Go sehingga tidak perlu khawatir soal bug keamanan memori, dan punya modul file_server yang solid
    • Saya sudah memakai Caddy selama beberapa tahun. Menyediakan sertifikat SSL otomatis, file serving, reverse proxy, dan konfigurasinya sangat mudah serta jelas. Karena berupa satu binary Go tunggal, “instalasinya” juga mudah dan file konfigurasinya cuma satu
    • Caddy cukup sederhana untuk dikonfigurasi agar menyajikan file statis
    • Merecat: https://github.com/troglobit/merecat/
  • Mungkin ini pertanyaan bodoh, tetapi mengapa Bitwarden sejak awal mengizinkan permintaan tanpa autentikasi ke /attachments? Bukankah kalau URL itu tetap memerlukan autentikasi, permintaannya akan gagal bahkan meski ada bug Nginx?

    • Ini exploit yang menargetkan konfigurasi web server, jadi kode autentikasi Bitwarden maupun kode Bitwarden sama sekali tidak dijalankan. Tidak aneh atau salah kalau proyek memakai autentikasi sendiri alih-alih Nginx atau modulnya
      Tetap saja, karena mereka mendistribusikan konfigurasi berbahaya lewat Docker, ini memang tanggung jawab Bitwarden. Sepertinya Bitwarden juga mengakui hal itu dan kemudian memperbaikinya
  • Maaf kalau ini pertanyaan bodoh. Bukankah dengan kepemilikan direktori dan file yang tepat, traversal seperti ini bisa dicegah?
    Jika nginx tidak berjalan sebagai root, bagaimana ia bisa membaca file lain selain file yang secara eksplisit diberikan kepada pengguna nginx?

    • Tentu saja bisa dicegah. Jalankan aplikasi sebagai satu pengguna, nginx sebagai pengguna lain, terapkan go-rwx pada semua file aplikasi, lalu setel grup file “static” ke www-data dan berikan hanya g+r, maka web server tidak akan bisa mengakses file aplikasi
      Ini benar-benar dasar hosting aplikasi 101, dan orang-orang sudah melakukannya 20 tahun lalu
    • Ah, betapa hebatnya umask 022. Secara pribadi, saya selalu menyarankan agar pengguna lain tidak bisa membaca file. Jika semua file terlalu sulit, setidaknya lakukan itu untuk direktori penting seperti yang ada di bawah /home
      Mungkin perlu sedikit mengutak-atik keanggotaan grup, tapi itu sangat sepadan
    • Saya tidak tahu soal orang lain, tapi sekarang saya tidak benar-benar memasang nginx dengan benar untuk penggunaan pribadi. Saya cuma menjalankan image Docker. Dan saya sebenarnya tidak memeriksa apakah itu berjalan sebagai root atau tidak
      Mungkin saya benar-benar sedang membuat kekacauan besar. Aduh
    • Umask yang umum adalah 022, jadi dalam kebanyakan kasus worker nginx bisa membaca tetapi tidak bisa menulis. Tidak perlu secara eksplisit ditetapkan ke pengguna seperti www-data. Jika aplikasi menghasilkan data sensitif, tentu lebih baik memakai umask 077
    • Benar
      Sayangnya nginx dan web server lain biasanya memang perlu berjalan sebagai root pada aplikasi web umum. Karena mereka harus listen di port 80 atau 443. Port di bawah 1024 hanya bisa dibuka oleh root
      Penjelasan lebih lanjut ada di sini: https://unix.stackexchange.com/questions/134301/why-does-ngi...