COMMAND
VNC
SYSTEMS AFFECTED
VNC version 3.3.3r7 for Windows
PROBLEM
Following is based on CORE SDI Security Advisory CORE-2001011502.
VNC stands for Virtual Network Computing. It is, in essence, a
remote display system which allows you to view a computing
'desktop' environment not only on the machine where it is running,
but from anywhere on the Internet and from a wide variety of
machine architectures.
The ATT VNC server for windows ships with a remotely and locally
exploitable buffer overflow if it is configured with a certain
debug level.
By providing a specially crafted HTTP request an attacker has the
ability to obtain access to the VNC server and execute arbitrary
commands with the privileges of the user running the server.
This vulnerability was found by Emiliano Kargieman, Agustin Azubel
and Maximiliano Caceres from Core SDI.
The following vulnerability depends on having the registry key
'DebugLevel' with a value greater than 0, and the ability to send
the right shellcode.
The VNC server listens on the network for incoming HTTP requests.
In the file vncHTTPConnect.cpp, method
vncHTTPConnectThread::DoHTTP, data read from the network is parsed
using sscanf( x, "GET %s", s ) into a buffer with 1024 bytes of
length. The request is logged issuing a call to Log::Print() with
the following string: "vncHTTPConnect.cpp : " + s + " file
requested\n".
In turn, Log::Print() (in Log.h) calls the private method
ReallyPrint() (in Log.cpp) which calls in turn vsprintf(3) with a
local buffer of fixed length (1024 bytes). Since the length of
the string might be as long as 1024 + 38 = 1062 bytes, the saved
return address in the stack can be overwritten, allowing the
attacker to execute arbitrary code with the privileges of the
account running the VNC server.
SOLUTION
Contact vendor for an appropriate fix. In the meantime apply this
patch while inside the vnc_winsrc/winvnc directory:
--- Log.cpp Mon Jan 15 18:17:46 2001
+++ Log.cpp Mon Jan 15 18:18:31 2001
@@ -130,7 +130,7 @@
// - Write the log message
TCHAR line[LINE_BUFFER_SIZE];
- vsprintf(line, format, ap);
+ _vsnprintf(line, sizeof(line)-sizeof(TCHAR), format, ap);
ReallyPrintLine(line);
}