This lab report summarizes experiments with implementing a simple call redirection service and testing the VoIP security system's response to valid and invalid SIP messages. The service was created using AGI to redirect unanswered calls from one user to another after 30 seconds. Testing showed the system handled some valid messages incorrectly and did not reject some invalid messages as expected.
This lab report summarizes experiments with implementing a simple call redirection service and testing the VoIP security system's response to valid and invalid SIP messages. The service was created using AGI to redirect unanswered calls from one user to another after 30 seconds. Testing showed the system handled some valid messages incorrectly and did not reject some invalid messages as expected.
This lab report summarizes experiments with implementing a simple call redirection service and testing the VoIP security system's response to valid and invalid SIP messages. The service was created using AGI to redirect unanswered calls from one user to another after 30 seconds. Testing showed the system handled some valid messages incorrectly and did not reject some invalid messages as expected.
This lab report summarizes experiments with implementing a simple call redirection service and testing the VoIP security system's response to valid and invalid SIP messages. The service was created using AGI to redirect unanswered calls from one user to another after 30 seconds. Testing showed the system handled some valid messages incorrectly and did not reject some invalid messages as expected.
The following lab exercises explore programmable services and security issues related to the Asterisk private branch exchange (PBX).
1. Simple Mobility Service
For our first task we implemented a simple mobility service that redirects calls if there is no answer within 30 seconds. Since the gateway to the PSTN has not been setup yet, our mobility service redirect calls to a user already registered with Asterisk. For our implementation we used the service creation tool AGI (Asterisk Gateway Interface), an interface for adding functionality to Asterisk by using many different programming languages such as Perl, PHP, Pascal, C and J ava. We chose to implement our service in C. Communication between our script and Asterisk is via standard input and standard output.
1.1 Implementing the service
We first implemented our C program that will be launched when a specific user calls another user. Communicating with Asterisk through the use of a script is relatively simple. The script writes to standard output to send a command to Asterisk, and reads from standard input to get the reply from Asterisk. Some things that need to be noted are the following:
At script startup Asterisk sends various pieces of information to our script that should be read via standard input before proceeding. These items are of no use in our case and can be ignored. Commands sent to Asterisk must be terminated with a newline character The results returned from Asterisk to our script are in the format of text strings
The script that we implemented can be seen in the following redirect.c text box. Our script first uses the setlinebuf on standard output and standard error in order to buffer one line at a time (rather than using a large buffer). We then read from standard input the items that are sent to our script once our script gets launched, and we simply ignore those items. The commands that we want Asterisk to execute follow. We send the commands to Asterisk by using printf. The first command tells Asterisk to dial cia8 for 30 seconds. The second command tells Asterisk to dial cia9. In our case the use of the two commands in this way have the effect of redirecting a calls. Once our script tells Asterisk to call cia8 for 30 seconds, if cia8 does not pickup, the script continues executing by telling Asterisk to call cia9. We then read Asterisks response from standard input and send the response to standard error which has the effect of sending the response to the console. This file is placed in the directory /var/lib/asterisk/agi-bin and is compiled using the command ./gcc redirect.c o redirect.agi. #i ncl ude <st di o. h> #i ncl ude <st r i ng. h>
mai n( ) {
char l i ne[ 80] ;
/ * Use l i ne buf f er i ng */ set l i nebuf ( st dout ) ; set l i nebuf ( st der r ) ;
/ * Read and i gnor e AGI envi r onment */ whi l e ( 1) { f get s( l i ne, 80, st di n) ;
i f ( st r l en( l i ne) <= 1) br eak; }
/ * Sendi ng Ast er i sk t he command t o di al ci a8 f or 30 mi nut es I f no r esponce i s r eci eved we send Ast er i sk a second command t o di al ci a9 */ pr i nt f ( " EXEC DI AL SI P/ ci a8| 30| m\ " \ " \ n" ) ; pr i nt f ( " EXEC DI AL SI P/ ci a9 \ " \ " \ n" ) ;
/ * Read r esponse f r omAst er i sk and show on consol e */ f get s( l i ne, 80, st di n) ; f put s( l i ne, st der r ) ;
}
redirect.c
1.2 Setting up the Dial plan
For our experiment we need to have 3 users registered on Asterisk. Our goal is to have cia7 call cia8 on extension 1000. If cia8 doesnt pick in 30 seconds, then the call is redirected to cia9, which in reality will be a second way in which cia8 can be contacted (i.e a cell phone). We add the 3 users, cia7, cia8 and cia9 in our sip.conf file. The changes in the sip.conf file can be seen in the following text box. We also need to set the appropriate functionality in the extensions.conf. In the extensions.conf file we add the context of cia7 that tells Asterisk to launch the script when cia7 calls extension 1000. The changes in the extensions.conf file can be seen in the following text box.
[ ci a7] t ype=f r i end user name=ci a7 secr et =ci a7 r egext en=9400 ; When t hey r egi st er , cr eat e ext ensi on 1234 host =dynami c ; Thi s devi ce needs t o r egi st er cont ext =ci a7t est
[ ci a8] t ype=f r i end user name=ci a8 secr et =ci a8 r egext en=9400 ; When t hey r egi st er , cr eat e ext ensi on 1234 host =dynami c ; Thi s devi ce needs t o r egi st er cont ext =ci a8t est
[ ci a9] t ype=f r i end user name=ci a9 secr et =ci a9 r egext en=9400 ; When t hey r egi st er , cr eat e ext ensi on 1234 host =dynami c ; Thi s devi ce needs t o r egi st er cont ext =ci a9t est
sip.conf
[ ci a7t est ] ext en => 1000, 1, AGI ( r edi r ect . agi )
extensions.conf
1.3 Testing the service
Once we have the above setup, we can launch Asterisk and perform the test. We observe that when the phone registered as cia7 dials 1000, cia8s phone rings for 30 seconds, and if there is no answer, cia9s phone starts to ring.
2. SIP Torture Tests
For our second task we used sipp and the torture tests described in RFC 4475 and tested our implementation to make sure it can handle those conditions. RFC 4475 gives examples of Session Initiation Protocol (SIP) test messages designed to exercise and torture a SIP implementation. The test messages are divided in valid messages and invalid messages. Each example clearly calls out what makes any invalid message incorrect. Please refer to the corresponding RFC as to what is being tested in each test message.
For the set of valid messages, we observed the following:
Test Case Observations A Short Tortuous INVITE Not working as the spaces and tabs are not properly parsed. Asterisk sent a 100 Trying back but did not forward call to the callee and 100 Trying was sent ot wrong IP address Wide Range of Valid Characters Not working as request URI should always be a number (in digit format) Valid Use of the % Escaping Mechanism Not working. Asterisk returns back "404 Resource Not Found". It is treating the request URI with %hex hex as a string and it does not replace the %hex hex values Escaped Nulls in URIs Not valid for Asterisk as request URIs should contain numbers only Use of % When It Is Not an Escape Sipp does not understand this format of % use, so it does not send the message Message with No LWS between Display Name and < Asterisk is not displaying the OPTIONS message Long Values in Header Fields Long header field values is valid and works Extra Trailing Octets in a UDP Datagram Asterisk is not printing out the message and does not understand the request Semicolon-Separated Parameters in URI User Part Asterisk is not understanding the request URI Varied and Unknown Transport Types Asterisk does not understand the OPTIONS request and discards it Multipart MIME Message Asterisk does not understand this valid MESSAGE Unusual Reason Phrase Not testing responses Empty Reason Phrase Not testing responses
For the set of invalid messages, we observed the following:
Test Case Observations Extraneous Header Field Separators Asterisk should reject the request with a "400 Bad Request" but treats it normally and proceeds Content Length Larger Than Message In UDP, Asterisk does not give a "400 Bad Request" but proceeds with the call. In TCP it waits for more packets to come but does not timeout Negative Content-Length For negative content length Asterisk in UDP returns 404. For TCP it does not terminate the connection Request Scalar Fields with Overlarge Values Asterisk does not understand large scalar values Unterminated Quoted String in Display Name Asterisk sends across the INVITE and is oblivious to the unqouted display name. It should return a "400 Bad Request". It seems that it simply parses the extension and ignores everything else <>Enclosing Request-URI Asterisk sends across the INVITE and is oblivious to the <>. It should return a "400 Bad Request". It seems that it simply parses the extension and ignores everything else Malformed SIP Request-URI (embedded LWS) Asterisk sends across the INVITE and its oblivious extra URI in the request line. It should return a "400 Bad Request". It seems that it simply parses the extension and ignores everything else Multiple SP Separating Request-Line Elements Asterisk sends across the INVITE and is oblivious to the extra space. It should return a "400 Bad Request". It seems that it simply parses the extension and ignores everything else SP Characters at End of Request-Line Asterisk returns a 200 OK for this sip OPTIONS message Escaped Headers in SIP Request-URI Asterisk ignores the invite request, does not forward it, sees the extension dialled and sends back 200 OK Invalid Timezone in Date Header Field Asterisk ignores the invite request, does not forward it, sees the extension dialled and sends back 200 OK. Failure to Enclose name-addr URI in <> Sip URI is malformed should return "400 Bad Request" but returns "404 Resource Not Found". So asterisk treats invalid message as a valid message Spaces within addr-spec Asterisk returns 200 OK. This implies that Asterisk does not understand the spaces at first parse of the message and stores as it is. It forwards the error Non-token Characters in Display Name Like before Asterisk treats the invalid request as valid and forwards the error Unknown Protocol Version Asterisk does not check protocol version Start Line and CSeq Method Mismatch Asterisk accepts the request having mismatching values for the method in the start line and the CSeq header field. It should reject it with a 400 Bad Request Unknown Method with CSeq Method Mismatch Unknown Method with CSeq Method Mismatch. Asterisk returns "501 Method Not Implemented", which is the right thing to do
3. Call Termination
For our third task we examined the possibility of terminating someone elses call by predicting the Call ID of a call. For our experiment we used the programs sipp and tcpdump.
3.1 Goal By having two users cia4 and cia3 registered on Asterisk, our goal is to have cia4 call cia3, have cia3 pick up and converse for some time, and have a malicious client terminate the call. The idea is that we will use tcpdump to capture the SIP header files that are exchanged during the initiation of the call between the two users, and then construct a BYE header file that will be send using sipp. This will result in the termination of the call.
3.2 Lab Topology
Our lab setup is the following: We registered two users, cia3 and cia4 with Asterisk cia3s host IP address is 160.39.253.209 cia4s host IP address is 160.39.247.21 Our Asterisks IP address is 128.59.15.57
3.2 Execution
In order to execute the termination of a call, we first use tcpdump to listen on port 5060 and capture all SIP header files that are exchanged between the two users. Once the call is in progress, we stop tcpdump, and examine the captured packets. From tcpdumps output we can distinguish all the SIP header files. In order to form the BYE message that will terminate the call, we need to get the IP addresses of cia3, cia4, and Asterisk as well as the From tag, To tag and Call ID. The IP addresses of cia3, cia4 and Asterisk can be easily retrieved from the captured data since they are included in all the header files exchanged. The rest are somewhat tricky since there are a few options that we could choose from. When Asterisk forwards header files for the initiation of a call between two users, he changes these fields and creates a mapping between header files sent from cia3 to Asterisk, and from Asterisk to cia4 (and vise versa). By performing some trial and error testing, we observed that the From tag and the Call ID that we needed to include in our BYE header where the ones used in the 3 rd INVITE. On the other hand, To tag that we needed was the one used in the 100 Trying message that was sent as a response to the 3 rd INVITE message. After collect this information we construct the BYE header file. The XML file that includes the BYE message that we implemented can be seen in the text box that follows.
<?xml ver si on=" 1. 0" encodi ng=" I SO- 8859- 1" ?> <! DOCTYPE scenar i o SYSTEM " si pp. dt d" >
<scenar i o name=" byemsg" >
<send r et r ans=" 500" > <! [ CDATA[
BYE si p: CI A3@160. 39. 253. 209: 5060 SI P/ 2. 0 Vi a: SI P/ 2. 0/ UDP 128. 59. 15. 57: 5060; br anch=z9hG4bK37cd9eb2; r por t Fr om: " ci a4" <si p: 5679@128. 59. 15. 57>; t ag=as3cf 8e189 To: <si p: CI A3@160. 39. 253. 209: 5060>; t ag=08a92ee38b91095 Cont act : <si p: 5679@128. 59. 15. 57; t r anspor t =UDP> Cal l - I D: 7d02d2136f eba4d479f d3d763f 949702@128. 59. 19. 58 CSeq: 105 BYE User - Agent : Ast er i sk PBX Max- For war ds: 70 Cont ent - Lengt h: 0
] ] > </ send>
<r ecv r esponse=" 200" cr l f =" t r ue" > </ r ecv>
</ scenar i o>
byemsg.xml
Once we have everything in place, we use sipp to send the xml file. The command used to send the file is:
. / si pp 160. 39. 253. 209: 5060 s ci a4 t u1 I 128. 59. 15. 57 p 5060 sf byemsg. xml r - 1 r p 1000 m1
This command sends the byemsg.xml to cia3 (160.39.253.209) and it acts as if it was sent from Asterisk (128.59.15.57). The result is that the connection between cia3 and Asterisk is terminated, while the connection between cia4 and Asterisk is still in session. Since cia3 has exited the call, the existing session between Asterisk and cia4 leads to a dead end.
4. INVITE DOS Attack
For our forth task, we simulated a DOS attack by flooding Asterisk with non- authenticated INVITE requests while serving legitimate requests. For our experiment we considered two scenarios. During our first scenario, we send a small number of legitimate INVITEs and a big number of non-authenticated INVITEs. During our second scenario we send Asterisk a big number of both legitimate and non-authenticated INVITEs.
4.1 Scenario 1
For our 1 st scenario we use two clients both running sipp. Our good client (client sending legitimate requests) sends 25 INVITE requests every 2 seconds, and our bad client (client sending non-authenticated requests) sends 400 requests per second. The commands used to flood Asterisk are the following:
Good client: . / si pp 128. 59. 19. 58: 5060 - s 1000 - t u1 - i 128. 59. 15. 49 - p 5060 - sf i nvi t e. xml - r 25 - r p 2000 - m10000
Bad client: . / si pp 128. 59. 19. 58: 5060 - s 1000 - t u1 - i 128. 59. 15. 64 - p 5060 - sf 3. 1. 1. 3. xml - r 400 - r p 1000 - m20000
From this scenario we observe that Asterisk in the beginning receives and responds to some of the legitimate requests but as time goes by a lot of retransmits start to show up. This shows that Asterisk is slowly reaching the point that the non-authenticated requests are taking most of Asterisks processing power. Asterisk doesnt respond to any of the non-authenticated requests. The following screenshots show this behavior.
Scenario 1: good requests being serviced
Scenario 1: bad requests being ignored
4.1 Scenario 2
For our 2 nd scenario we also use two clients both running sipp. Our good client sends 100 INVITE per seconds, and our bad client sends 400 requests per second. The commands used to flood Asterisk are the following:
Good client: . / si pp 128. 59. 19. 58: 5060 - s 1000 - t u1 - i 128. 59. 15. 49 - p 5060 - sf i nvi t e. xml - r 100 - r p 1000 - m10000
Bad client: . / si pp 128. 59. 19. 58: 5060 - s 1000 - t u1 - i 128. 59. 15. 64 - p 5060 - sf 3. 1. 1. 3. xml - r 400 - r p 1000 - m20000
From this scenario we observe that Asterisk does not respond to any of the legitimate and non-authenticated responses. The flooding of the requests makes Asterisk unable to process any of the legitimate requests. The following screenshots show this behavior.
Scenario 2: good requests being ignored
Scenario 2: bad requests being ignored
5. Interdomain DOS Attack
The DOS attack described in draft-lawrence-maxforward-problems-00 describes an attack against SIP networks where a small number of legitimate, even authorized, SIP requests can stimulate massive amounts of proxy-to-proxy traffic. This attack requires the use of multiple registrations with different contacts for the same user. Unfortunately this feature is not supported by Asterisk and thus we are unable to perform this task.