Apa inti CVE-2022-1058 dan versi Gitea mana yang terdampak serta yang menambalnya?
Apa akar penyebab open redirect ini (parser differential)?
Bagaimana cara menemukannya secara manual, dengan SAST, dan dengan DAST?
Mengapa open redirect memperkuat serangan phishing?
Bagaimana Gitea memperbaikinya dan apa pelajarannya?
Reference Points
IF4053 Keamanan Perangkat Lunak (W12 — CVE-2022-1058 Open Redirect Walkthrough)
IF4053 Keamanan Perangkat Lunak (W12 — bagian “Bypass Variants & How It Was Fixed”)
CVE at a Glance
CVE-2022-1058 adalah kerentanan Open Redirect (CWE-601) pada Gitea—slide menargetkan Gitea 1.16.4, dengan rentang affected Gitea < 1.16.5 dan patched pada Gitea 1.16.5. Severity-nya CVSS 3.1 = 6.1 (Medium). Vektor serangannya adalah cookie/parameter redirect_to pada /user/login. Kerentanan ini tidak membutuhkan auth—dieksploitasi selama alur login. Sumber resmi: nvd.nist.gov/vuln/detail/CVE-2022-1058. Catatan etis: hanya untuk edukasi—uji hanya pada container Docker milik sendiri.
Akar Penyebab — Dua Parser, Satu Ketidaksepakatan
Validator Gitea memakai url.Parse("//evil.com") yang mengembalikan Scheme dan Host kosong, sehingga validator menyimpulkan “tanpa scheme, tanpa host = path relatif yang aman”. Namun browser menafsirkan Location: //evil.com sebagai URL protocol-relative dan menavigasi ke http://evil.com. Inilah parser differential bug: input yang sama diurai berbeda oleh dua kode—validator Go vs parser browser. Bug semacam ini muncul di mana pun input diurai dua kali oleh kode berbeda.
// modules/context/context.go (v1.16.4)func (ctx *Context) RedirectToFirst(location ...string) { for _, loc := range location { u, err := url.Parse(loc) if err != nil || ((u.Scheme != "" || u.Host != "") && ...) { continue } ctx.Redirect(loc) // ← "//evil.com" lolos }}
Penemuan Manual dan Varian Bypass
Jalankan versi rentan: docker run -d --name gitea -p 3000:3000 -p 222:22 gitea/gitea:1.16.4 (1.16.4 ada di Docker Hub gitea/gitea, bukan docker.gitea.com), selesaikan setup, buat admin dan user uji. PoC kanonik (inject cookie): tangkap POST /user/login di HTTP History, kirim ke Repeater (Burp) / Manual Editor (ZAP), tambahkan ke header Cookie: redirect_to=//example.com (jangan ganti cookie yang ada), kirim, lalu inspeksi header RESPONSE—munculnya Location: //example.com menandakan bug menyala. Bila token CSRF kedaluwarsa, tangkap ulang request segar. Varian bypass (tiap payload menguji keanehan parser): //example.com (protocol-relative, kanonik) → External ✓; /\example.com (normalisasi \→/ browser) → External ✓; ///example.com (multi-slash, dianggap path) → Internal ✗; https://example.com (URL absolut) → Blocked ✗; //[email protected] (userinfo confusion) → Depends; //ex%E3%80%82com (IDN homograph, titik CJK) → browser quirk. Bug butuh dua syarat: server meloloskan string DAN browser menafsirkannya sebagai eksternal.
flowchart TD
A["Penyerang kirim tautan login<br/>+ redirect_to=//evil.com"] --> B["Korban login ke Gitea sah"]
B --> C["Validator Go: //evil.com = path relatif (aman)"]
C --> D["Response Location: //evil.com"]
D --> E["Browser: navigasi ke evil.com"]
Penemuan dengan SAST
SAST dapat menandai pola redirect tidak aman, tetapi eksploitasi sebenarnya membutuhkan pemahaman perilaku browser—yang tak dapat dinalar analisis statis. Rule Semgrep kustom menggunakan pattern-either untuk $CTX.Redirect($USER_INPUT) dan http.Redirect($W, $R, $USER_INPUT, ...) (severity WARNING, Go), menghasilkan kandidat untuk review manusia—selalu konfirmasi dengan pengujian manual. SAST menangkap: pemanggilan redirect dengan input terkontrol pengguna, validasi yang hilang sebelum redirect, dan penggunaan url.Parse tanpa pengecekan lanjutan. SAST melewatkan: interpretasi URL spesifik-browser, apakah validasi benar-benar memadai, kerentanan parser differential, dan varian bypass berbasis encoding. Analisis statis melihat kode, bukan browser nyata yang mengeksekusinya.
Penemuan dengan DAST
DAST adalah pasangan alami untuk open redirect—tembakkan payload, amati header Location. Setup ZAP Fuzzer: klik kanan POST /user/login → Attack → Fuzz, sorot nilai redirect_to di header Cookie → Add, tempel 30+ varian payload (Strings), tambahkan processor Encode → URL, mulai fuzzer, urutkan berdasarkan header Location. Padanan Burp: Intruder dengan serangan Sniper pada posisi yang sama. Active Scanner ZAP bahkan memiliki rule External Redirect bawaan (di Information Gathering). Yang mendeteksi: ZAP Active Scan (rule Ext. Redirect), Burp Pro scanner, fuzzing manual dengan daftar payload, dan Burp Collaborator (kasus blind). Yang tidak menemukan: ZAP baseline (pasif), Nikto, Nuclei (kecuali template CVE dimuat), serta crawler generik tanpa fuzzing. Open redirect terdeteksi hanya lewat pengujian aktif, bukan observasi pasif.
Coverage Matrix, Dampak, dan Mitigasi
Coverage Matrix: injeksi cookie manual di Repeater (✓, rendah), ZAP Fuzzer (✓, medium), Burp Intruder Sniper (✓, medium), ZAP Active Scanner (✓, rendah), Burp Pro scanner (✓, rendah), Semgrep rule kustom (✓ kandidat, medium), gosec (✗), Trivy image scan (✓ via versi, rendah)—CVE ini paling merata terdeteksi lintas SAST dan DAST di antara ketiga studi kasus. Dampak: open redirect memperkuat phishing karena URL bar menampilkan domain sah sebelum pengalihan ke situs jahat. Mitigasi (Gitea 1.16.5): tambahkan pemeriksaan string mentah SEBELUM url.Parse—menolak lebih awal URL yang diawali // atau /\ (if len(loc) > 1 && loc[0] == '/' && (loc[1] == '/' || loc[1] == '\\') { continue }). Pendekatan ini melewati parser sepenuhnya. Pelajaran: validasi string mentah, bukan objek hasil parse, dan kadang lima baris (termasuk komentar) sudah cukup—patch terkecil terkadang yang paling tepat.
Summary
CVE-2022-1058 adalah open redirect (CWE-601) pada Gitea < 1.16.5 (slide menyorot 1.16.4; ditambal di 1.16.5, CVSS 6.1 Medium) via cookie/parameter redirect_to pada /user/login, tanpa auth dan dipicu selama alur login. Akar penyebabnya parser differential: validator Go menganggap //evil.com sebagai path relatif aman, sementara browser menavigasinya sebagai http://evil.com. Penemuan manual dengan menyisipkan redirect_to=//example.com di Repeater dan menguji varian bypass (//, /\, userinfo, IDN); SAST menandai pola Redirect($USER_INPUT) sebagai kandidat; DAST sangat efektif lewat ZAP Fuzzer/Active Scanner dan Burp Intruder/scanner. Perbaikannya memeriksa string mentah sebelum url.Parse (lima baris), menegaskan prinsip validasi string mentah, bukan objek hasil parse. Open redirect berbahaya karena memperkuat phishing.
Additional Information
Lebih dalam — Anatomi URL Protocol-Relative (DI LUAR sumber)
URL yang diawali // adalah protocol-relative: browser mengisi skema (http/https) mengikuti halaman saat ini, lalu menafsirkan sisanya sebagai host. Jadi //evil.com menjadi https://evil.com. Validator yang hanya mengecek Scheme dan Host dari url.Parse tertipu karena Go menganggap //evil.com ambigu (relatif). Kelas bug ini—di mana standar parsing (RFC 3986 vs WHATWG URL browser) berbeda—adalah sumber umum kerentanan SSRF dan open redirect.
Lebih dalam — Mitigasi Open Redirect yang Robust (DI LUAR sumber)
Selain menolak prefix // dan /\, praktik kuat untuk redirect terkontrol pengguna meliputi: (1) allowlist tujuan yang sah (mis. hanya path internal yang dikenal), (2) hanya mengizinkan path relatif yang dipaksa diawali / tunggal lalu di-normalisasi, atau (3) memetakan input pengguna ke token/ID internal alih-alih URL mentah. Mengandalkan denylist payload (//, \, encoding) rapuh karena varian bypass terus bertambah—itulah sebabnya pemeriksaan struktural pada string mentah lebih andal.
Proyek Eksplorasi Mandiri
Jalankan Gitea 1.16.4 dan 1.16.5, uji seluruh varian payload dari tabel pada keduanya, dan dokumentasikan mana yang menghasilkan Location eksternal sebelum vs sesudah patch.
Susun daftar 30+ payload open redirect, jalankan ZAP Fuzzer/Burp Intruder terhadap redirect_to, lalu urutkan berdasarkan header Location untuk mengidentifikasi bypass.
Tulis rule Semgrep untuk mendeteksi ctx.Redirect/http.Redirect dengan input pengguna di basis kode Go pilihanmu, lalu validasi temuannya secara manual.
Bacaan Lanjutan
NVD — CVE-2022-1058 dan diff commit Gitea v1.16.4 ↔ v1.16.5.
OWASP — Unvalidated Redirects and Forwards Cheat Sheet dan CWE-601.
Riset URL parser confusion (mis. “A New Era of SSRF” / studi perbedaan parser URL) untuk memahami parser differential.