php 5.3.9 漏洞,PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830) 详解
這個(gè)新的修復(fù)方法初衷是好的, 但是卻帶來一個(gè)嚴(yán)重的問題(5.3.10中已經(jīng)修復(fù)), 這個(gè)問題最初是由Stefan Esser發(fā)現(xiàn)的. 請看之前(5.3.9)最終的修復(fù)方案(php_register_variable_ex):
代碼如下
while (1) {
if (zend_symtable_find(symtable1, escaped_index, index_len + 1, (void **) &gpc_element_p) == FAILURE
|| Z_TYPE_PP(gpc_element_p) != IS_ARRAY) { //(3)
if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) { // (4)
if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. ...", PG(max_input_vars)); // (1)
}
MAKE_STD_ZVAL(gpc_element);
array_init(gpc_element);
zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
//......
}
//.....
symtable1 = Z_ARRVAL_PP(gpc_element_p); // (2)
goto plain;
}< li>
注意到, 如果此時(shí)注冊一個(gè)數(shù)組變量(在GET中類似于: a[]=2), 并且此時(shí)這個(gè)變量剛好是第max_input_vars個(gè)變量的時(shí)候, 會(huì)觸發(fā)一個(gè)警告(1), 此時(shí)一切正常.
但是, 如果此時(shí)還是注冊一個(gè)數(shù)組變量,但是這個(gè)變量已經(jīng)是第max_input_vars + 1個(gè)變量的時(shí)候, 那么此時(shí)gpc_element_p將成為一個(gè)未初始化的指針, 而因?yàn)楝F(xiàn)在邏輯會(huì)繼續(xù)走, 也就會(huì)走到(2)號位置, 導(dǎo)致解引用了一個(gè)未初始化的指針. 于是, Boomb~
那么, 到目前位置, 我們就可以使用這樣的特性來對5.3.9做Ddos了. 如果Server開啟了Core Dump的話, 這個(gè)效果會(huì)非常明顯.
然而, 這個(gè)問題還會(huì)導(dǎo)致一個(gè)更嚴(yán)重的問題:
還是上面的代碼, 在最外層有一個(gè)循環(huán), 這個(gè)循環(huán)起作用的時(shí)刻在注冊類似于a[b]=2的pair對的時(shí)候, 循環(huán)將會(huì)執(zhí)行倆次, 第一次插入a[], 第二次往a[]中插入b. 然后再讓我們注意下(3), 如果在目的數(shù)組中找不到一個(gè)想要的元素, **或者這個(gè)元素不為數(shù)組**, 則也會(huì)直接導(dǎo)致流程留到(2), 于是問題就出現(xiàn)了.
對于這樣的POST串(默認(rèn)max_input_vars是1000):
1=1&1=2&..........&999=1&x="我是惡意的string"&x[0]=
會(huì)發(fā)生什么事情呢?
讓我來一步一步描述下:
1. 從1到999沒什么問題, 都被正常插入
2. x是1000個(gè)元素, 所以觸發(fā)警告, 也沒有問題, x被插入
3. x[0]插入的時(shí)候, (3)號語句判斷發(fā)現(xiàn)不是Arrary于是進(jìn)入if體, 但是此時(shí)(4)號語句失敗, 于是流程最終流到了(2)
4. 此時(shí), gpc_element_p指向x, 也就是那個(gè)我們偽造的字符串….
現(xiàn)在讓我們看看關(guān)鍵的數(shù)據(jù)結(jié)構(gòu), zval:
代碼如下
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};< li>
然后看zvalue_value:
代碼如下
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;< li>
zvalue_value是一個(gè)聯(lián)合體, 于是我們構(gòu)造的字符串區(qū)域的內(nèi)存, 就會(huì)被當(dāng)做一個(gè)Hashtable結(jié)構(gòu)體:
代碼如下
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer; /* Used for element traversal */
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor; //注意這個(gè)
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;< li>
在Hashtable結(jié)構(gòu)體中, 有一個(gè)pDestructor, 這個(gè)指針指向一個(gè)函數(shù), 當(dāng)這個(gè)Hashtable中有元素要被清除的時(shí)候, 就會(huì)調(diào)用它…
也就是說, 你可以隨心所欲的設(shè)置一個(gè)地址(pDestructor), 然后讓PHP去調(diào)用它(誘使一個(gè)元素被刪除).
總結(jié)
以上是生活随笔為你收集整理的php 5.3.9 漏洞,PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830) 详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小学计算机教师育人案例,台屯小学青年教师
- 下一篇: 计算机中国象棋书籍,[建议]中国的象棋永