README-SERIOUSLY.bestpractices.txt 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. ==================
  2. | Best Practices |
  3. ==================
  4. The purpose of this document is to define best practices when working with
  5. Asterisk in order to minimize possible security breaches and to provide tried
  6. examples in field deployments. This is a living document and is subject to
  7. change over time as best practices are defined.
  8. --------
  9. Sections
  10. --------
  11. * Filtering Data:
  12. How to protect yourself from redial attacks
  13. * Proper Device Naming:
  14. Why to not use numbered extensions for devices
  15. * Secure Passwords:
  16. Secure passwords limit your risk to brute force attacks
  17. * Reducing Pattern Match Typos:
  18. Using the 'same' prefix, or using Goto()
  19. * Manager Class Authorizations:
  20. Recognizing potential issues with certain classes of authorization
  21. * Avoid Privilege Escalations:
  22. Disable the ability to execute functions that may escalate privileges
  23. ----------------
  24. Additional Links
  25. ----------------
  26. Additional links that contain useful information about best practices or
  27. security are listed below.
  28. * Seven Steps to Better SIP Security:
  29. http://blogs.digium.com/2009/03/28/sip-security/
  30. * Asterisk VoIP Security (webinar):
  31. http://www.asterisk.org/security/webinar/
  32. ==============
  33. Filtering Data
  34. ==============
  35. In the Asterisk dialplan, several channel variables contain data potentially
  36. supplied by outside sources. This could lead to a potential security concern
  37. where those outside sources may send cleverly crafted strings of data which
  38. could be utilized, e.g. to place calls to unexpected locations.
  39. An example of this can be found in the use of pattern matching and the ${EXTEN}
  40. channel variable. Note that ${EXTEN} is not the only system created channel
  41. variable, so it is important to be aware of where the data you're using is
  42. coming from.
  43. For example, this common dialplan takes 2 or more characters of data, starting
  44. with a number 0-9, and then accepts any additional information supplied by the
  45. request.
  46. [NOTE: We use SIP in this example, but is not limited to SIP only; protocols
  47. such as Jabber/XMPP or IAX2 are also susceptible to the same sort of
  48. injection problem.]
  49. [incoming]
  50. exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
  51. exten => _X.,n,Dial(SIP/${EXTEN})
  52. exten => _X.,n,Hangup()
  53. This dialplan may be utilized to accept calls to extensions, which then dial a
  54. numbered device name configured in one of the channel configuration files (such
  55. as sip.conf, iax.conf, etc...) (see the section Proper Device Naming for more
  56. information on why this approach is flawed).
  57. The example we've given above looks harmless enough until you take into
  58. consideration that several channel technologies accept characters that could
  59. be utilized in a clever attack. For example, instead of just sending a request
  60. to dial extension 500 (which in our example above would create the string
  61. SIP/500 and is then used by the Dial() application to place a call), someone
  62. could potentially send a string like "500&SIP/itsp/14165551212".
  63. The string "500&SIP/itsp/14165551212" would then be contained within the
  64. ${EXTEN} channel variable, which is then utilized by the Dial() application in
  65. our example, thereby giving you the dialplan line of:
  66. exten => _X.,n,Dial(SIP/500&SIP/itsp/14165551212)
  67. Our example above has now provided someone with a method to place calls out of
  68. your ITSP in a place where you didn't expect to allow it. There are a couple of
  69. ways in which you can mitigate this impact: stricter pattern matching, or using
  70. the FILTER() dialplan function.
  71. Strict Pattern Matching
  72. -----------------------
  73. The simple way to mitigate this problem is with a strict pattern match that does
  74. not utilize the period (.) or bang (!) characters to match on one-or-more
  75. characters or zero-or-more characters (respectively). To fine tune our example
  76. to only accept three digit extensions, we could change our pattern match to
  77. be:
  78. exten => _XXX,n,Dial(SIP/${EXTEN})
  79. In this way, we have minimized our impact because we're not allowing anything
  80. other than the numbers zero through nine. But in some cases we really do need to
  81. handle variable pattern matches, such as when dialing international numbers
  82. or when we want to handle something like a SIP URI. In this case, we'll need to
  83. utilize the FILTER() dialplan function.
  84. Using FILTER()
  85. --------------
  86. The FILTER() dialplan function is used to filter strings by only allowing
  87. characters that you have specified. This is a perfect candidate for controlling
  88. which characters you want to pass to the Dial() application, or any other
  89. application which will contain dynamic information passed to Asterisk from an
  90. external source. Lets take a look at how we can use FILTER() to control what
  91. data we allow.
  92. Using our previous example to accept any string length of 2 or more characters,
  93. starting with a number of zero through nine, we can use FILTER() to limit what
  94. we will accept to just numbers. Our example would then change to something like:
  95. [incoming]
  96. exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
  97. exten => _X.,n,Dial(SIP/${FILTER(0-9,${EXTEN})})
  98. exten => _X.,n,Hangup()
  99. Note how we've wrapped the ${EXTEN} channel variable with the FILTER() function
  100. which will then only pass back characters that fit into the numerical range that
  101. we've defined.
  102. Alternatively, if we didn't want to utilize the FILTER() function within the
  103. Dial() application directly, we could save the value to a channel variable,
  104. which has a side effect of being usable in other locations of your dialplan if
  105. necessary, and to handle error checking in a separate location.
  106. [incoming]
  107. exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
  108. exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})
  109. exten => _X.,n,Dial(SIP/${SAFE_EXTEN})
  110. exten => _X.,n,Hangup()
  111. Now we can use the ${SAFE_EXTEN} channel variable anywhere throughout the rest
  112. of our dialplan, knowing we've already filtered it. We could also perform an
  113. error check to verify that what we've received in ${EXTEN} also matches the data
  114. passed back by FILTER(), and to fail the call if things do not match.
  115. [incoming]
  116. exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
  117. exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})
  118. exten => _X.,n,GotoIf($[${EXTEN} != ${SAFE_EXTEN}]?error,1)
  119. exten => _X.,n,Dial(SIP/${SAFE_EXTEN})
  120. exten => _X.,n,Hangup()
  121. exten => error,1,Verbose(2,Values of EXTEN and SAFE_EXTEN did not match.)
  122. exten => error,n,Verbose(2,EXTEN: "${EXTEN}" -- SAFE_EXTEN: "${SAFE_EXTEN}")
  123. exten => error,n,Playback(silence/1&invalid)
  124. exten => error,n,Hangup()
  125. Another example would be using FILTER() to control the characters we accept when
  126. we're expecting to get a SIP URI for dialing.
  127. [incoming]
  128. exten => _[0-9a-zA-Z].,1,Verbose(2,Incoming call to extension ${EXTEN})
  129. exten => _[0-9a-zA-Z].,n,Dial(SIP/${FILTER(.@0-9a-zA-Z,${EXTEN})
  130. exten => _[0-9a-zA-Z].,n,Hangup()
  131. Of course the FILTER() function doesn't check the formatting of the incoming
  132. request. There is also the REGEX() dialplan function which can be used to
  133. determine if the string passed to it matches the regular expression you've
  134. created, and to take proper action on whether it matches or not. The creation of
  135. regular expressions is left as an exercise for the reader.
  136. More information about the FILTER() and REGEX() dialplan functions can be found
  137. by typing "core show function FILTER" and "core show function REGEX" from your
  138. Asterisk console.
  139. ====================
  140. Proper Device Naming
  141. ====================
  142. In Asterisk, the concept of an extension number being tied to a specific device
  143. does not exist. Asterisk is aware of devices it can call or receive calls from,
  144. and how you define in your dialplan how to reach those devices is up to you.
  145. Because it has become common practice to think of a specific device as having an
  146. extension number associated with it, it only becomes natural to think about
  147. naming your devices the same as the extension number you're providing it. But
  148. by doing this, you're limiting the powerful concept of separating user from
  149. extensions, and extensions from devices.
  150. It can also be a security hazard to name your devices with a number, as this can
  151. open you up to brute force attacks. Many of the current exploits deal with
  152. device configurations which utilize a number, and even worse, a password that
  153. matches the devices name. For example, take a look at this poorly created device
  154. in sip.conf:
  155. [1000]
  156. type=friend
  157. context=international_dialing
  158. secret=1000
  159. As implied by the context, we've permitted a device named 1000 with a password
  160. of 1000 to place calls internationally. If your PBX system is accessible via
  161. the internet, then your system will be vulnerable to expensive international
  162. calls. Even if your system is not accessible via the internet, people within
  163. your organization could get access to dialing rules you'd prefer to reserve only
  164. for certain people.
  165. A more secure example for the device would be to use something like the MAC
  166. address of the device, along with a strong password (see the section Secure
  167. Passwords). The following example would be more secure:
  168. [0004f2040001]
  169. type=friend
  170. context=international_dialing
  171. secret=aE3%B8*$jk^G
  172. Then in your dialplan, you would reference the device via the MAC address of the
  173. device (or if using the softphone, a MAC address of a network interface on the
  174. computer).
  175. Also note that you should NOT use this password, as it will likely be one of the
  176. first ones added to the dictionary for brute force attacks.
  177. ================
  178. Secure Passwords
  179. ================
  180. Secure passwords are necessary in many (if not all) environments, and Asterisk
  181. is certainly no exception, especially when it comes to expensive long distance
  182. calls that could potentially cost your company hundreds or thousands of dollars
  183. on an expensive monthly phone bill, with little to no recourse to fight the
  184. charges.
  185. Whenever you are positioned to add a password to your system, whether that is
  186. for a device configuration, a database connection, or any other secure
  187. connection, be sure to use a secure password. A good example of a secure
  188. password would be something like:
  189. aE3%B8*$jk^G
  190. Our password also contains 12 characters with a mixture of upper and
  191. lower case characters, numbers, and symbols. Because these passwords are likely
  192. to only be entered once, or loaded via a configuration file, there is
  193. no need to create simple passwords, even in testing. Some of the holes found in
  194. production systems used for exploitations involve finding the one test extension
  195. that contains a weak password that was forgotten prior to putting a system into
  196. production.
  197. Using a web search you can find several online password generators such as
  198. http://www.strongpasswordgenerator.com or there are several scripts that can be
  199. used to generate a strong password.
  200. ============================
  201. Reducing Pattern Match Typos
  202. ============================
  203. As of Asterisk 1.6.2, a new method for reducing the number of complex pattern
  204. matches you need to enter, which can reduce typos in your dialplan, has been
  205. implemented. Traditionally, a dialplan with a complex pattern match would look
  206. something like:
  207. exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})
  208. exten => _[3-5]XXX,n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})
  209. exten => _[3-5]XXX,n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})
  210. exten => _[3-5]XXX,n,GotoIf($[${ISNULL(${TECHNOLOGY})} | ${ISNULL(${DEVICE})}]?error,1)
  211. exten => _[3-5]XXX,n,Dial(${TECHNOLOGY}/${DEVICE},${GLOBAL(TIMEOUT)})
  212. exten => _[3-5]XXX,n,Set(vmFlag=${IF($[${DIALSTATUS} = BUSY]?b:u)})
  213. exten => _[3-5]XXX,n,Voicemail(${EXTEN}@${GLOBAL(VOICEMAIL_CONTEXT)},${vmFlag})
  214. exten => _[3-5]XXX,n,Hangup()
  215. exten => error,1,Verbose(2,Unable to lookup technology or device for extension)
  216. exten => error,n,Playback(silence/1&num-not-in-db)
  217. exten => error,n,Hangup()
  218. Of course there exists the possibility for a typo when retyping the pattern
  219. match _[3-5]XXX which will match on extensions 3000 through 5999. We can
  220. minimize this error by utilizing the same => prefix on all lines beyond the
  221. first one. Our same dialplan with using same => would look like the following:
  222. exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})
  223. same => n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})
  224. same => n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})
  225. same => n,GotoIf($[${ISNULL(${TECHNOLOGY})} | ${ISNULL(${DEVICE})}]?error,1)
  226. same => n,Dial(${TECHNOLOGY}/${DEVICE},${GLOBAL(TIMEOUT)})
  227. same => n,Set(vmFlag=${IF($[${DIALSTATUS} = BUSY]?b:u)})
  228. same => n,Voicemail(${EXTEN}@${GLOBAL(VOICEMAIL_CONTEXT)},${vmFlag})
  229. same => n,Hangup()
  230. exten => error,1,Verbose(2,Unable to lookup technology or device for extension)
  231. same => n,Playback(silence/1&num-not-in-db)
  232. same => n,Hangup()
  233. ============================
  234. Manager Class Authorizations
  235. ============================
  236. Manager accounts have associated class authorizations that define what actions
  237. and events that account can execute/receive. In order to run Asterisk commands
  238. or dialplan applications that affect the system Asterisk executes on, the
  239. "system" class authorization should be set on the account.
  240. However, Manager commands that originate new calls into the Asterisk dialplan
  241. have the potential to alter or affect the system as well, even though the
  242. class authorization for origination commands is "originate". Take, for example,
  243. the Originate manager command:
  244. Action: Originate
  245. Channel: SIP/foo
  246. Exten: s
  247. Context: default
  248. Priority: 1
  249. Application: System
  250. Data: echo hello world!
  251. This manager command will attempt to execute an Asterisk application, System,
  252. which is normally associated with the "system" class authorication. While some
  253. checks have been put into Asterisk to take this into account, certain dialplan
  254. configurations and/or clever manipulation of the Originate manager action can
  255. circumvent these checks. For example, take the following dialplan:
  256. exten => s,1,Verbose(Incoming call)
  257. same => n,MixMonitor(foo.wav,,${EXEC_COMMAND})
  258. same => n,Dial(SIP/bar)
  259. same => n,Hangup()
  260. Whatever has been defined in the variable EXEC_COMMAND will be executed after
  261. MixMonitor has finished recording the call. The dialplan writer may have
  262. intended that this variable to be set by some other location in the dialplan;
  263. however, the Manager action Originate allows for channel variables to be set by
  264. the account initiating the new call. This could allow the Originate action to
  265. execute some command on the system by setting the EXEC_COMMAND dialplan variable
  266. in the Variable: header.
  267. In general, you should treat the Manager class authorization "originate" the
  268. same as the class authorization "system". Good system configuration, such as
  269. not running Asterisk as root, can prevent serious problems from arising when
  270. allowing external connections to originate calls into Asterisk.
  271. ===========================
  272. Avoid Privilege Escalations
  273. ===========================
  274. External control protocols, such as Manager, often have the ability to get and
  275. set channel variables; which allows the execution of dialplan functions.
  276. Dialplan functions within Asterisk are incredibly powerful, which is wonderful
  277. for building applications using Asterisk. But during the read or write
  278. execution, certain diaplan functions do much more. For example, reading the
  279. SHELL() function can execute arbitrary commands on the system Asterisk is
  280. running on. Writing to the FILE() function can change any file that Asterisk has
  281. write access to.
  282. When these functions are executed from an external protocol, that execution
  283. could result in a privilege escalation. Asterisk can inhibit the execution of
  284. these functions, if live_dangerously in the [options] section of asterisk.conf
  285. is set to no.
  286. In Asterisk 12 and later, live_dangerously defaults to no.