惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

Comments for 风雪之隅

Yac 2.4.0发布 - 小值读取性能提升64% 用Yac给WordPress做缓存:比Memcached快19% Laruence Laruence Laruence Laruence Laruence Laruence 深入理解PHP7内核之OBJECT - 风雪之隅 关于调用约定(cdecl、fastcall、stcall、thiscall) 的一点知识 - 风雪之隅 PHP 8新特性之Attributes(注解) - 风雪之隅 博客迁移到腾讯云 - 风雪之隅 提升PHP性能之改变Zend引擎分发方式 - 风雪之隅 如何调试PHP的Core之获取基本信息 - 风雪之隅 请手动释放你的资源(Please release resources manually) - 风雪之隅 在Qcon 2015 北京上的演讲PPT - PHP7 Linux上配置Nginx+PHP5(FastCGI) - 风雪之隅 深入理解Javascript之this关键字 - 风雪之隅 Yar-2.1 新功能介绍 - 风雪之隅 Yaf and Phalcon, which is faster? PHP CLI模式下的多进程应用 - 风雪之隅 PHP5.2.*防止Hash冲突拒绝服务攻击的Patch - 风雪之隅 PHP中的Hash算法 - 风雪之隅 PHP单引号和双引号的区别 - 风雪之隅 深入理解PHP之数组(遍历顺序) - 风雪之隅 深入理解PHP原理之变量分离/引用(Variables Separation) - 风雪之隅 PHP Taint - 一个用来检测XSS/SQL/Shell注入漏洞的扩展 - 风雪之隅 BTwitter(Twitter In Bash) - 风雪之隅 automake,autoconf使用详解 - 风雪之隅 HTTPOXY漏洞说明 - 风雪之隅
在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 - 风雪之隅
Prestige par · 2023-07-13 · via Comments for 风雪之隅

最近在做一个PHP的安全模块,其中要在Module的函数中获取用户的Cookie,从而生成签名;今天找遍Baidu/Google,一点相关资料都 没有,不得已,只好给yahoo PHP dev mail list发了求救信。后来,偶然在Google上看到了一个变量 http_globals ,眼前一亮,虽然没有详细资料,但经过一顿试,N次Segmentation fault以后,终于成功!
接下来,我结合实例和大家分享:
假设要获取$_GET['c'];
首先,先介绍下http_globals;
1.http_globals,定义在php_globals.h中;
zval * http_globals[6];
其中的索引为:

#define TRACK_VARS_POST           0
#define TRACK_VARS_GET            1
#define TRACK_VARS_COOKIE         2
#define TRACK_VARS_SERVER         3
#define TRACK_VARS_ENV            4
#define TRACK_VARS_FILES          5
#define TRACK_VARS_REQUEST        6

就是不知道为什么,http_globals定义为6个元素,但是索引却定义了7个,猜测可能是因为REQUREST本来也就是GET和POST的 merge,并且存取都是通过宏来进行,所以可能最后宏中会处理TRACK_VARS_REQUEST为GET和POST的merge。
2.获取方法:

zval * arr;
zval ** temp;
char * key = "c", r_str;
int len = 2, r_len,duplicate=1;
arr = PG(http_globals)[TRACK_VARS_GET];
zend_hash_find(HASH_OF(arr), key, len, (void **)&temp);
r_str = Z_STRVAL_PP(temp);
r_len = Z_STRLEN_PP(temp);
ZVAL_STRINGL(return_value, r_str, r_len, duplicate)

3.分析
其中PG是一个宏,定义在php_globals.h中:
# define PG(v) TSRMG(core_globals_id, php_core_globals *, v)
TSRMG也是一个宏,定义在TSRM.h中:
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
TSRM_UNSHUFFLE_RSRC_ID也是一个宏,也定义在TSRM.h中:
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
那么PG(http_globals)展开后就会成为:

PG(http_globals) =>;
TSRM(core_globals_id, php_core_globals *, http_globals);
=>;
((php_core_globals *)(*((void ***))tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(core_globals_id)])->http_globals);
=>;
((php_core_globals *)(*((void ***))tsrm_ls))[(core_globals_id-1)])->http_globals);

HASH_OF也是个宏,定义在zend_API.h中:

         #define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p) TSRMLS_CC) : NULL)))

4.获取
根据测试的结果,可以认定PG(http_globals)[TRACK_VARS_GET]是一个hash table;
5.问题
有个问题就是,Zend中好像字符的len要计算结束符'\0'的,就是因为我定义len=1,导致crash N次。。郁闷。
6.再补充点关于return_value:

1. php.h:        #define PHP_FUNCTION                       ZEND_FUNCTION
2. zend_API.h: #define ZEND_FUNCTION(name)        ZEND_NAMED_FUNCTION(ZEND_FN(name))
3. zend_API.h: #define ZEND_FN(name)      zif_##name
4. zend_API.h: #define ZEND_NAMED_FUNCTION(name)       void name(INTERNAL_FUNCTION_PARAMETERS)
5. zend.h: #define INTERNAL_FUNCTION_PARAMETERS   int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC</blockquote>

这样一来,我们的函数PHP_FUNCTION(getGetParam)就会变成:
void zif_getGetParam( int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);
可见,return_value是默认就定义的,是返回值的载体。
呵呵,就写这么多,有时间再补充。
7.原代码:

PHP_FUNCTION(confirm_getCookie_compiled){
	char *arg = NULL;
	int arg_len, len;
	ulong ikey;
	char * strg, * skey;
	zval * arr;
	zval **data;
	HashTable* h;
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
		WRONG_PARAM_COUNT;
	}
	arr = PG(http_globals)[TRACK_VARS_GET];
	h  = HASH_OF(arr);
	array_init(return_value);
	zend_hash_internal_pointer_reset(h);
	int count = zend_hash_num_elements(h);
	for(int i=0 ; i&lt;count; i++){
		zend_hash_get_current_data(h, (void**)&data);
		zend_hash_get_current_key(h, &skey, &ikey, 0);
		add_assoc_stringl(return_value, skey, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1);
		zend_hash_move_forward(h);
	}
	return;
	//      RETURN_STRINGL(strg, len, 0);
	//ZVAL_STRINGL(return_value, strg, len, 0);
}