摘要:的預(yù)定義變量和,這些變量的生成過程。主要是由于之前看到一篇文章通過構(gòu)造沖突實(shí)現(xiàn)各種語(yǔ)言的拒絕服務(wù)攻擊。其中看似是相當(dāng)于注冊(cè)聲明對(duì)應(yīng)的預(yù)定義變量名,而才是真正的將值寫入到和變量中的操作。提交最大變量數(shù)限制,中做限制,參考資料
PHP的預(yù)定義變量:$_SERVER,$_POST,$_GET,$_COOKIE,$_ENV,$_FILES和$_REQUEST,這些變量的生成過程。
主要是由于之前看到一篇文章通過構(gòu)造Hash沖突實(shí)現(xiàn)各種語(yǔ)言的拒絕服務(wù)攻擊。
看完之后思考這些變量是什么時(shí)候生成的,是由web服務(wù)器生成的還是PHP生成的?
客戶端將請(qǐng)求發(fā)送到web服務(wù)器,web服務(wù)器在收到請(qǐng)求后,將請(qǐng)求攜帶的參數(shù)寫入到緩沖區(qū)stdin,然后php寫入預(yù)定義變量的時(shí)候,會(huì)從stdin中取出這些參數(shù)然后裝入到對(duì)應(yīng)的預(yù)定義變量中$_GET,$_POST,$_REQUEST中
自己跟蹤代碼看整個(gè)php的流程1>執(zhí)行main/mian.c中的php_module_startup函數(shù)
2>執(zhí)行php_startup_auto_globals函數(shù),該函數(shù)在php_variables.c中定義的
//php_variable.c void php_startup_auto_globals(void) { zend_register_auto_global(zend_string_init("_GET", sizeof("_GET")-1, 1), 0, php_auto_globals_create_get); zend_register_auto_global(zend_string_init("_POST", sizeof("_POST")-1, 1), 0, php_auto_globals_create_post); zend_register_auto_global(zend_string_init("_COOKIE", sizeof("_COOKIE")-1, 1), 0, php_auto_globals_create_cookie); zend_register_auto_global(zend_string_init("_SERVER", sizeof("_SERVER")-1, 1), PG(auto_globals_jit), php_auto_globals_create_server); zend_register_auto_global(zend_string_init("_ENV", sizeof("_ENV")-1, 1), PG(auto_globals_jit), php_auto_globals_create_env); zend_register_auto_global(zend_string_init("_REQUEST", sizeof("_REQUEST")-1, 1), PG(auto_globals_jit), php_auto_globals_create_request); zend_register_auto_global(zend_string_init("_FILES", sizeof("_FILES")-1, 1), 0, php_auto_globals_create_files); } //zend_compile.c,將各個(gè)預(yù)定義變量寫入 int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback){ zend_auto_global auto_global; int retval; auto_global.name = zend_new_interned_string(name); auto_global.auto_global_callback = auto_global_callback; auto_global.jit = jit; retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE; zend_string_release(name); return retval; } //zend_compile.c,將各個(gè)變量的key-value寫入到hashtable中 static zend_always_inline void *zend_hash_add_mem(HashTable *ht, zend_string *key, void *pData, size_t size){ zval tmp, *zv; ZVAL_PTR(&tmp, NULL); if ((zv = zend_hash_add(ht, key, &tmp))) { //這一步的$_REQUEST可能被攻擊 Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT); memcpy(Z_PTR_P(zv), pData, size); return Z_PTR_P(zv); } return NULL; }laruence的博客:
要知道PHP是怎么處理的,首先我們要了解,$_GET, $_POST, $_COOKIE等變量的構(gòu)造過程。
每個(gè)請(qǐng)求到來(lái)以后,apache處理到response階段的時(shí)候, 會(huì)將控制權(quán)交給PHP模塊, PHP模塊會(huì)在處理請(qǐng)求之前首先間接調(diào)用 php_request_startup函數(shù),在php_request_startup中:
#ifndef APACHE_HOOKS int php_request_startup(void) { int retval = SUCCESS; #ifdef HAVE_DTRACE DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method)); #endif /* HAVE_DTRACE */ #ifdef PHP_WIN32 # if defined(ZTS) _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); # endif PG(com_initialized) = 0; #endif #if PHP_SIGCHILD signal(SIGCHLD, sigchld_handler); #endif zend_try { PG(in_error_log) = 0; PG(during_request_startup) = 1; php_output_activate(); /* initialize global variables */ PG(modules_activated) = 0; PG(header_is_being_sent) = 0; PG(connection_status) = PHP_CONNECTION_NORMAL; PG(in_user_include) = 0; zend_activate(); sapi_activate(); #ifdef ZEND_SIGNALS zend_signal_activate(); #endif if (PG(max_input_time) == -1) { zend_set_timeout(EG(timeout_seconds), 1); } else { zend_set_timeout(PG(max_input_time), 1); } /* Disable realpath cache if an open_basedir is set */ if (PG(open_basedir) && *PG(open_basedir)) { CWDG(realpath_cache_size_limit) = 0; } if (PG(expose_php)) { sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1); } if (PG(output_handler) && PG(output_handler)[0]) { zval oh; ZVAL_STRING(&oh, PG(output_handler)); php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS); zval_ptr_dtor(&oh); } else if (PG(output_buffering)) { php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS); } else if (PG(implicit_flush)) { php_output_set_implicit_flush(1); } /* We turn this off in php_execute_script() */ /* PG(during_request_startup) = 0; */ php_hash_environment(); zend_activate_modules(); PG(modules_activated)=1; } zend_catch { retval = FAILURE; } zend_end_try(); SG(sapi_started) = 1; return retval; }
其中的zend_variables.c文件中php_hash_environment函數(shù):
PHPAPI int php_hash_environment(void) { memset(PG(http_globals), 0, sizeof(PG(http_globals))); zend_activate_auto_globals(); if (PG(register_argc_argv)) { php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); } return SUCCESS; } //回調(diào)zend_variables.c中的zend_activate_auto_globals函數(shù)將請(qǐng)求的value寫入到對(duì)應(yīng)的$_POST和$_GET預(yù)定義變量中 ZEND_API void zend_activate_auto_globals(void) /* {{{ */ { zend_auto_global *auto_global; ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) { if (auto_global->jit) { auto_global->armed = 1; } else if (auto_global->auto_global_callback) { //這里會(huì)回調(diào)php_auto_globals_create_post,php_auto_globals_create_get,php_auto_globals_create_request函數(shù)處理對(duì)應(yīng)的變量 auto_global->armed = auto_global->auto_global_callback(auto_global->name); } else { auto_global->armed = 0; } } ZEND_HASH_FOREACH_END(); }
拿其中一個(gè)$_REQUEST數(shù)據(jù)來(lái)看,php_variables.c文件中php_auto_globals_create_request函數(shù)對(duì)應(yīng)代碼:
static zend_bool php_auto_globals_create_post(zend_string *name) { if (PG(variables_order) && (strchr(PG(variables_order),"P") || strchr(PG(variables_order),"p")) && !SG(headers_sent) && SG(request_info).request_method && !strcasecmp(SG(request_info).request_method, "POST")) { //寫入數(shù)據(jù) sapi_module.treat_data(PARSE_POST, NULL, NULL); } else { zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); array_init(&PG(http_globals)[TRACK_VARS_POST]); } zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_POST]); Z_ADDREF(PG(http_globals)[TRACK_VARS_POST]); return 0; /* don"t rearm */ }
可以看到,離成功不遠(yuǎn)了,sapi_module.treat_data 也就是php_default_treat_data,
在php_default_treat_data中,對(duì)于變量,都調(diào)用php_register_variable_safe來(lái)注冊(cè)變量,
而php_register_variable_safe最終會(huì)調(diào)用php_register_variable_ex:
zend_variables.c文件中zend_register_auto_global和zend_activate_auto_globals之間的關(guān)系,應(yīng)該有先后順序的問題。
其中zend_register_auto_global看似是相當(dāng)于注冊(cè)聲明對(duì)應(yīng)的預(yù)定義變量名,而zend_activate_auto_globals才是真正的將值寫入到$_GET和$_POST變量中的操作。
提交最大變量數(shù)限制,php_varialbles.c中add_post_vars做限制,SAPI_POST_HANDLER_FUNC(php_std_post_handler)
參考資料:
http://www.laruence.com/2008/...
http://www.laruence.com/2008/...
http://www.php-internals.com/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/23225.html
摘要:注意和是不同的變量,處理它們的方式不同變量說(shuō)明默認(rèn)情況下包含了,和的數(shù)組。包含相同的信息,但它不是一個(gè)超全局變量。這些特殊的常量不區(qū)分大小寫,如下幾個(gè)的魔術(shù)常量名稱說(shuō)明文件中的當(dāng)前行號(hào)。 整理了下關(guān)于php的基礎(chǔ)知識(shí),參考了些資料,如下: 超全局變量 超全局變量 — 超全局變量是在全部作用域中始終可用的內(nèi)置變量: $GLOBALS $GLOBALS — 引用全局作用域中可用的全部變量 ...
摘要:和進(jìn)程的啟動(dòng)過程類似,啟動(dòng)過程有種進(jìn)程角色啟動(dòng)進(jìn)程進(jìn)程和進(jìn)程。直到請(qǐng)求到來(lái),將連接賦值給對(duì)象的字段。注當(dāng)進(jìn)程執(zhí)行完后會(huì)再次調(diào)用函數(shù),準(zhǔn)備監(jiān)聽新的請(qǐng)求。當(dāng)讀取到的時(shí),會(huì)調(diào)用函數(shù)對(duì)進(jìn)行解析,將中的以及存儲(chǔ)到結(jié)構(gòu)體中。 運(yùn)營(yíng)研發(fā)團(tuán)隊(duì) 季偉濱 一、前言 前幾天的工作中,需要通過curl做一次接口測(cè)試。讓我意外的是,通過$_POST竟然無(wú)法獲取到Content-Type是application...
摘要:最近計(jì)劃把手冊(cè),認(rèn)真的先過一遍。語(yǔ)言參考類型新認(rèn)知強(qiáng)制轉(zhuǎn)換類型用。后期靜態(tài)綁定從這里開始語(yǔ)言參考生成器新認(rèn)知生成器汗水的核心是關(guān)鍵字。語(yǔ)言參考預(yù)定義變量超全局變量前一個(gè)錯(cuò)誤信息原始數(shù)據(jù)以上 showImg(https://segmentfault.com/img/remote/1460000010147451); 最近計(jì)劃把 PHP手冊(cè),認(rèn)真的先過一遍。記錄一些以前不知道,不明確的知識(shí)...
摘要:,意為跨網(wǎng)站請(qǐng)求偽造,也有寫為。攻擊者偽造目標(biāo)用戶的請(qǐng)求,然后此請(qǐng)求發(fā)送到有漏洞的網(wǎng)站,網(wǎng)站執(zhí)行此請(qǐng)求后,引發(fā)跨站請(qǐng)求偽造攻擊。 CSRF(Cross Site Request Forgeries),意為跨網(wǎng)站請(qǐng)求偽造,也有寫為XSRF。攻擊者偽造目標(biāo)用戶的HTTP請(qǐng)求,然后此請(qǐng)求發(fā)送到有CSRF漏洞的網(wǎng)站,網(wǎng)站執(zhí)行此請(qǐng) 求后,引發(fā)跨站請(qǐng)求偽造攻擊。攻擊者利用隱蔽的HTTP連接,讓目標(biāo)...
摘要:這里創(chuàng)建的對(duì)象可以在進(jìn)程生命周期內(nèi)使用目的加載框架中的內(nèi)容定義應(yīng)用目錄加載基礎(chǔ)文件把接收的信息轉(zhuǎn)換為可識(shí)別的對(duì)于超全局?jǐn)?shù)組不會(huì)釋放函數(shù)輸出打印 Swoole完美支持ThinkPHP5 1、首先要開啟http的server 可以在thinkphp的目錄下創(chuàng)建一個(gè)server目錄,里面創(chuàng)建一個(gè)HTTPServer的php 2、需要在WorkerStart回調(diào)事件做兩件事 定義應(yīng)用目錄:d...
閱讀 953·2021-09-09 09:32
閱讀 2935·2021-09-02 10:20
閱讀 2766·2021-07-23 11:24
閱讀 856·2019-08-30 15:54
閱讀 3671·2019-08-30 15:54
閱讀 1376·2019-08-30 11:02
閱讀 2880·2019-08-26 17:40
閱讀 1159·2019-08-26 13:55