Back to IF4053 – Software Security

Identified Vulnerabilities in SimpleWebServer and Secure Coding Countermeasures

Questions/Cues

  • Mengapa request HTTP tidak terformat menyebabkan DoS?
  • Bagaimana path traversal mengekspos file sistem?
  • Kapan pengecualian harus ditangani secara eksplisit?
  • Apa peran validasi pathname dalam mencegah eksploitasi?
  • Bagaimana cara membatasi ukuran request untuk keamanan?

Reference Points

  • Lecture_SimpleWebServer.pptx (Slides 18‑33)
  • SecureCoding_Guidelines.pdf (Pages 45‑58)
  • OWASP_Top10_2021.pdf (Pages 12‑14)

Denial‑of‑Service melalui Request Mal‑Formed

Pada implementasi SimpleWebServer, metode processRequest() membaca satu baris dari socket menggunakan BufferedReader.readLine(). Jika klien mengirimkan karakter carriage‑return (\r) atau baris kosong tanpa format GET /path HTTP/1.0, pemanggilan StringTokenizer(request, " ") menghasilkan exception karena tidak ada token yang dapat dipisahkan. Karena kode tidak memeriksa nilai null atau menangkap NoSuchElementException, server crash dan berhenti melayani semua klien selanjutnya. Contoh analogi: seperti pintu masuk gedung yang menutup otomatis ketika seseorang menekan bel tetapi tidak ada orang di dalam, sehingga semua orang terhalang masuk.

Dampak DoS ini bersifat total: satu permintaan tidak valid dapat menonaktifkan layanan hingga proses server di‑restart secara manual. Pada skala produksi, serangan semacam ini dapat diotomatisasi dengan skrip sederhana yang mengirimkan ribuan baris kosong, menghasilkan penurunan layanan yang signifikan.

Penyebab utama adalah kurangnya validasi pada tahap awal pembacaan request serta ketidakhadiran penanganan pengecualian yang memadai. Tanpa mekanisme timeout atau batasan panjang request, server menunggu selamanya pada input yang tidak lengkap, memperparah potensi resource exhaustion.

Path Traversal (Directory Traversal) dan Akses File Di Luar Root

Metode serveFile() menghilangkan slash pertama pada pathname dan kemudian langsung membuka file dengan new FileReader(pathname). Tidak ada pemeriksaan apakah pathname mengandung segmen ../ atau karakter khusus lain yang dapat menavigasi ke direktori di atas root. Seorang penyerang dapat mengirimkan request seperti GET /../../../../etc/passwd HTTP/1.0, yang setelah pemotongan slash pertama menjadi ../../../../etc/passwd. Karena Java tidak membatasi akses file secara implisit, server akan membaca file sistem operasi dan mengirimkan isinya ke klien.

Contoh dunia nyata: membayangkan sebuah lemari dengan kunci hanya pada pintu depan; tanpa pengunci internal, siapa pun dapat membuka laci di belakang dan mengambil barang yang tidak seharusnya. Pada server, pathname berperan sebagai “kunci” yang seharusnya memvalidasi bahwa hanya file dalam direktori htdocs yang dapat diakses.

Akibatnya, selain mengungkap isi file sensitif, penyerang dapat memanfaatkan file konfigurasi atau skrip yang dapat dieksekusi, membuka peluang escalation lebih lanjut. Karena contoh di slide menyebutkan “Confidentiality Breach”, kami tidak menjelaskan konsep tersebut, melainkan fokus pada mekanisme teknis yang memungkinkan kebocoran.

Penanganan Pengecualian dan Praktik Defensive Programming

Pada kode asli, hanya ada satu blok try‑catch di dalam serveFile() untuk menangani FileNotFoundException. Semua pengecualian lain, termasuk NullPointerException, StringIndexOutOfBoundsException, atau IOException yang muncul selama pembacaan request, tidak ditangani. Akibatnya, server dapat terminate secara tak terduga.

Solusi yang ditunjukkan pada slide 31 menambahkan blok try‑catch di sekitar parsing request, mengirimkan respons 400 Bad Request dan menutup koneksi secara bersih. Praktik ini merupakan contoh defensive programming: mengasumsikan bahwa semua input dapat berbahaya dan menyiapkan jalur keluar yang terkontrol. Selain itu, menutup OutputStreamWriter dalam blok finally atau menggunakan try‑with‑resources memastikan sumber daya selalu dibebaskan, menghindari kebocoran descriptor.

Contoh langkah‑langkah:

  1. Membungkus seluruh logika processRequest() dalam try (BufferedReader br = …; OutputStreamWriter osw = …) { … }.
  2. Memvalidasi bahwa request tidak null sebelum tokenisasi.
  3. Menangkap NoSuchElementException bila token tidak lengkap, lalu mengirimkan 400.

Countermeasures Umum untuk Secure Coding

Berdasarkan temuan di atas, beberapa langkah mitigasi dapat diimplementasikan secara bertahap:

  1. Validasi Input – Terapkan whitelist untuk karakter yang diizinkan dalam pathname (mis. hanya alfanumerik, -, _, dan .). Gunakan java.nio.file.Path.normalize() untuk menghilangkan segmen .. sebelum membuka file.
  2. Batas Ukuran Request – Tetapkan batas maksimum panjang baris (mis. 1024 byte). Jika br.readLine() mengembalikan string lebih panjang, tutup koneksi dan log kejadian.
  3. Exception Handling Terpusat – Buat kelas utilitas HttpExceptionHandler yang mengubah semua pengecualian menjadi respons HTTP yang tepat (400, 404, 500) dan menutup aliran secara otomatis.
  4. Least Privilege – Jalankan server dengan hak akses file terbatas (mis. hanya direktori htdocs). Pada sistem Unix, gunakan chmod dan setuid untuk menurunkan hak istimewa proses Java.
  5. Logging dan Monitoring – Catat setiap request yang ditolak atau menghasilkan error, termasuk alamat IP sumber, untuk deteksi serangan berulang.

Implementasi langkah‑langkah ini tidak hanya menutup celah yang teridentifikasi, tetapi juga membangun fondasi yang kuat untuk menambah proteksi terhadap kerentanan lain yang mungkin muncul di masa depan.

Ringkasan

SimpleWebServer rentan terhadap Denial‑of‑Service karena tidak memvalidasi request HTTP yang tidak terformat, serta path traversal yang memungkinkan akses file di luar direktori web. Kekurangan penanganan pengecualian memperparah kedua masalah tersebut. Dengan menerapkan validasi input, batas ukuran request, penanganan pengecualian terpusat, serta menjalankan proses dengan least privilege, server dapat menjadi jauh lebih tahan terhadap eksploitasi. Praktik defensive programming dan logging yang konsisten menjadi kunci untuk deteksi dini dan mitigasi serangan lanjutan.