Skip to content

Instantly share code, notes, and snippets.

@bashtheshell
Last active February 27, 2019 09:40
SIPp Ring Trigger for Videotelephony App

Videotelephony Ring Trigger


Purpose

The ultimate goal of this "ring trigger" guide is to test the videotelephony SIP-based client to see if it is actively listening on local socket. The client should ring continuously upon command execution. The tool used in this guide is simply a preexisting SIPp command, and we're going to take a narrow focus on only using the SIP INVITE request rather than the entire SIP handshake sequence.

Disclaimer: All information and software available on this guide are for educational purposes only. Use these at your own discretion, the author cannot be held responsible for any damages caused. Usage of all tools on this guide for attacking targets without prior mutual consent is illegal. It is the end user’s responsibility to obey all applicable local, state and federal laws. The author assumes no liability and is not responsible for any misuse or damage caused by this guide.

Quick Peak

For macOS, you'll need to install Homebrew first prior to installing SIPp:brew install sipp

For all other available platforms, please see the doc here.

To quickly test the "bloated" snippet on the SIP software client locally installed on your computer, run the following command (the example used client with IP 192.168.1.100, listening on port 5060):

sipp -sn uac -r 1 -rp -i 127.0.0.1 192.168.1.100:5060

You'd see spooling output. Although, the above command does more than just invoking the ring call, which is not what we want here. To exit the command, press CTRL+C.

The Real Deal

The main focus of this guide is to dissect the sipp command to the bare minimum so that we can only focus on one SIP request and reply.

Introduction:

As of version 3.5, SIPp command comes with integrated scenarios built-in. The one used in previous example is UAC (user-agent client) as indicated by the -sn uac command option.

To get a good idea of what the UAC handshake looks like:

SIPp UAC            Remote
    |(1) INVITE         |
    |------------------>|
    |(2) 100 (optional) |
    |<------------------|
    |(3) 180 (optional) |
    |<------------------|
    |(4) 200            |
    |<------------------|
    |(5) ACK            |
    |------------------>|
    |                   |
    |(6) PAUSE          |
    |                   |
    |(7) BYE            |
    |------------------>|
    |(8) 200            |
    |<------------------|

As you can see, we're only interested in the first and third responses. You can download the XML file to examine the default UAC scenario.

'Ring Trigger' Scenario:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- This file was tested with SIPp v3.5.2-PCAP-RTPSTREAM (as of 2/23/19)         -->


<scenario name="Basic Sipstone UAC">

<!-- 'caller_name' and 'caller_number' variables are used here         -->
<Global variables="caller_name,caller_number" />.

  <!-- In client mode (sipp placing calls), the Call-ID MUST be         -->
  <!-- generated by sipp. To do so, use [call_id] keyword.                -->
  <send>
    
    <!-- The second block below is for Session Description Protocol inside the SIP payload        -->
    <![CDATA[

      INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: [caller_name] <sip:[caller_number]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
      To: <sip:[service]@[remote_ip]:[remote_port]>
      Call-ID: [call_id]
      CSeq: 2 INVITE
      Contact: sip:[caller_number]@[local_ip]:[local_port]
      Max-Forwards: 67
      Subject: Performance Test
      Content-Type: application/sdp
      Content-Length: [len]

      v=0
      o=[caller_number] 4060584993 4060584993 IN IP[local_ip_type] [local_ip]
      s=-
      c=IN IP[media_ip_type] [media_ip]
      b=AS:570
      t=0 0
      m=audio [media_port] RTP/AVP 8 0 101
      a=rtpmap:0 PCMU/8000
      a=fmtp:8 bitrate=64000
      a=rtpmap:0 PCMU/8000
      a=fmtp:0 bitrate=64000
      a=rtpmap:101 telephone-event/8000
      a=fmtp:101 0-15
      a=ptime:20

    ]]>
  </send>

  <!-- 180 is used for ringing response from client. Command should exit upon success.      -->
  <recv response="180">
    <action>
      <!-- 'stop_now' is CTRL+C, 'stop_gracefully' is interactively pressing 'q'                -->
      <exec int_cmd="stop_gracefully"/>
    </action>
  </recv>


  <!-- NO ACKNOWLEDGEMENT SENT. WE WANT TO SEE THE RECIPIENT CLIENT GET STUCK WITH RINGING          -->


  <Reference variables="caller_name,caller_number" />
</scenario>

Command:

To test the SIP videotelephony client locally installed on the computer:

sipp -sf ring-trigger.xml -r 1 -i 127.0.0.1 -s 5551234567 -key caller_name "John Doe" -key caller_number "8885551234" 192.168.1.100:5060

sipp Breakdown Explained:

-sf option would loads an alternate XML scenario file. The above "ring trigger" scenario is pasted in an XML file named ring-trigger.xml in the current directory.

-r sets the call rate in calls per seconds, and the default rate period is 1 second. So, the command would attempt to generate a call per second until the handshake responses, defined in the scenario, have been processed.

-i sets the local IP address for 'Contact:','Via:', and 'From:' headers. By default, it'd use the primary host IP address. In our case, we use the loopback address to avoid the risk of accidentally scanning the SIP clients residing outside the host. However, if testing the remote client is desirable, then this option should be removed.

Below is a snippet of the SIP message header from the 'ring trigger' scenario:

INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [caller_name] <sip:[caller_number]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: <sip:[service]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 2 INVITE
Contact: sip:[caller_number]@[local_ip]:[local_port]

-s sets the username part of the request URI. The default is 'service'. In our case, this should be the recipient's phone number as you can see in the 'To:' header above.

-key sets the keyword, found in the scenario file, to a value. For example, we can set the [call_number] (by the way, this is not a phone number but rather a random sequential ID) as shown in the above snippet.

Two customs keywords have been added as it was defined in Global XML tag in our scenario file. The [caller_name] is the name of the caller who originated the call, and of course, [caller_number] is the originating number you'd see on the client's caller ID when ringing.

<Global variables="caller_name,caller_number" />.

And lastly, an IP address and listening port number would be needed to complete the command. In our case, we used the host address locally. To determine the listening socket, you can run the following from *nix terminal:

lsof -i | grep -E "(LISTEN|ESTABLISHED)"

Here's a pro-tip. For continuous spooling on the terminal to observe active sockets in real-time, use the watch command:

watch -n 1 'lsof -i | grep -E "(LISTEN|ESTABLISHED)"'

Known Issues

You may get the follow error, even with the minimum options: Last Error: Unable to send UDP message: Invalid argument.

To fix the above issue, add the -i 0.0.0.0 option to bind to any IP address on the local host or you can also specify your preferred interface's IP address here.


LICENSE

MIT License

Copyright (c) 2019 Travis Johnson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment