Saya tidak akan menggambarkan perubahan ini sebagai "kritis", tetapi masih memiliki implikasi keamanan. Saya tidak mengetahui apa pun yang telah berubah secara mendasar sejak saran itu menjadi relevan - perilaku PHP cenderung kuat ke arah kompatibilitas mundur, bahkan ketika itu memiliki implikasi keamanan. Bayangkan Anda memiliki server yang memungkinkan orang mengunggah file ke server, katakanlah di direktori bernama upload
. Sekarang, skrip unggahan Anda berhati-hati untuk hanya mengizinkan file dengan ekstensi tertentu (katakanlah hanya .png
) untuk memastikan tidak ada yang mengunggah file PHP berbahaya.
Sekarang, sebagai penyerang, saya akan mencoba menulis shell PHP ke dalam file, beri nama file evil.png
, dan mengunggahnya. Saat diunggah, saya akan mengunjungi http://example.com/upload/evil.png
, tetapi saya akan menemukan bahwa ini hanya mengunduh file untuk saya -- nginx tidak pernah mengirimkan permintaan ke php-fcgi untuk diproses sebagai php, karena nama file diakhiri dengan .png
.
Jika saya seorang penyerang yang mengetahui PATH_INFO
, selanjutnya saya akan mencoba http://example.com/upload/evil.png/index.php
. Jika server Anda dikonfigurasi demikian, ini akan mengakibatkan PHP dieksekusi (karena nginx melihat index.php
di akhir) dan PHP akan menelusuri jalur tersebut hingga menemukan komponen yang berupa file, bukan direktori (evil.png
) dan coba jalankan. Kemudian shell saya dieksekusi dan saya menang.
Meskipun demikian, ada cara yang lebih baik untuk menangani hal ini dengan membuat konfigurasi NGINX memisahkan jalur terlebih dahulu, sehingga PHP tidak menjalankan sistem file.
Dari postingan blog Neal Poole yang luar biasa tentang masalah ini:
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
Bahkan sekarang tampaknya berbahaya karena bagaimana PHP masih memproses skrip dari kejadian pertama file yang ditemukan. Jadi mengapa mereka mempertahankan default sebagai ;cgi.fix_pathinfo=1
lalu?
Karena CGI independen dari PHP dan memiliki standarnya sendiri. CGI (Common Gateway Interface) adalah antarmuka yang menginstruksikan server tentang cara mengkomunikasikan data dengan aplikasi, bagaimana informasi permintaan dan badan diteruskan, dari input ke output. Server Web dapat dikonfigurasi untuk menjalankan program sebagai CGI
, yang berarti mereka akan meneruskan data permintaan ke program tertentu. Dan begitulah cara NGinx meneruskan permintaan ke PHP.
Berbicara tentang Standar CGI , PHP-FPM
pengembang harus mematuhi standar CGI seperti yang dinyatakan dalam PHP-FPM
file ini ex :/etc/php/7.2/fpm/php.ini
:
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
;cgi.fix_pathinfo=1
Jadi saya kira teksnya Setting this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting of zero causes PHP to behave as before.
menjelaskan pilihan. Ini adalah PATH_INFO
Spesifikasi CGI.