asterisk / dialplan / variable expansion / security
Even after writing plenty of Asterisk PBX dialplan, I occasionally get bitten by the unintuitiveness of the parser.
A few rules to avoid mistakes, are:
-
Always use double quotes on no side of the expression, or better yet, on both if there is a chance that the value is empty:
$[${HANGUPCAUSE}=17]
or
$["${value_which_may_be_empty}"="somevalue"]
-
Otherwise try to avoid double quotes (and semi-colons, and backslashes) whenever possible. If you need to escape them, it’s too easy to get it wrong.
-
Always strip double quotes from any user input. Always.\
; imagine this variable comes from a valid SIP header same => n,Set(fromuser="!="InVaLiD"|") ; without this next line, you're screwed same => n,Set(fromuser=${FILTER(A-Za-z0-9_-,${fromuser})}) ; if we did not filter, this comparison would look like this: ; $[""!="InVaLiD"|""="secret"] same => n,Set(is_superuser=${IF($["${fromuser}"="secret"]?1:0)})
Today, I ran into this example, where — this time — the colon adds the magic. (Indented for clarity.)
;; drop optional <sip:...> -- changed between asterisk 10 and 11
same => n,Set(
tmp=${IF($["${SIPTRANSFER_REFERER:0:5}"="<sip:"]?
${SIPTRANSFER_REFERER:5:-1}:
${SIPTRANSFER_REFERER}
)})
You’d be tempted to guess that it works as advertised, converting
<sip:123@domain:5060>
to 123@domain:5060
and leaving the latter
as-is, but you’d be wrong.
For the input without surrounding <sip:...>
, it expands into this:
;; drop optional <sip:...> -- changed between asterisk 10 and 11
same => n,Set(tmp=${IF($["123@d"="<sip:"]?omain:506:123@domain:5060)})
Notice the colons? If we indent that for clarity, it looks like this:
;; drop optional <sip:...> -- changed between asterisk 10 and 11
same => n,Set(
tmp=${IF($["123@d"="<sip:"]?
omain:
506:123@domain:5060
)})
Drat, that came out wrong. tmp
is now 506:123@domain:5060
.
When changed to this, it works as intended:
same => n,Set(tmp=${SIPTRANSFER_REFERER})
;; drop optional <sip:...> -- changed between asterisk 10 and 11
same => n,ExecIf($["${tmp:0:5}"="<sip:"]?Set(tmp=${tmp:5:-1}))