Commit e4824231 authored by J0WI's avatar J0WI Committed by Leonardo Arena
Browse files

community/mumble: security fixes (CVE-2018-20743)

parent 721147d3
......@@ -3,9 +3,9 @@
# Maintainer: Johannes Matheis <jomat+alpinebuild@jmt.gr>
pkgname=mumble
pkgver=1.2.19
pkgrel=4
pkgdesc="A low-latency, high quality voice chat software"
url="http://wiki.mumble.info"
pkgrel=5
pkgdesc="Low-latency, high quality voice chat software"
url="https://wiki.mumble.info"
arch="all"
license="BSD"
depends="qt-sqlite"
......@@ -17,9 +17,15 @@ pkgusers="murmur"
pkggroups="murmur"
subpackages="$pkgname-doc murmur murmur-doc:murmur_doc:noarch"
source="https://github.com/mumble-voip/$pkgname/releases/download/$pkgver/$pkgname-$pkgver.tar.gz
CVE-2018-20743.1.patch
CVE-2018-20743.2.patch
murmur.initd"
builddir="$srcdir"/$pkgname-$pkgver
# secfixes:
# 1.2.19-r5:
# - CVE-2018-20743
build() {
cd "$builddir"
qmake -recursive main.pro \
......@@ -104,4 +110,6 @@ murmur_doc() {
}
sha512sums="f91111194a899149b500a94afcf7cc5b9691c7ce8669f07fca2c66adbb3916ddb863bf703d04fb8387133fb75f3c8edb52974d1acf3febfafa1f73da19946de4 mumble-1.2.19.tar.gz
6a3c78a479c795f91fabd557c34249308e1032be51ee668a9576cb8d2f7028526c4d79895b5053822c05f998e147a0577e801e8a27c9a454a4473193f16de943 CVE-2018-20743.1.patch
9e2b0dcb5ca34aea1607e0561446bced93e13ce296df986855299f7b652e99db8f9504e0dfa6544e8f443996b8a78a912328f4924813a4716028a8323c70d6d0 CVE-2018-20743.2.patch
c74ade232146a180448cb0027503f59642000bee50613a1fb99162cdc4bc81089ab4e84e51b0bbdac5c176eb52b76e6bd2b3ec790a9148135a1fc050569921c3 murmur.initd"
From 0daec57f5cfc4225aa4527b537b4ec4fbbc35635 Mon Sep 17 00:00:00 2001
From: MadMaurice <madmaurice@zom.bi>
Date: Thu, 30 Aug 2018 15:08:01 +0200
Subject: [PATCH] Prevent instability and crash due to message flood
This patch adds a rate limiting to selected patches. The underlying rate limiter
used is the Leaky-Bucket algorithm. It allows for a burst of messages, but
limits them after a specified amount of messages within a time frame.
---
src/murmur/Messages.cpp | 17 ++++++++++++
src/murmur/ServerUser.cpp | 58 +++++++++++++++++++++++++++++++++++++++
src/murmur/ServerUser.h | 29 ++++++++++++++++++++
3 files changed, 104 insertions(+)
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp
index 967cff794..1739378e1 100644
--- a/src/murmur/Messages.cpp
+++ b/src/murmur/Messages.cpp
@@ -42,6 +42,11 @@
#include "ServerUser.h"
#include "Version.h"
+#define RATELIMIT(user) \
+ if (user->leakyBucket.ratelimit(1)) { \
+ return; \
+ }
+
#define MSG_SETUP(st) \
if (uSource->sState != st) { \
return; \
@@ -679,6 +684,10 @@
bBroadcast = true;
}
+ if (uSource == pDstServerUser) {
+ RATELIMIT(uSource);
+ }
+
if (msg.has_channel_id()) {
Channel *c = qhChannels.value(msg.channel_id());
@@ -791,6 +800,8 @@
c = qhChannels.value(msg.channel_id());
if (! c)
return;
+ } else {
+ RATELIMIT(uSource);
}
// Check if the parent exists
@@ -1074,6 +1076,8 @@
QSet<ServerUser *> users;
QQueue<Channel *> q;
+ RATELIMIT(uSource);
+
QString text = u8(msg.message());
bool changed = false;
@@ -1241,6 +1254,8 @@ void Server::msgACL(ServerUser *uSource, MumbleProto::ACL &msg) {
return;
}
+ RATELIMIT(uSource);
+
if (msg.has_query() && msg.query()) {
QStack<Channel *> chans;
Channel *p;
@@ -1497,6 +1512,8 @@ void Server::msgContextAction(ServerUser *uSource, MumbleProto::ContextAction &m
}
void Server::msgVersion(ServerUser *uSource, MumbleProto::Version &msg) {
+ RATELIMIT(uSource);
+
if (msg.has_version())
uSource->uiVersion=msg.version();
if (msg.has_release())
diff --git a/src/murmur/ServerUser.cpp b/src/murmur/ServerUser.cpp
index c851d86d8..e5c570d47 100644
--- a/src/murmur/ServerUser.cpp
+++ b/src/murmur/ServerUser.cpp
@@ -112,3 +112,61 @@ int BandwidthRecord::bandwidth() const {
return static_cast<int>((sum * 1000000ULL) / elapsed);
}
+#if __cplusplus > 199711LL
+
+inline static
+time_point now() {
+ return std::chrono::steady_clock::now();
+}
+
+inline static
+unsigned long millisecondsBetween(time_point start, time_point end) {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+}
+
+#else
+
+inline static
+time_point now() {
+ return clock();
+}
+
+inline static
+unsigned long millisecondsBetween(time_point start, time_point end) {
+ return 1000 * (end - start) / CLOCKS_PER_SEC;
+}
+
+#endif
+
+// Rate limiting: burst up to 30, 4 message per sec limit over longer time
+LeakyBucket::LeakyBucket() : tokensPerSec(4), maxTokens(30), currentTokens(0) {
+ lastUpdate = now();
+}
+
+bool LeakyBucket::ratelimit(int tokens) {
+ // First remove tokens we leaked over time
+ time_point tnow = now();
+ long ms = millisecondsBetween(lastUpdate, tnow);
+
+ long drainTokens = (ms * tokensPerSec) / 1000;
+
+ // Prevent constant starvation due to too many updates
+ if (drainTokens > 0) {
+ this->lastUpdate = tnow;
+
+ this->currentTokens -= drainTokens;
+ if (this->currentTokens < 0) {
+ this->currentTokens = 0;
+ }
+ }
+
+ // Then try to add tokens
+ bool limit = this->currentTokens > ((static_cast<long>(maxTokens)) - tokens);
+
+ // If the bucket is not overflowed, allow message and add tokens
+ if (!limit) {
+ this->currentTokens += tokens;
+ }
+
+ return limit;
+}
diff --git a/src/murmur/ServerUser.h b/src/murmur/ServerUser.h
index 28e582739..0a3828205 100644
--- a/src/murmur/ServerUser.h
+++ b/src/murmur/ServerUser.h
@@ -14,6 +14,13 @@
#include <winsock2.h>
#endif
+// <chrono> was introduced in C++11
+#if __cplusplus > 199711LL
+#include <chrono>
+#else
+#include <ctime>
+#endif
+
#include "Connection.h"
#include "Timer.h"
#include "User.h"
@@ -55,6 +62,26 @@ struct WhisperTarget {
class Server;
+#if __cplusplus > 199711L
+ typedef std::chrono::time_point<std::chrono::steady_clock> time_point;
+#else
+ typedef clock_t time_point;
+#endif
+
+// Simple algorithm for rate limiting
+class LeakyBucket {
+ private:
+ unsigned int tokensPerSec, maxTokens;
+ long currentTokens;
+ time_point lastUpdate;
+
+ public:
+ // Returns true if packets should be dropped
+ bool ratelimit(int tokens);
+
+ LeakyBucket();
+};
+
class ServerUser : public Connection, public User {
private:
Q_OBJECT
@@ -103,6 +130,8 @@ class ServerUser : public Connection, public User {
QMap<int, TargetCache> qmTargetCache;
QMap<QString, QString> qmWhisperRedirect;
+ LeakyBucket leakyBucket;
+
int iLastPermissionCheck;
QMap<int, unsigned int> qmPermissionSent;
#ifdef Q_OS_UNIX
From 4761ca41ab1f611cd4a6d117f9f6cfd7c64f6b55 Mon Sep 17 00:00:00 2001
From: MadMaurice <madmaurice@zom.bi>
Date: Fri, 31 Aug 2018 00:01:40 +0200
Subject: [PATCH] Lower bucket params
Use 1 tokens per second and 5 burst instead of 4 tokens per second and 30 burst
---
src/murmur/ServerUser.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/murmur/ServerUser.cpp b/src/murmur/ServerUser.cpp
index e5c570d47..5356690de 100644
--- a/src/murmur/ServerUser.cpp
+++ b/src/murmur/ServerUser.cpp
@@ -138,8 +138,8 @@ unsigned long millisecondsBetween(time_point start, time_point end) {
#endif
-// Rate limiting: burst up to 30, 4 message per sec limit over longer time
-LeakyBucket::LeakyBucket() : tokensPerSec(4), maxTokens(30), currentTokens(0) {
+// Rate limiting: burst up to 5, 1 message per sec limit over longer time
+LeakyBucket::LeakyBucket() : tokensPerSec(1), maxTokens(5), currentTokens(0) {
lastUpdate = now();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment