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