对register_argc_argv的分析
简介
使用
cli模式下,不论是否开始register_argc_argv,都可以获取命令行或者说外部参数
web模式下,只有开启了register_argc_argv,才可以获取外部参数
未开启register_argc_argv时
开启register_argc_argv
可以看到,在处理argv时,不是以&作为分隔符,而是以+作为分隔符
学会了register_argc_argv后,它对于安全有什么威胁呢?
修改代码
进行查看
可以看到,当开启register_argc_argv后,Cli模式下会注册两个全局变量$argc,$argv。也就是说它同时在$_SERVER中和超全局变量中创建了对应的参数信息。
(这样就有可能出现变量覆盖的情况)
可以看见其中是以+号作为分隔符,而不是&
源码分析
/* {{{ php_build_argv */
PHPAPI void php_build_argv(const char *s, zval *track_vars_array)
{
zval arr, argc, tmp;
int count = 0;
if (!(SG(request_info).argc || track_vars_array)) {
return;
}
array_init(&arr);
/* Prepare argv */
if (SG(request_info).argc) { /* are we in cli sapi? */
int i;
for (i = 0; i < SG(request_info).argc; i++) {
ZVAL_STRING(&tmp, SG(request_info).argv[i]);
if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) {
zend_string_efree(Z_STR(tmp));
}
}
} else if (s && *s) {
while (1) {
const char *space = strchr(s, '+'); //分隔符的设置
/* auto-type */
ZVAL_STRINGL(&tmp, s, space ? space - s : strlen(s));
count++;
if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) {
zend_string_efree(Z_STR(tmp));
}
if (!space) {
break;
}
s = space + 1;
}
}
/* prepare argc */
if (SG(request_info).argc) {
ZVAL_LONG(&argc, SG(request_info).argc);
} else {
ZVAL_LONG(&argc, count);
}
if (SG(request_info).argc) {
Z_ADDREF(arr);
zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), &arr);
zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), &argc);
}
if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) {
Z_ADDREF(arr);
zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGV), &arr);
zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGC), &argc);
}
zval_ptr_dtor_nogc(&arr);
}
漏洞利用
用这个特性写个高免杀一句话
但是说了这么多,前提得是register_argc_argv开启得情况下,但默认是不开启的,所以这里就到此gg了嘛???看了一个大师傅的博客,发现并非如此
可以看到该属性的设置权限为php_ini_perdir,查看配置权限
柳暗花明又一村
于是乎,就算配置中默认没开启register_argc_argv选项,但我们可以先上传一个.htaccess(Apache)或.user.ini来对配置进行覆盖
.htaccess
php_value register_argc_argv On
.user.ini
register_argc_argv=On
直接尝试
不知道为什么本地就是不成功,按道理应该是可以的..
折腾了小一会儿,突然想起来会不会是没开启.htaccess覆盖模式
将配置修改好后,再次访问成功
漏洞利用(2)
利用pear.cmd从LFI到getshell
总结
姿势是真的骚,基础是真的ε=ε=ε=( ̄▽ ̄)
缺少必要的开发及运维知识,导致对很多配置都不熟悉。。。
- .htaccess为什么可以被访问?
是因为未对请求的资源进行过滤,导致可以访问.htaccess或.user.ini
2.apache重写模块配置
https://www.cnblogs.com/liluxiang/p/9450826.html