<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7399">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">README-SERIOUSLY.bestpractices.txt: Convert to markdown<br><br>Follow-up to conversion of README.md.<br><br>Change-Id: I17ee7cf25bc027ece844efa2c1dfe613aff1e35b<br>---<br>R README-SERIOUSLY.bestpractices.md<br>1 file changed, 69 insertions(+), 57 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/99/7399/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/README-SERIOUSLY.bestpractices.txt b/README-SERIOUSLY.bestpractices.md<br>similarity index 89%<br>rename from README-SERIOUSLY.bestpractices.txt<br>rename to README-SERIOUSLY.bestpractices.md<br>index 7a65602..7e18c4a 100644<br>--- a/README-SERIOUSLY.bestpractices.txt<br>+++ b/README-SERIOUSLY.bestpractices.md<br>@@ -1,51 +1,34 @@<br>-==================<br>-| Best Practices |<br>-==================<br>+# Best Practices<br> <br> The purpose of this document is to define best practices when working with<br> Asterisk in order to minimize possible security breaches and to provide tried<br> examples in field deployments. This is a living document and is subject to<br> change over time as best practices are defined.<br> <br>---------<br>-Sections<br>---------<br>-<br>-* Filtering Data:<br>+* [Filtering Data]:<br> How to protect yourself from redial attacks<br>-<br>-* Proper Device Naming:<br>+* [Proper Device Naming]:<br> Why to not use numbered extensions for devices<br>-<br>-* Secure Passwords:<br>+* [Secure Passwords]:<br> Secure passwords limit your risk to brute force attacks<br>-<br>-* Reducing Pattern Match Typos:<br>+* [Reducing Pattern Match Typos]:<br> Using the 'same' prefix, or using Goto()<br>-<br>-* Manager Class Authorizations:<br>+* [Manager Class Authorizations]:<br> Recognizing potential issues with certain classes of authorization<br>-<br>-* Avoid Privilege Escalations:<br>+* [Avoid Privilege Escalations]:<br> Disable the ability to execute functions that may escalate privileges<br> <br>-----------------<br>-Additional Links<br>-----------------<br>+<br>+## Additional Links<br> <br> Additional links that contain useful information about best practices or<br> security are listed below.<br> <br>-* Seven Steps to Better SIP Security:<br>- http://blogs.digium.com/2009/03/28/sip-security/<br>-<br>-* Asterisk VoIP Security (webinar):<br>- https://www.asterisk.org/security/webinar/<br>+* [Seven Steps to Better SIP Security][blog-sip-security]<br>+* [Asterisk VoIP Security (webinar)][voip-security-webinar]<br> <br> <br>-==============<br>-Filtering Data<br>-==============<br>+## Filtering Data<br> <br> In the Asterisk dialplan, several channel variables contain data potentially<br> supplied by outside sources. This could lead to a potential security concern<br>@@ -61,20 +44,21 @@<br> with a number 0-9, and then accepts any additional information supplied by the<br> request.<br> <br>-[NOTE: We use SIP in this example, but is not limited to SIP only; protocols<br>- such as Jabber/XMPP or IAX2 are also susceptible to the same sort of<br>- injection problem.]<br>+**NOTE**:<br>+> We use SIP in this example, but is not limited to SIP only; protocols such as<br>+> Jabber/XMPP or IAX2 are also susceptible to the same sort of injection problem.<br> <br>-<br>+```INI<br> [incoming]<br> exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})<br> exten => _X.,n,Dial(SIP/${EXTEN})<br> exten => _X.,n,Hangup()<br>+```<br> <br> This dialplan may be utilized to accept calls to extensions, which then dial a<br> numbered device name configured in one of the channel configuration files (such<br>-as sip.conf, iax.conf, etc...) (see the section Proper Device Naming for more<br>-information on why this approach is flawed).<br>+as sip.conf, iax.conf, etc...) (see [Proper Device Naming] for more information<br>+on why this approach is flawed).<br> <br> The example we've given above looks harmless enough until you take into<br> consideration that several channel technologies accept characters that could<br>@@ -87,7 +71,9 @@<br> ${EXTEN} channel variable, which is then utilized by the Dial() application in<br> our example, thereby giving you the dialplan line of:<br> <br>+```INI<br> exten => _X.,n,Dial(SIP/500&SIP/itsp/14165551212)<br>+```<br> <br> Our example above has now provided someone with a method to place calls out of<br> your ITSP in a place where you didn't expect to allow it. There are a couple of<br>@@ -101,8 +87,8 @@<br> system command execution. The FILTER() dialplan function is available to remove<br> dangerous characters from untrusted strings to block the command injection.<br> <br>-Strict Pattern Matching<br>------------------------<br>+<br>+### Strict Pattern Matching<br> <br> The simple way to mitigate this problem is with a strict pattern match that does<br> not utilize the period (.) or bang (!) characters to match on one-or-more<br>@@ -110,7 +96,9 @@<br> to only accept three digit extensions, we could change our pattern match to<br> be:<br> <br>+```INI<br> exten => _XXX,n,Dial(SIP/${EXTEN})<br>+```<br> <br> In this way, we have minimized our impact because we're not allowing anything<br> other than the numbers zero through nine. But in some cases we really do need to<br>@@ -118,8 +106,8 @@<br> or when we want to handle something like a SIP URI. In this case, we'll need to<br> utilize the FILTER() dialplan function.<br> <br>-Using FILTER()<br>---------------<br>+<br>+### Using FILTER()<br> <br> The FILTER() dialplan function is used to filter strings by only allowing<br> characters that you have specified. This is a perfect candidate for controlling<br>@@ -132,10 +120,12 @@<br> starting with a number of zero through nine, we can use FILTER() to limit what<br> we will accept to just numbers. Our example would then change to something like:<br> <br>+```INI<br> [incoming]<br> exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})<br> exten => _X.,n,Dial(SIP/${FILTER(0-9,${EXTEN})})<br> exten => _X.,n,Hangup()<br>+```<br> <br> Note how we've wrapped the ${EXTEN} channel variable with the FILTER() function<br> which will then only pass back characters that fit into the numerical range that<br>@@ -146,17 +136,20 @@<br> which has a side effect of being usable in other locations of your dialplan if<br> necessary, and to handle error checking in a separate location.<br> <br>+```INI<br> [incoming]<br> exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})<br> exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})<br> exten => _X.,n,Dial(SIP/${SAFE_EXTEN})<br> exten => _X.,n,Hangup()<br>+```<br> <br> Now we can use the ${SAFE_EXTEN} channel variable anywhere throughout the rest<br> of our dialplan, knowing we've already filtered it. We could also perform an<br> error check to verify that what we've received in ${EXTEN} also matches the data<br> passed back by FILTER(), and to fail the call if things do not match.<br> <br>+```INI<br> [incoming]<br> exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})<br> exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})<br>@@ -168,14 +161,17 @@<br> exten => error,n,Verbose(2,EXTEN: "${EXTEN}" -- SAFE_EXTEN: "${SAFE_EXTEN}")<br> exten => error,n,Playback(silence/1&invalid)<br> exten => error,n,Hangup()<br>+```<br> <br> Another example would be using FILTER() to control the characters we accept when<br> we're expecting to get a SIP URI for dialing.<br> <br>+```INI<br> [incoming]<br> exten => _[0-9a-zA-Z].,1,Verbose(2,Incoming call to extension ${EXTEN})<br> exten => _[0-9a-zA-Z].,n,Dial(SIP/${FILTER(.@0-9a-zA-Z,${EXTEN})<br> exten => _[0-9a-zA-Z].,n,Hangup()<br>+```<br> <br> Of course the FILTER() function doesn't check the formatting of the incoming<br> request. There is also the REGEX() dialplan function which can be used to<br>@@ -188,9 +184,7 @@<br> Asterisk console.<br> <br> <br>-====================<br>-Proper Device Naming<br>-====================<br>+## Proper Device Naming<br> <br> In Asterisk, the concept of an extension number being tied to a specific device<br> does not exist. Asterisk is aware of devices it can call or receive calls from,<br>@@ -208,10 +202,12 @@<br> matches the devices name. For example, take a look at this poorly created device<br> in sip.conf:<br> <br>+```INI<br> [1000]<br> type=friend<br> context=international_dialing<br> secret=1000<br>+```<br> <br> As implied by the context, we've permitted a device named 1000 with a password<br> of 1000 to place calls internationally. If your PBX system is accessible via<br>@@ -224,10 +220,12 @@<br> address of the device, along with a strong password (see the section Secure<br> Passwords). The following example would be more secure:<br> <br>+```INI<br> [0004f2040001]<br> type=friend<br> context=international_dialing<br> secret=aE3%B8*$jk^G<br>+```<br> <br> Then in your dialplan, you would reference the device via the MAC address of the<br> device (or if using the softphone, a MAC address of a network interface on the<br>@@ -237,9 +235,7 @@<br> first ones added to the dictionary for brute force attacks.<br> <br> <br>-================<br>-Secure Passwords<br>-================<br>+## Secure Passwords<br> <br> Secure passwords are necessary in many (if not all) environments, and Asterisk<br> is certainly no exception, especially when it comes to expensive long distance<br>@@ -252,7 +248,9 @@<br> connection, be sure to use a secure password. A good example of a secure<br> password would be something like:<br> <br>+```<br> aE3%B8*$jk^G<br>+```<br> <br> Our password also contains 12 characters with a mixture of upper and<br> lower case characters, numbers, and symbols. Because these passwords are likely<br>@@ -263,19 +261,18 @@<br> production.<br> <br> Using a web search you can find several online password generators such as<br>-https://www.strongpasswordgenerator.com or there are several scripts that can be<br>+[Strong Password Generator] or there are several scripts that can be<br> used to generate a strong password.<br> <br> <br>-============================<br>-Reducing Pattern Match Typos<br>-============================<br>+## Reducing Pattern Match Typos<br> <br> As of Asterisk 1.6.2, a new method for reducing the number of complex pattern<br> matches you need to enter, which can reduce typos in your dialplan, has been<br> implemented. Traditionally, a dialplan with a complex pattern match would look<br> something like:<br> <br>+```INI<br> exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})<br> exten => _[3-5]XXX,n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})<br> exten => _[3-5]XXX,n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})<br>@@ -288,12 +285,14 @@<br> exten => error,1,Verbose(2,Unable to lookup technology or device for extension)<br> exten => error,n,Playback(silence/1&num-not-in-db)<br> exten => error,n,Hangup()<br>+```<br> <br> Of course there exists the possibility for a typo when retyping the pattern<br>-match _[3-5]XXX which will match on extensions 3000 through 5999. We can<br>+match _\[3-5\]XXX which will match on extensions 3000 through 5999. We can<br> minimize this error by utilizing the same => prefix on all lines beyond the<br> first one. Our same dialplan with using same => would look like the following:<br> <br>+```INI<br> exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})<br> same => n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})<br> same => n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})<br>@@ -306,11 +305,10 @@<br> exten => error,1,Verbose(2,Unable to lookup technology or device for extension)<br> same => n,Playback(silence/1&num-not-in-db)<br> same => n,Hangup()<br>+```<br> <br> <br>-============================<br>-Manager Class Authorizations<br>-============================<br>+## Manager Class Authorizations<br> <br> Manager accounts have associated class authorizations that define what actions<br> and events that account can execute/receive. In order to run Asterisk commands<br>@@ -322,6 +320,7 @@<br> class authorization for origination commands is "originate". Take, for example,<br> the Originate manager command:<br> <br>+```<br> Action: Originate<br> Channel: SIP/foo<br> Exten: s<br>@@ -329,6 +328,7 @@<br> Priority: 1<br> Application: System<br> Data: echo hello world!<br>+```<br> <br> This manager command will attempt to execute an Asterisk application, System,<br> which is normally associated with the "system" class authorication. While some<br>@@ -336,10 +336,12 @@<br> configurations and/or clever manipulation of the Originate manager action can<br> circumvent these checks. For example, take the following dialplan:<br> <br>+```INI<br> exten => s,1,Verbose(Incoming call)<br> same => n,MixMonitor(foo.wav,,${EXEC_COMMAND})<br> same => n,Dial(SIP/bar)<br> same => n,Hangup()<br>+```<br> <br> Whatever has been defined in the variable EXEC_COMMAND will be executed after<br> MixMonitor has finished recording the call. The dialplan writer may have<br>@@ -354,9 +356,8 @@<br> not running Asterisk as root, can prevent serious problems from arising when<br> allowing external connections to originate calls into Asterisk.<br> <br>-===========================<br>-Avoid Privilege Escalations<br>-===========================<br>+<br>+## Avoid Privilege Escalations<br> <br> External control protocols, such as Manager, often have the ability to get and<br> set channel variables; which allows the execution of dialplan functions.<br>@@ -370,7 +371,18 @@<br> <br> When these functions are executed from an external protocol, that execution<br> could result in a privilege escalation. Asterisk can inhibit the execution of<br>-these functions, if live_dangerously in the [options] section of asterisk.conf<br>+these functions, if live_dangerously in the \[options\] section of asterisk.conf<br> is set to no.<br> <br> In Asterisk 12 and later, live_dangerously defaults to no.<br>+<br>+<br>+[voip-security-webinar]: https://www.asterisk.org/security/webinar/<br>+[blog-sip-security]: http://blogs.digium.com/2009/03/28/sip-security/<br>+[Strong Password Generator]: https://www.strongpasswordgenerator.com<br>+[Filtering Data]: #filtering-data<br>+[Proper Device Naming]: #proper-device-naming<br>+[Secure Passwords]: #secure-passwords<br>+[Reducing Pattern Match Typos]: #reducing-pattern-match-typos<br>+[Manager Class Authorizations]: #manager-class-authorizations<br>+[Avoid Privilege Escalations]: #avoid-privilege-escalations<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7399">change 7399</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7399"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I17ee7cf25bc027ece844efa2c1dfe613aff1e35b </div>
<div style="display:none"> Gerrit-Change-Number: 7399 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>