Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 28 Aug 2014 18:42:23 +0200
From: Pierre Schweitzer <pierre@...ctos.org>
To: oss-security@...ts.openwall.com
Subject: Full disclosure: denial of service in srvx

Hi all,

ZeRoFiGhter and I (Pierre Schweitzer), at OnlineGamesNet.net discovered
the following issue on OnlineGamesNet.net on the 14th of July.

This is full disclosure of a denial of service security issue in srvx
software (http://www.srvx.net/). Vendor was contacted a month ago (on
the 16th of July) and acknowledge good reception of the issue and the
patches. The issues is today still unfixed in development trunk.

1 - Description:
=========
When configuring the HelpServ bots in srvx, there is not bound check for
intervals in which various functions are executed (for instance the
EmptyInterval parameter). These parameters can be accessed and set by
either IRCops (with access to OpServ bot) or by HelpServ bot managers
(who do not require to be IRCops).

Putting an extremely high value to these parameters, such as
184467440723049 will lead to an integer overflow. When attempting to
queue the function execution, srvx will add it in the past, will attempt
to execute it immediately and thus will loop forever on this, and will
finally crash due to memory exhaustion.

Furthermore, any restart of the service will not be possible, as the
value is stored in the configuration file. It will be required to
manually edit the configuration file to correct the wrongly set values
for the bot.

2 - How to reproduce:
=============
Simply create a bot with HelpServ module.
Set the high value: ?helpserv set HelpServ EmptyInterval 184467440723049
To fasten the coming crash: ?writeall and then ?restart
srvx will not show up again, it will crash on boot.

3 - Risks:
=====
Low. HelpServ module needs to be activated on your server. Furthermore,
only supposedly trusted people can change these settings (bot managers &
IRCops).

4 - Available fixes:
===========
See the two patches attached (generated against the development trunk).
These two patches are not dependent and can be applied separately and
both fix the issue.

0001-Ensure-that-timeq-added-function-isn-t-added-in-the-.patch: most
generic fix. It is here to deny any function adding in the past. In such
case, it will be dropped.
This patches fixes any issue linked to integer overflow for timeq
functions execution.
Applied alone it fixes the said issue.

0002-Bound-check-for-intervals-in-mod-helpserv.-This-prev.patch: the
bound check fix. It adds controls to the input of the users for the
function interval execution. And thus, prevents any overflow. It's set
to 2y, a widely used value in srvx for intervals (see timed bans).
Applied alone it fixes the said issue.

5 - Mitigation:
========
Inform concerned people (ie, with enough accesses) about the risks. 2y
is enough for maximum bound. Reduce accesses to not trusted enough people.

6 - Affected versions:
=============
1.3.1
Development trunk

With my best regards,

-- 
Pierre Schweitzer <pierre at reactos.org>
System & Network Administrator
Senior Kernel Developer
ReactOS Deutschland e.V.


From 88fd15f69376a0f544afd599e952f68cbaf9e919 Mon Sep 17 00:00:00 2001
From: Pierre Schweitzer <pierre@...ctos.org>
Date: Thu, 28 Aug 2014 18:06:10 +0200
Subject: Ensure that timeq added function isn't added in the past

---
 src/timeq.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/timeq.c b/src/timeq.c
index 767bc12..ad98c7f 100644
--- a/src/timeq.c
+++ b/src/timeq.c
@@ -59,6 +59,8 @@ timeq_add(unsigned long when, timeq_func func, void *data)
 {
     struct timeq_entry *ent;
     void *w;
+    if (when < now)
+    	return;
     ent = malloc(sizeof(struct timeq_entry));
     ent->func = func;
     ent->data = data;
-- 
1.9.1


From 8e53ee6ede5c1ff50f080b6f48c1cfb81f12bb22 Mon Sep 17 00:00:00 2001
From: Pierre Schweitzer <pierre@...ctos.org>
Date: Thu, 28 Aug 2014 18:06:46 +0200
Subject: Bound check for intervals in mod-helpserv. This prevents integer
 overflow in helpserv bots configuration

---
 src/mod-helpserv.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/mod-helpserv.c b/src/mod-helpserv.c
index c9eec1b..76655fe 100644
--- a/src/mod-helpserv.c
+++ b/src/mod-helpserv.c
@@ -3114,7 +3114,7 @@ static HELPSERV_OPTION(opt_req_closed) {
     return opt_message(user, hs, from_opserv, argc, argv, MSGTYPE_REQ_CLOSED);
 }
 
-static int opt_interval(struct userNode *user, struct helpserv_bot *hs, int from_opserv, int argc, char *argv[], enum interval_type idx, unsigned int min) {
+static int opt_interval(struct userNode *user, struct helpserv_bot *hs, int from_opserv, int argc, char *argv[], enum interval_type idx, unsigned int min, unsigned int max) {
     char buf[INTERVALLEN];
     int changed=0;
 
@@ -3124,7 +3124,7 @@ static int opt_interval(struct userNode *user, struct helpserv_bot *hs, int from
             helpserv_notice(user, "MSG_INVALID_DURATION", argv[0]);
             return 0;
         }
-        if (new_int && new_int < min) {
+        if (new_int && (new_int < min || new_int > max)) {
             intervalString(buf, min, user->handle_info);
             helpserv_notice(user, "HSMSG_INVALID_INTERVAL", user_find_message(user, interval_types[idx].print_name), buf);
             return 0;
@@ -3141,18 +3141,18 @@ static int opt_interval(struct userNode *user, struct helpserv_bot *hs, int from
 }
 
 static HELPSERV_OPTION(opt_idle_delay) {
-    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_IDLE_DELAY, 60);
+    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_IDLE_DELAY, 60, 60 * 60 * 24 * 365 * 2);
 }
 
 static HELPSERV_OPTION(opt_whine_delay) {
-    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_WHINE_DELAY, 60);
+    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_WHINE_DELAY, 60, 60 * 60 * 24 * 365 * 2);
 }
 
 static HELPSERV_OPTION(opt_whine_interval) {
     unsigned int old_val = hs->intervals[INTERVAL_WHINE_INTERVAL];
     int retval;
 
-    retval = opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_WHINE_INTERVAL, 60);
+    retval = opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_WHINE_INTERVAL, 60, 60 * 60 * 24 * 365 * 2);
 
     if (!old_val && hs->intervals[INTERVAL_WHINE_INTERVAL]) {
         timeq_add(now + hs->intervals[INTERVAL_WHINE_INTERVAL], run_whine_interval, hs);
@@ -3167,7 +3167,7 @@ static HELPSERV_OPTION(opt_empty_interval) {
     unsigned int old_val = hs->intervals[INTERVAL_EMPTY_INTERVAL];
     int retval;
 
-    retval = opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_EMPTY_INTERVAL, 60);
+    retval = opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_EMPTY_INTERVAL, 60, 60 * 60 * 24 * 365 * 2);
 
     if (!old_val && hs->intervals[INTERVAL_EMPTY_INTERVAL]) {
         timeq_add(now + hs->intervals[INTERVAL_EMPTY_INTERVAL], run_empty_interval, hs);
@@ -3179,7 +3179,7 @@ static HELPSERV_OPTION(opt_empty_interval) {
 }
 
 static HELPSERV_OPTION(opt_stale_delay) {
-    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_STALE_DELAY, 60);
+    return opt_interval(user, hs, from_opserv, argc, argv, INTERVAL_STALE_DELAY, 60, 60 * 60 * 24 * 365 * 2);
 }
 
 static enum persistence_length persistence_from_name(const char *name) {
-- 
1.9.1



[ CONTENT OF TYPE application/pkcs7-signature SKIPPED ]

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ