Lecture
This does not mean that all dangerous functions must urgently be banned. Nor does it mean that banning them will definitely protect you from every PHP shell. Most of these functions can be used perfectly safely in your application, framework or libraries. Each application should be approached individually. Security is the process of building a deeply layered defense, and disabling dangerous functions is just one possible line of that defense.
A list of such functions can serve as a helper in searching for suspicious files. A PHP shell can be hidden very cleverly — an excellent example of obfuscation is the article on habr

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";
It would be a good idea to disable some dangerous functions for PHP-fpm (or another SAPI). Leave the ability to run them only through PHP-cli. Monitor files for the appearance of other functions. The third group should be treated more carefully, and unsanitized or insufficiently validated strings should never be allowed into their arguments.
exec
expect_popen
passthru
system
shell_exec
popen
proc_open
pcntl_exec
These functions should be disabled first. If you need them in PHP-fpm, you are doing something wrong. These functions make it possible to escape the environment specified in open_basedir. Disabling only some of the functions will not be enough. For example, WSO, a shell loved by many, goes through the functions looking for ways to execute code.
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;
}
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
These should be disabled too. For example, proc_open is found in WSO. Besides, such functions have no place in a PHP-fpm environment. Daemons should be started through PHP-cli.
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 reveal information about your system and can significantly ease an attack on other software. They can also become a source of leaks of confidential data; for example, symfony recommends storing database connections in ENV. It is therefore advisable to forbid these functions, except for those used in your application.
eval
assert
preg_replace
create_function
include
include_once
require
require_once
You should check for their presence in uploaded files and regularly audit the files you already have. Besides eval, there are other ways to execute PHP code. For example, you can include a specially crafted JPG file. However, most frameworks and applications use these functions, so they cannot be disabled. It is therefore important to be extremely careful with them when using them. A shell can consist of just one line:
include("data:text/plain;base64,$_GET[code]");
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. Use them carefully and do not let raw data reach the function arguments. After all, they can also serve to disguise a shell. An example of the simplest shell using these functions looks like this:
print_r(call_user_func_array($_POST['functie'], array($_POST['argv'])));
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 disguise already known PHP shells from antivirus software and from prying eyes. Check uploaded files for their presence and regularly audit the existing files. An example of hiding a shell:

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 upload files or to disclose information about the system, so use them with caution. Many PHP shells can download third-party files over ftp. A simple PHP shell for uploading an arbitrary file looks like this:
copy($_GET['s'], $_GET['d']);
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
These functions also require caution, and some of them are better forbidden. For example, mail can be used by an infected site to send spam. If your application does not need these functions, disable them. The following construction does not look frightening, but it is one of the smallest PHP shells:
@extract($_REQUEST); @die ($ctime($atime));
Disabling unsafe PHP functions is one way to reduce risks when resources are limited. If people with "specialized knowledge" take an interest in your project, it will most likely fall.
Comments