成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【PHP預(yù)定義變量】$_GET,$_POST,$_REQUEST生成

Aceyclee / 755人閱讀

摘要:的預(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

相關(guān)文章

  • php超全局變量,魔術(shù)常量,魔術(shù)方法

    摘要:注意和是不同的變量,處理它們的方式不同變量說(shuō)明默認(rèn)情況下包含了,和的數(shù)組。包含相同的信息,但它不是一個(gè)超全局變量。這些特殊的常量不區(qū)分大小寫,如下幾個(gè)的魔術(shù)常量名稱說(shuō)明文件中的當(dāng)前行號(hào)。 整理了下關(guān)于php的基礎(chǔ)知識(shí),參考了些資料,如下: 超全局變量 超全局變量 — 超全局變量是在全部作用域中始終可用的內(nèi)置變量: $GLOBALS $GLOBALS — 引用全局作用域中可用的全部變量 ...

    mj 評(píng)論0 收藏0
  • PHP7源碼分析】PHP中$_POST揭秘

    摘要:和進(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...

    sf190404 評(píng)論0 收藏0
  • PHP 手冊(cè)閱讀筆記 - 語(yǔ)言參考篇

    摘要:最近計(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í)...

    Developer 評(píng)論0 收藏0
  • CSRF攻擊是什么并且如何防止

    摘要:,意為跨網(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)...

    Flands 評(píng)論0 收藏0
  • Swoole完美支持ThinkPHP5

    摘要:這里創(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...

    XiNGRZ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<