 |
|
 |
by Tan Chew Keong
Release Date: 17 Jan 2005
Japanese Version
NodeManager Professional
is a network management and monitoring tool.
It receives SNMPv1 traps and displays them on screen and writes them to
a log file. NodeManager Professional V2.00 has a stack overflow
vulnerability that can be exploited by sending a specially crafted
SNMPv1 trap.
NodeManager Professional V2.00 on English Win2K SP4, WinXP SP1, SP2.
NodeManager Professional allows the user to use a format string to
customize how each received SNMPv1 trap is logged. For example, the default
format string for the LinkDown event is
"Snmp Trap LinkDown (EnterPrise=%EPRISE ObjectID=%OID Value=%DATA)"
When a LinkDown-Trap packet is received, the various placeholders
(e.g. %OID, %DATA) will be replaced with the received values. The
resulting string is then displayed on screen and written out to a log file.
The various fields from the received LinkDown-Trap UDP packet is first copied
to global buffers in the .data segment.
When the format string is parsed, each received value is first copied to a
512-byte local stack buffer before it is concatenated to the final string.
By sending a LinkDown-Trap packet containing an OCTET-STRING of more than 512
bytes in the Trap variable-bindings field, it is possible to overflow the stack
buffer and overwrite the EIP. This happens when the %DATA placeholder is processed.
Sample SNMPv1 Trap
A sample SNMPv1 Trap that can trigger the overflow is shown below.
Version: 1
Community: public
PDU type: TRAP-V1
Enterprise: 1.3.6.1.2.3.4.5.6.7
Agent address: 127.0.0.1
Trap type: LINK DOWN
Specific trap type: 0 (0)
Timestamp : 4660
Object identifier 1: 1.3.6.1.2.3.4.5.6
Value: OCTET-STRING: AAAAAAA [> 512 bytes] AAAAAAA
Analysis
The unsafe copy occurs in func_00424030() based on disassembled code from NodeManager.exe.
A 512-byte stack buffer belonging to func_0040EC50() is passed to func_0040ED80(), and then to
func_00424030() where the unsafe copy occurs. EIP can be controlled when func_0040EC50() returns.
This pseudo-C code was derived
based on disassembled code and may not be 100% accurate, but it gives an idea of where the overflow
occurs.
func_0040EC50(param1, param2, struct *receivedTrapDataStruct, char *formatString, char *outputBuf, outBufLen = 1023)
{
char tempBuf[512];
EBP = formatString;
EBX = 0;
while(*EBP)
{
AL = *EBP;
if(EBX >= outBufLen)
break;
if(AL == '%') // start of a placeholder
{
memset(tempBuf, 0, sizeof(tempBuf));
EBP++;
// func_0040ED80 returns length of placeholder
EBP += func_0040ED80(param2, receivedTrapDataStruct, EBP, tempBuf);
len = strlen(tempBuf);
if(outBufLen - EBX - 1 <= len)
return;
memcpy(outputBuf + EBX, tempBuf, len);
EBX += len;
}
else
{
EBP++;
*(outputBuf + EBX) = AL;
EBX++;
}
}
}
func_0040ED80(param1, struct *receivedTrapDataStruct, char *formatString, char *tempBuf)
{
// formatString now points to current placeholder
// compare current placeholder against a list of allowed placeholders
...
switch(placeholder_index)
{
case 0x1:
...
break;
case 0x12: // %DATA
...
// the actual copy occurs in func_00424030
func_00424030(receivedTrapDataStruct + someoffset, tempBuf, 4);
break;
default:
break;
}
...
}
func_00424030(struct *receivedTrapData, char *tempBuf, type)
{
...
switch(type)
{
...
case 0x4:
// In this case, receivedTrapData.data will contain "AAAAAA [> 512 bytes] AAAAA"
// tempBuf, which is passed from func_0040EC50() is a stack buffer of only 512 bytes
memcpy(tempBuf, receivedTrapData.data, strlen(receivedTrapData.data));
break;
default:
break;
}
}
This is the Proof-of-concept exploit code that was used to validate the vulnerability. It binds shell on
port 2001.
Proof-of-concept bindshell exploit code can be downloaded here.
Upgrade to version 2.01, which fixes this vulnerability.
20 Dec 04 - Vulnerability Discovered
21 Dec 04 - Initial Author Notification
22 Dec 04 - Received Author's Reply
07 Jan 05 - Second Author Notification
11 Jan 05 - Second Author Reply
15 Jan 05 - Author Released Fixed Version
17 Jan 05 - Public Release
For further questions and enquries, email them to the following.
Overall-in-charge: Tan Chew Keong
webmaster@security.org.sg
|
 |