<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7700">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins2: Verified
George Joseph: Looks good to me, approved; Approved for Submit
</div><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, 81 insertions(+), 69 deletions(-)<br><br></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 88%<br>rename from README-SERIOUSLY.bestpractices.txt<br>rename to README-SERIOUSLY.bestpractices.md<br>index c8546bb..7e18c4a 100644<br>--- a/README-SERIOUSLY.bestpractices.txt<br>+++ b/README-SERIOUSLY.bestpractices.md<br>@@ -1,55 +1,38 @@<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>+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>-where those outside sources may send cleverly crafted strings of data which <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>+where those outside sources may send cleverly crafted strings of data which<br> could be utilized, e.g. to place calls to unexpected locations.<br> <br> An example of this can be found in the use of pattern matching and the ${EXTEN}<br>@@ -57,24 +40,25 @@<br> variable, so it is important to be aware of where the data you're using is<br> coming from.<br> <br>-For example, this common dialplan takes 2 or more characters of data, starting <br>+For example, this common dialplan takes 2 or more characters of data, starting<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>- <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>+```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>@@ -83,11 +67,13 @@<br> SIP/500 and is then used by the Dial() application to place a call), someone<br> could potentially send a string like "500&SIP/itsp/14165551212".<br> <br>-The string "500&SIP/itsp/14165551212" would then be contained within the <br>+The string "500&SIP/itsp/14165551212" would then be contained within the<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,16 +87,18 @@<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>+not utilize the period (.) or bang (!) characters to match on one-or-more<br> characters or zero-or-more characters (respectively). To fine tune our example<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>@@ -128,14 +116,16 @@<br> external source. Lets take a look at how we can use FILTER() to control what<br> data we allow.<br> <br>-Using our previous example to accept any string length of 2 or more characters, <br>-starting with a number of zero through nine, we can use FILTER() to limit what <br>+Using our previous example to accept any string length of 2 or more characters,<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,25 +235,25 @@<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>+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> calls that could potentially cost your company hundreds or thousands of dollars<br> on an expensive monthly phone bill, with little to no recourse to fight the<br> charges.<br> <br> Whenever you are positioned to add a password to your system, whether that is<br>-for a device configuration, a database connection, or any other secure <br>+for a device configuration, a database connection, or any other secure<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>+lower case characters, numbers, and symbols. Because these passwords are likely<br> to only be entered once, or loaded via a configuration file, there is<br> no need to create simple passwords, even in testing. Some of the holes found in<br> production systems used for exploitations involve finding the one test extension<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/7700">change 7700</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/7700"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: certified/13.18 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I17ee7cf25bc027ece844efa2c1dfe613aff1e35b </div>
<div style="display:none"> Gerrit-Change-Number: 7700 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>