9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
10 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.973 High
EPSS
Percentile
99.8%
Spoofs a call to a SIP phone and detects the action taken by the target (busy, declined, hung up, etc.)
This works by sending a fake sip invite request to the target phone and checking the responses. A response with status code 180 means that the phone is ringing. The script waits for the next responses until timeout is reached or a special response is received. Special responses include: Busy (486), Decline (603), Timeout (408) or Hang up (200).
Caller user ID. Defaults to Home
.
SIP Extension to send request from. Defaults to 100
.
Source application’s user agent. Defaults to Ekiga
.
Time to wait for a response. Defaults to 5s
Source address to spoof.
See the documentation for the sip library.
nmap --script=sip-call-spoof -sU -p 5060 <targets>
nmap --script=sip-call-spoof -sU -p 5060 --script-args
'sip-call-spoof.ua=Nmap, sip-call-spoof.from=Boss' <targets>
5060/udp open sip
| sip-call-spoof:
|_ Target hung up. (After 10.9 seconds)
local nmap = require "nmap"
local shortport = require "shortport"
local sip = require "sip"
local stdnse = require "stdnse"
description = [[
Spoofs a call to a SIP phone and detects the action taken by the target (busy, declined, hung up, etc.)
This works by sending a fake sip invite request to the target phone and checking
the responses. A response with status code 180 means that the phone is ringing.
The script waits for the next responses until timeout is reached or a special
response is received. Special responses include: Busy (486), Decline (603),
Timeout (408) or Hang up (200).
]]
---
--@args sip-call-spoof.ua Source application's user agent. Defaults to
-- <code>Ekiga</code>.
--
--@args sip-call-spoof.from Caller user ID. Defaults to <code>Home</code>.
--
--@args sip-call-spoof.extension SIP Extension to send request from. Defaults to
-- <code>100</code>.
--
--@args sip-call-spoof.src Source address to spoof.
--
--@args sip-call-spoof.timeout Time to wait for a response. Defaults to
-- <code>5s</code>
--
-- @usage
-- nmap --script=sip-call-spoof -sU -p 5060 <targets>
-- nmap --script=sip-call-spoof -sU -p 5060 --script-args
-- 'sip-call-spoof.ua=Nmap, sip-call-spoof.from=Boss' <targets>
--
--@output
-- 5060/udp open sip
-- | sip-call-spoof:
-- |_ Target hung up. (After 10.9 seconds)
author = "Hani Benhabiles"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "intrusive"}
portrule = shortport.port_or_service(5060, "sip", {"tcp", "udp"})
--- Function that sends an invite request with given parameters.
-- @arg session SIP Session to use.
-- @arg ua User Agent to use.
-- @arg from SIP From field.
-- @arg src Request source address to spoof.
-- @arg extension Request SIP extension.
-- @return status True if we got a response, false else.
-- @return resp Response table if status is true, error string else.
local sendinvite = function(session, ua, from, src, extension)
local request = sip.Request:new(sip.Method.INVITE)
request:setUri("sip:" .. session.sessdata:getServer())
request:setUA(ua)
if src then
session.sessdata:setDomain(src)
end
session.sessdata:setUsername(extension)
session.sessdata:setName(from)
request:setSessionData(session.sessdata)
return session:exch(request)
end
--- Function that waits for certain responses for an amount of time.
-- @arg session SIP Session to use.
-- @arg timeout Max time to wait for responses other than ringing.
-- @return ringing True if we got a ringing response, false else.
-- @return responsecode Code for the latest meaningful response.
-- could be 180, 200, 486, 408 or 603
local waitresponses = function(session,timeout)
local response, status, data, responsecode, ringing, waittime
local start = nmap.clock_ms()
while (nmap.clock_ms() - start) < timeout do
status, data = session.conn:recv()
if status then
response = sip.Response:new(data)
responsecode = response:getErrorCode()
waittime = nmap.clock_ms() - start
if responsecode == sip.Error.RING then
ringing = true
elseif responsecode == sip.Error.BUSY then
return ringing, sip.Error.BUSY
elseif responsecode == sip.Error.DECLINE then
return ringing, sip.Error.DECLINE, waittime
elseif responsecode == sip.Error.OK then
return ringing, sip.Error.OK, waittime
elseif responsecode == sip.Error.TIMEOUT then
return ringing, sip.Error.OK
end
end
end
if ringing then
return ringing, sip.Error.RING
end
end
--- Function that spoofs an invite request and listens for responses.
-- @arg session SIP Session to use.
-- @arg ua User Agent to use.
-- @arg from SIP From field.
-- @arg src Request source address to spoof.
-- @arg extension Request SIP extension.
-- @arg timeout Max time to wait for responses other than ringing.
-- @return ringing True if we got a ringing response, false else.
-- @return responsecode Code for the latest meaningful response.
-- could be 180, 200, 486, 408 or 603
local invitespoof = function(session, ua, from, src, extension, timeout)
local status, response = sendinvite(session, ua, from, src, extension)
-- check if we got a 100 Trying response.
if status and response:getErrorCode() == 100 then
-- wait for responses
return waitresponses(session, timeout)
end
end
action = function(host, port)
local status, session
local ua = stdnse.get_script_args(SCRIPT_NAME .. ".ua") or "Ekiga"
local from = stdnse.get_script_args(SCRIPT_NAME .. ".from") or "Home"
local src = stdnse.get_script_args(SCRIPT_NAME .. ".src")
local extension = stdnse.get_script_args(SCRIPT_NAME .. ".extension") or 100
local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
-- Default timeout value = 5 seconds.
timeout = (timeout or 5) * 1000
session = sip.Session:new(host, port)
status = session:connect()
if not status then
return stdnse.format_output(false, "Failed to connect to the SIP server.")
end
local ringing, result, waittime = invitespoof(session, ua, from, src, extension, timeout)
-- If we get a response, we set the port to open.
if result then
if nmap.get_port_state(host, port) ~= "open" then
nmap.set_port_state(host, port, "open")
end
end
-- We check for ringing to skip false positives.
if ringing then
if result == sip.Error.BUSY then
return stdnse.format_output(true, "Target line is busy.")
elseif result == sip.Error.DECLINE then
return stdnse.format_output(true, ("Target declined the call. (After %.1f seconds)"):format(waittime / 1000))
elseif result == sip.Error.OK then
return stdnse.format_output(true, ("Target hung up. (After %.1f seconds)"):format(waittime / 1000))
elseif result == sip.Error.TIMEOUT then
return stdnse.format_output(true, "Ringing, no answer.")
elseif result == sip.Error.RING then
return stdnse.format_output(true, "Ringing, got no answer. (script timeout)")
end
else
stdnse.debug1("Target phone didn't ring.")
end
end
9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
10 High
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.973 High
EPSS
Percentile
99.8%