Recently, we have supplied a couple of patches for a customer
installation that are meant to solve proxy random crashes. The first
incident seems to point to failure in reassembly of TCP segments.
Whether the error was caused by a bug in sipXtackLib packet reassembly
algorithm or by a corruption in the packet due to low level transport
failure is yet to be determined. However, core dumps suggest that such
incidents could cause the SIP parser to crash at the point when the SIP
stack is trying to match messages with transactions. In this case,
parsing of the via header caused a segmentation fault. The via in the
SIPMessage looks like this.
Via: SIP/2.0/UDP
10.10.5.93:506���M��##6###6#####�#�####Z#D##E##(6�@#@#�e�##0
So I fired a new CPP UNIT test case against this via header hoping to
reproduce a crash but it didn't. Parser went fine with it. In fact
getting the via of SIP message even returned TRUE indicating nothing
about the error! Clearly, no check is being done in the parser as to
which bytes can legally be present in a SIP header. As to what caused
the crash is still unknown at this point and my main suspect is that
corruption in SIP messages allowed some buffer overruns to happen.
However, if only sanity checks where up, the crash could have been
avoided and prevented from being propagated into the transaction layer.
Incident number 2 of proxy crashing due to parser error is pretty
straight forward because it can be reproduced using a regression test
case. It happens when multiple packets are packed together in a single
TCP segment. In this particular incident, the TCP segment contained 3
INVITEs and 1 ACK request. The SDP in the INVITEs are not terminated by
an empty line but has the correct content-length. It is perfectly
formatted. However, the tokenizer of the SDP expects either a blank line
as the boundary or if the string is terminated by '\000' both of which
are not present. Blank line is not present because SDP ended at the last
line and was properly represented by content-length and '\000' is not
present because the next character after the SDP is already the
beginning of the next packet in the combo segment. This caused the
parser to overrun some bytes from the next packet resulting to corrupt
SIP Message. Yet again, parser crashed the system.
My proposal is to create a new task for this iteration to produce a
regression/crash test against the following parsers to catch more of
these possible proxy crashers.
1. Contact/From/To parsing including UTF 8
2. URI parsing - including IPV6 host parsing
3. Via parsing - including IPV6 host parsing
4. Route/Record-Route parsing - including IPV6
5. Request-Line/Status-Line parsing
6. Buffer overflow checks against integer headers (CSeq, Expires etc)
7. Improve NameValueTokenizer to respect boundaries instead of
positioning snipers in the front of the stack to prevent attacks.
If I missed something, just add to the list.
Modify parser accordingly based on results of these checks. The
NameValueTokenizer needs to be replaced by a boundary safe
implementation in main. I recommend boost::tokenizer
I would welcome and appreciate some comments.
Lastly my future plan is to introduce better exception handling in SIP
Message parsing and be able to respond back with a 400 with exactly
which header the parser thinks is bad. Something like the code below.
SipMessage msg;
try
{
msg.read(socket);
}
catch(SipParserException& e)
{
if (msg.isResponsePossible())
{
SipMessage response;
msg.createBadRequestResponse(response, e.what());
transport.send(response);
}
}
Joegen
_______________________________________________
sipx-dev mailing list
[email protected]
List Archive: http://list.sipfoundry.org/archive/sipx-dev/