Disable Functions ================================ 机制实现 --------------------------------- PHPä¸Disable Function的实现是在php-src/Zend/Zend-API.cä¸ã€‚PHP在å¯åŠ¨æ—¶ï¼Œè¯»å–é…置文件ä¸ç¦æ¢çš„函数,é€ä¸€æ ¹æ®ç¦æ¢çš„函数å调用 ``zend_disable_function`` æ¥å®žçŽ°ç¦æ¢çš„æ•ˆæžœã€‚ è¿™ä¸ªå‡½æ•°æ ¹æ®å‡½æ•°ååœ¨å†…ç½®å‡½æ•°åˆ—è¡¨ä¸æ‰¾åˆ°å¯¹åº”çš„ä½ç½®å¹¶ä¿®æ”¹æŽ‰ï¼Œå½“å‰ç‰ˆæœ¬çš„代ç 如下: .. code-block:: cpp ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */ { zend_internal_function *func; if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) { zend_free_internal_arg_info(func); func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_RETURN_TYPE); func->num_args = 0; func->arg_info = NULL; func->handler = ZEND_FN(display_disabled_function); return SUCCESS; } return FAILURE; } 和函数的实现方å¼ç±»ä¼¼ï¼Œdisable classesä¹Ÿæ˜¯è¿™æ ·å®žçŽ°çš„ .. code-block:: cpp ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {{{ */ { zend_class_entry *disabled_class; zend_string *key; key = zend_string_alloc(class_name_length, 0); zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length); disabled_class = zend_hash_find_ptr(CG(class_table), key); zend_string_release_ex(key, 0); if (!disabled_class) { return FAILURE; } INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new); disabled_class->create_object = display_disabled_class; zend_hash_clean(&disabled_class->function_table); return SUCCESS; } å› ä¸ºè¿™ä¸ªå®žçŽ°æœºåˆ¶çš„åŽŸå› ï¼Œåœ¨PHPå¯åЍåŽé€šè¿‡ ``ini_set`` æ¥ä¿®æ”¹ ``disable_functions`` 或 ``disable_classes`` æ˜¯æ— æ•ˆçš„ã€‚ Bypass --------------------------------- - LD_PRELOAD绕过 - https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD - ``mail()`` + ``putenv`` - PHP OPcache - Mail函数 - imap_open - https://www.cvedetails.com/cve/cve-2018-19518