FlawOpen

flawopen.com/Penyertaan file/PHP include()

Apakah PHP include() aman dengan input pengguna?

CWE-98: PHP Remote File InclusionHalaman referensi
Jawaban singkat

Tidak. include() mem-parsing file terpilih sebagai PHP, tetapi dampaknya bergantung pada file yang dapat dijangkau dan isinya. Cacat dapat membocorkan sumber melalui wrapper, menyertakan file lokal yang tidak dimaksud, atau menjalankan PHP yang dikendalikan penyerang hanya jika penyerang dapat mengendalikan konten bertag PHP dan aplikasi menyertakan file itu. Penyertaan URL jarak jauh juga bergantung pada konfigurasi PHP. Petakan kunci pilihan pengguna ke daftar izin tetap; jangan membangun jalur include dari data permintaan.

RENTAN
<?php
// User-controlled path: unintended local file
include $_GET['page'] . '.php';

// Example selector: ../../private/sample
// Impact depends on the resolved file and
// whether it contains PHP code to interpret.

// Remote URL inclusion requires the relevant
// URL wrapper and allow_url_include setting.

// Wrappers can change which resource is read;
// php://filter is a read filter, not a path
// containment check.
DIPERBAIKI
<?php
// Allowlist: input selects a KEY,
// never a path or wrapper.
$pages = [
    'home'    => __DIR__ . '/pages/home.php',
    'about'   => __DIR__ . '/pages/about.php',
    'contact' => __DIR__ . '/pages/contact.php',
];

$key = $_GET['page'] ?? 'home';

if (!is_string($key) || !array_key_exists($key, $pages)) {
    http_response_code(404);
    exit;
}

include $pages[$key];

Mengapa penyertaan lokal tidak otomatis menjalankan kode

Penyertaan lokal tidak otomatis menjalankan kode. PHP mem-parsing file yang disertakan: pernyataan dalam tag PHP valid berjalan dalam konteks penyerta, sedangkan byte lain dapat dikirim sebagai keluaran. Eksekusi memerlukan file terjangkau berisi PHP yang dikendalikan penyerang atau perilaku lain yang dapat dieksploitasi. Cacat unggah atau penulisan log dapat menjadi rantai serangan jika menaruh konten PHP terkendali ke file yang kemudian disertakan.

php://filter menerapkan filter saat membuka stream. Dalam alur baca atau penyertaan yang rentan, filter yang sesuai dapat mengungkap teks sumber tanpa menjalankannya; akses bergantung pada wrapper, izin, dan konfigurasi aplikasi.

Mengapa sanitasi jalur bukan perbaikannya

Menghapus ../, menambahkan ekstensi tetap, atau memberi awalan direktori tidak membuktikan bahwa sumber akhir diizinkan. Pengodean, jalur absolut, aturan platform, dan wrapper dapat mengubah interpretasi. Hapus kendali pengguna atas nama sumber: izinkan hanya kunci tetap yang ditentukan aplikasi.

Jika jalur harus diselesaikan, kanonisasikan dengan realpath() dan verifikasi batas direktori seperti pada panduan Path Traversal. Batasi hasil ke file yang disetujui dan perhitungkan symlink serta kondisi balapan antara pemeriksaan dan penggunaan. Daftar izin target tetap lebih aman.

Pertanyaan umum

Apakah allow_url_include=Off membuatnya aman?

Pengaturan ini menonaktifkan wrapper URL untuk include/require. PHP mendokumentasikannya nonaktif secara default dan deprecated sejak PHP 7.4. Ini mengurangi paparan penyertaan jarak jauh, tetapi tidak mencegah traversal lokal atau include lokal yang tidak aman. Biarkan nonaktif dan hilangkan kendali pengguna atas target.

Apakah teknik byte nol masih berlaku?

PHP 5.3.4 memperbaiki penghentian byte nol pada pemrosesan jalur. Jangan mengandalkan berakhirnya teknik lama ini; target include yang tidak tepercaya tetap berbahaya.

Bagaimana dengan require, include_once, dan readfile?

require dan varian _once juga menyertakan serta mem-parsing target; perilaku kegagalan dan pengulangan berbeda, tetapi target tak tepercaya tetap tidak aman. readfile() dan file_get_contents() mengembalikan data tanpa mem-parsingnya sebagai PHP; jalur tak tepercaya dapat menyebabkan traversal atau kebocoran, bukan eksekusi melalui include.

Referensi

Lihat juga Path traversal (CWE-22): cara kerja dan cara mencegahnya di setiap bahasa — flawopen.com Perbaikan Path Traversal Python os.path.join() Apa itu kerentanan Zip Slip? Node.js path.join() tidak mencegah Path Traversal