Evitando Spoofing no Asterisk® SCF™
O uso malicioso do CALLERID(name)<number> pode ser uma forma de spoofing, onde o atacante tenta enganar o sistema ou usuários ao passar um número falso — como delphini<1234>. Isso pode ser usado para:
- Burlar regras de acesso;
- Fazer chamadas fraudulentas;
- Injetar comandos em logs, bancos de dados ou URAs, se não houver tratamento adequado.
Como evitar ataques via CALLERID(number) no Asterisk
1. Sanitizar o CALLERID no dialplan
Você pode limpar o número, mantendo apenas dígitos:
exten => _X.,1,Set(CALLERID(num)=${FILTER(0-9,${CALLERID(num)})})
Ou, para armazenar em variável segura:
exten => _X.,1,Set(SAFE_CALLERID=${FILTER(0-9,${CALLERID(num)})})
Assim, qualquer caractere estranho (letras, símbolos, espaços, etc) será removido.
2. Verificar padrões válidos antes de usar
exten => _X.,n,GotoIf($["${CALLERID(num)}" :!^ [0-9]+$] ?hangup,s,1)
Isso envia para um contexto de hangup se o número tiver algo além de dígitos.
3. Bloquear chamadas com CALLERID suspeito
Você pode negar chamadas que tenham nomes/números suspeitos:
exten => _X.,1,ExecIf($["${CALLERID(name)}" = "delphini"]?Hangup())
exten => _X.,n,ExecIf($["${CALLERID(num)}" = "1234"]?Hangup())
Ou usar expressões mais robustas com ${REGEX(...)}.
4. Forçar um novo CALLERID confiável
Se você sabe que as chamadas vêm de uma operadora confiável, pode substituir o CallerID:
exten => _X.,1,Set(CALLERID(num)=0123456789)
exten => _X.,n,Set(CALLERID(name)=EmpresaX)
5. No sip.conf ou pjsip.conf: Controlar permissões
SIP (chan_sip):
[ataque]
callerid=unknown
trustrpid=no
sendrpid=no
PJSIP (chan_pjsip):
[ataque]
trust_id_inbound=no
send_pai=no
send_rpid=no
Esses parâmetros evitam que o Asterisk confie no CALLERID vindo do peer.
6. Logs e proteção contra injeções
Nunca jogue o CALLERID(num) diretamente em banco de dados, logs ou AGI sem limpar. Exemplo:
exten => _X.,n,Set(SAFE_CID=${FILTER(0-9,${CALLERID(num)})})
7. iptables / fail2ban para SIP
Monitore tentativas suspeitas com fail2ban (regex em /var/log/asterisk/messages).
Pode criar regras para bloquear IPs que tentam registrar ou enviar chamadas com CALLERID inválido.
Segue um Validador de Chamadas Suspeitas por CallerID (Python)
- Bloquear IPs no IPTABLES (associados ao CallerID suspeito).
- Gravar os eventos em um banco de dados MariaDB.
Pré-requisitos
-
Python:
-
pyodbc
(oumysql-connector-python
) -
Acesso
sudo
(para executar iptables)
-
-
Banco de dados MariaDB com tabela:
CREATE TABLE chamadas_suspeitas (
id INT AUTO_INCREMENT PRIMARY KEY,
callerid VARCHAR(50),
ip VARCHAR(50),
datahora DATETIME,
motivo VARCHAR(255)
);
Código Python
import re
import logging
import subprocess
import mysql.connector
from datetime import datetime
# Configurações
DB_CONFIG = {
'host': 'localhost',
'user': 'usuario',
'password': 'senha',
'database': 'seu_banco'
}
PATTERNS_SUSPEITOS = [
r'^00\d{6,}', r'^1\d{2,}$', r'^\d{10,}$', r'^[*#]\d+',
r'^(.)\1{5,}$', r'^(1234|1111|0000)$', r'^anonymous$', r'^restricted$', r'^$',
]
def eh_callerid_suspeito(callerid):
callerid = callerid.strip().lower()
for padrao in PATTERNS_SUSPEITOS:
if re.match(padrao, callerid):
return padrao
return None
def bloquear_ip(ip):
try:
subprocess.run(['sudo', 'iptables', '-A', 'INPUT', '-s', ip, '-j', 'DROP'], check=True)
logging.warning(f"IP bloqueado via iptables: {ip}")
except subprocess.CalledProcessError as e:
logging.error(f"Erro ao bloquear IP: {ip} - {e}")
def registrar_no_banco(callerid, ip, motivo):
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
query = """
INSERT INTO chamadas_suspeitas (callerid, ip, datahora, motivo)
VALUES (%s, %s, %s, %s)
"""
valores = (callerid, ip, datetime.now(), motivo)
cursor.execute(query, valores)
conn.commit()
cursor.close()
conn.close()
logging.info(f"Registro salvo no banco: {callerid}, {ip}, motivo: {motivo}")
except Exception as e:
logging.error(f"Erro ao salvar no banco: {e}")
def processar_chamada(callerid, ip):
motivo = eh_callerid_suspeito(callerid)
if motivo:
bloquear_ip(ip)
registrar_no_banco(callerid, ip, motivo)
# Exemplo de chamadas
chamadas = [
{"callerid": "anonymous", "ip": "192.168.1.100"},
{"callerid": "5511999999999", "ip": "192.168.1.101"},
{"callerid": "999999", "ip": "192.168.1.102"},
{"callerid": "normaluser", "ip": "192.168.1.103"}
]
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
for chamada in chamadas:
processar_chamada(chamada["callerid"], chamada["ip"])
Dicas finais:
-
⚙️ Para o
sudo
funcionar sem senha comiptables
, edite/etc/sudoers
com:
youruser ALL=NOPASSWD: /sbin/iptables.
Deixe um comentário