900+ FreePBX instances are still running web shells right now. Yours might be one of them.
In February 2026, the Shadowserver Foundation confirmed that over 900 Sangoma FreePBX systems were actively compromised through CVE-2025-64328 - a post-authentication command injection vulnerability in the Endpoint Manager filestore module. The attacks started in December 2025. The patch existed since November. Most victims never applied it.
This isn't a theoretical risk. The threat group INJ3CTOR3 deployed a web shell called EncystPHP on vulnerable systems. Once inside, they execute arbitrary commands as the asterisk user, generate fraudulent outbound calls, and pivot deeper into victim networks.
My take: The real problem isn't the CVE itself - it's that most FreePBX admins have zero visibility into what's happening on their PBX. They can't detect a compromise because they never set up monitoring. This article fixes that.
I'll walk you through exactly how to detect if your FreePBX is already compromised, harden it against future attacks, and set up ongoing monitoring that catches anomalies before they become incidents.
What Happened: CVE-2025-64328 Explained
CVE-2025-64328 (CVSS 8.6) is a command injection vulnerability in FreePBX's Endpoint Manager module, specifically in the check_ssh_connect() function within the filestore component.
Here's what makes it dangerous:
- —Attack vector: An authenticated user sends an HTTP request with
command=testconnectionanddriver=SSH. The user-supplied values for host, port, user, key, and path are passed to anexec()call without sanitization. - —Impact: Arbitrary shell command execution as the
asteriskuser - the service account that controls your entire PBX. - —Affected versions: FreePBX Endpoint Manager 17.0.2.36 and above, before 17.0.3.
- —Exploited by: INJ3CTOR3, a known threat group that targets VoIP infrastructure for toll fraud.
The injected web shell (EncystPHP) provides persistent remote access, command execution, and the ability to deploy additional web shells. Fortinet's FortiGuard Labs documented the campaign in January 2026.
Who's at Risk
If you run FreePBX with the Endpoint Manager module and your admin panel is accessible from the internet - even behind authentication - you're in the target zone.
The Shadowserver data shows compromised instances across 50+ countries:
- —401 in the United States
- —51 in Brazil
- —43 in Canada
- —40 in Germany
- —36 in France
My take: The "post-authentication" label gives people false comfort. It means the attacker needs any valid admin credential - not that your system is safe if you're running auth. Default credentials, reused passwords, and phished accounts all qualify.
Step 1: Check If You're Already Compromised
Before you harden anything, check if you're already owned. Run these checks on your FreePBX server via SSH.
Scan for Web Shells
The EncystPHP web shell and similar payloads typically hide in the web root. Search for suspicious PHP files:
# Find PHP files modified in the last 120 days in web-accessible directories
find /var/www/html -name "*.php" -mtime -120 -ls 2>/dev/null
# Look for common web shell signatures
grep -rl "eval(base64_decode" /var/www/html/ 2>/dev/null
grep -rl "system(\$_" /var/www/html/ 2>/dev/null
grep -rl "exec(\$_" /var/www/html/ 2>/dev/null
grep -rl "passthru(" /var/www/html/ 2>/dev/null
grep -rl "shell_exec(" /var/www/html/ 2>/dev/null | grep -v "/vendor/"
# Check for files owned by asterisk user that shouldn't be there
find /var/www/html -user asterisk -name "*.php" -newer /var/www/html/index.php -lsIf any of these return results, stop. Treat the system as compromised. Don't try to "clean" it - rebuild from known-good backups taken before December 2025.
Check for Unauthorized Cron Jobs
Web shells often install persistent cron jobs:
# Check asterisk user's crontab
crontab -u asterisk -l
# Check system cron directories
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
cat /var/spool/cron/asterisk 2>/dev/null
# Look for recently modified cron entries
find /etc/cron* -mtime -120 -ls 2>/dev/nullCheck Active Network Connections
Compromised PBXes often maintain outbound connections to command-and-control servers:
# List all established connections from the asterisk process
ss -tnp | grep asterisk
# Look for unexpected outbound connections (not your SIP trunks)
ss -tnp state established | grep -v ":5060" | grep -v ":5061"
# Check for listeners on unusual ports
ss -tlnp | grep -v -E ":(22|80|443|5060|5061|8080|8443|4569|10000)"Audit CDR for Toll Fraud
The #1 goal of INJ3CTOR3 is toll fraud - generating expensive international calls through your PBX. Check your CDR:
-- Find calls to international premium-rate destinations (last 30 days)
-- Run in Asterisk MySQL/MariaDB or your CDR database
SELECT
calldate,
src,
dst,
duration,
disposition,
channel
FROM cdr
WHERE calldate > DATE_SUB(NOW(), INTERVAL 30 DAY)
AND (
dst LIKE '011%' -- International (US dialing)
OR dst LIKE '00%' -- International (EU dialing)
OR dst LIKE '+%' -- E.164 international
OR LENGTH(dst) > 12 -- Unusually long numbers
)
AND duration > 0
ORDER BY calldate DESC
LIMIT 100;-- Find calls outside business hours (potential fraud indicator)
SELECT
DATE(calldate) as call_date,
HOUR(calldate) as call_hour,
COUNT(*) as call_count,
SUM(duration) as total_seconds,
COUNT(DISTINCT dst) as unique_destinations
FROM cdr
WHERE calldate > DATE_SUB(NOW(), INTERVAL 30 DAY)
AND (HOUR(calldate) < 6 OR HOUR(calldate) > 22)
AND disposition = 'ANSWERED'
GROUP BY DATE(calldate), HOUR(calldate)
HAVING call_count > 5
ORDER BY call_date DESC, call_hour;-- Detect sudden spikes in outbound call volume
SELECT
DATE(calldate) as call_date,
COUNT(*) as total_calls,
COUNT(CASE WHEN dst LIKE '011%' OR dst LIKE '00%' OR dst LIKE '+%'
THEN 1 END) as international_calls,
SUM(duration) as total_duration_sec,
ROUND(SUM(duration)/3600, 1) as total_hours
FROM cdr
WHERE calldate > DATE_SUB(NOW(), INTERVAL 60 DAY)
GROUP BY DATE(calldate)
ORDER BY call_date DESC;If you see international calls you don't recognize - especially to destinations in Africa, Eastern Europe, or the Caribbean - your system has likely been used for toll fraud.
My take: Most FreePBX admins check CDR once a month when the SIP trunk bill arrives. By then, a compromised system has generated thousands of dollars in fraudulent calls. Real-time CDR monitoring isn't optional - it's the difference between a $200 incident and a $20,000 phone bill.
Step 2: Patch and Harden Your FreePBX
If your system is clean (or you've rebuilt from backup), here's how to lock it down.
Apply the Patch
Update the Endpoint Manager module to version 17.0.3 or later:
# Update FreePBX modules
fwconsole ma upgradeall
fwconsole reload
# Verify the Endpoint Manager version
fwconsole ma list | grep endpointIf you can't update immediately, disable the vulnerable function by restricting access to the filestore component.
Lock Down the Admin Panel
The CVE requires authentication, but that's a weak barrier if your admin panel is internet-facing.
Restrict access by IP with iptables:
# Allow admin panel only from your management network
iptables -A INPUT -p tcp --dport 443 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j DROP
# Allow admin panel from a specific public IP (your office)
iptables -A INPUT -p tcp --dport 443 -s YOUR.OFFICE.IP.HERE -j ACCEPTOr use the FreePBX Responsive Firewall:
Admin -> Connectivity -> Firewall -> Interfaces
- Mark your LAN interface as "Trusted"
- Mark WAN/Internet as "Internet" (not Trusted)
- Enable "Responsive Firewall" for SIP only
- NEVER mark the internet interface as Trusted
Disable Unnecessary Modules
Every enabled module is an attack surface:
# List all installed modules
fwconsole ma list
# Disable modules you don't use
fwconsole ma disable endpointman # If you don't use Endpoint Manager
fwconsole ma disable restapi # If you don't use REST API
fwconsole ma disable webrtc # If you don't use WebRTC
fwconsole reloadHarden SSH Access
The exploit chain often starts with SSH compromise. Harden it:
# /etc/ssh/sshd_config - add or modify:
Port 2222 # Change from default 22
PermitRootLogin no # Never allow root SSH
PasswordAuthentication no # Key-based auth only
AllowUsers your-admin-user # Whitelist specific users
MaxAuthTries 3
LoginGraceTime 30# Restart SSH after changes
systemctl restart sshdTired of guessing what's happening in your queues?
Astervis gives you 30+ real-time charts, operator KPIs, and CRM integration for your Asterisk PBX. Self-hosted. Install in 5 minutes. From $119/mo flat — unlimited operators.
Configure Fail2Ban for FreePBX
Fail2Ban watches your logs and blocks IPs after failed auth attempts:
# /etc/fail2ban/jail.local
[freepbx]
enabled = true
filter = freepbx
action = iptables-allports[name=FreePBX, protocol=all]
logpath = /var/log/asterisk/freepbx_security.log
maxretry = 3
bantime = 86400
findtime = 600
[asterisk]
enabled = true
filter = asterisk
action = iptables-allports[name=Asterisk, protocol=all]
logpath = /var/log/asterisk/messages
maxretry = 3
bantime = 86400
findtime = 600# /etc/fail2ban/filter.d/freepbx.conf
[Definition]
failregex = \[SECURITY\](.*) from <HOST>
ignoreregex =# Restart Fail2Ban
systemctl restart fail2ban
# Check current bans
fail2ban-client status freepbxStep 3: Set Up Ongoing Security Monitoring
Patching and hardening are one-time actions. Monitoring is what keeps you safe long-term.
Monitor Asterisk Logs for Suspicious Activity
Your Asterisk logs contain signals that most admins never look at.
Key log files to watch:
| Log File | What It Contains |
|---|---|
/var/log/asterisk/freepbx_security.log | Authentication failures, blocked IPs |
/var/log/asterisk/full | All Asterisk events, including channel activity |
/var/log/asterisk/messages | SIP registration attempts, errors |
/var/log/httpd/access_log | Web panel access attempts |
/var/log/secure | SSH login attempts |
Automated log monitoring script:
#!/bin/bash
# /usr/local/bin/pbx-security-check.sh
# Run via cron every hour: 0 * * * * /usr/local/bin/pbx-security-check.sh
ALERT_EMAIL="admin@yourcompany.com"
LOG="/var/log/asterisk/freepbx_security.log"
# Count failed auth attempts in the last hour
FAILURES=$(grep "$(date -d '1 hour ago' '+%Y-%m-%d %H')" "$LOG" 2>/dev/null | grep -c "SECURITY")
if [ "$FAILURES" -gt 20 ]; then
echo "ALERT: $FAILURES auth failures in the last hour on $(hostname)" | \
mail -s "FreePBX Security Alert" "$ALERT_EMAIL"
fi
# Check for new PHP files in web root
NEW_PHP=$(find /var/www/html -name "*.php" -mmin -60 -ls 2>/dev/null)
if [ -n "$NEW_PHP" ]; then
echo "ALERT: New PHP files detected in web root:\n$NEW_PHP" | \
mail -s "FreePBX: Suspicious File Alert" "$ALERT_EMAIL"
fi
# Check for unexpected outbound connections
SUSPICIOUS=$(ss -tnp state established | grep asterisk | grep -v -E ":(5060|5061|3306|6379)" | head -5)
if [ -n "$SUSPICIOUS" ]; then
echo "ALERT: Unexpected outbound connections from asterisk:\n$SUSPICIOUS" | \
mail -s "FreePBX: Suspicious Connection Alert" "$ALERT_EMAIL"
fiSet Up CDR-Based Anomaly Detection
CDR analysis catches toll fraud faster than anything else. Here's a query you can run daily:
-- Daily anomaly detection: compare today's pattern to the 30-day average
SELECT
'TODAY' as period,
COUNT(*) as total_calls,
COUNT(CASE WHEN dst LIKE '011%' OR dst LIKE '00%' OR dst LIKE '+%'
THEN 1 END) as international_calls,
ROUND(AVG(duration), 0) as avg_duration,
COUNT(DISTINCT src) as unique_sources,
MAX(duration) as longest_call
FROM cdr
WHERE calldate >= CURDATE()
UNION ALL
SELECT
'30D_AVG' as period,
ROUND(COUNT(*) / 30, 0) as total_calls,
ROUND(COUNT(CASE WHEN dst LIKE '011%' OR dst LIKE '00%' OR dst LIKE '+%'
THEN 1 END) / 30, 0) as international_calls,
ROUND(AVG(duration), 0) as avg_duration,
ROUND(COUNT(DISTINCT src) / 30, 0) as unique_sources,
MAX(duration) as longest_call
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
AND calldate < CURDATE();If today's international call count is more than 3x the 30-day daily average, investigate immediately.
Monitor SIP Registration Attempts
Brute-force SIP registration is often the precursor to a full compromise:
-- Track failed SIP registrations per source IP (last 24 hours)
-- Requires Asterisk security event logging enabled
SELECT
SUBSTRING_INDEX(
SUBSTRING_INDEX(channel, '/', 2), '/', -1
) as source,
COUNT(*) as attempts,
MIN(calldate) as first_seen,
MAX(calldate) as last_seen
FROM cdr
WHERE calldate >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND disposition = 'FAILED'
GROUP BY source
HAVING attempts > 10
ORDER BY attempts DESC;Asterisk Configuration for Security Logging
Enable detailed security logging in your Asterisk config:
; /etc/asterisk/logger.conf
[logfiles]
security => security
full => notice,warning,error,verbose(3)
messages => notice,warning,error
[general]
dateformat=%F %T.%3q; /etc/asterisk/sip.conf (or pjsip.conf)
[general]
alwaysauthreject=yes ; Don't reveal valid extensions
allowguest=no ; Block unauthenticated calls; /etc/asterisk/extensions.conf
; Block international dialing by default - whitelist specific trunks
[from-internal]
; Only allow international calls through approved trunk
exten => _011.,1,NoOp(International call attempt: ${CALLERID(num)} -> ${EXTEN})
exten => _011.,n,Set(CDR(userfield)=INTL_ATTEMPT)
exten => _011.,n,GotoIf($["${CHANNEL(peerip)}" = "10.0.0.100"]?allow:deny)
exten => _011.,n(deny),Playback(ss-noservice)
exten => _011.,n,Hangup()
exten => _011.,n(allow),Dial(SIP/trunk/${EXTEN})Real-Time Monitoring: What to Track
Here are the metrics that matter for PBX security monitoring:
| Metric | Normal Range | Alert Threshold | What It Means |
|---|---|---|---|
| Failed SIP registrations/hour | < 10 | > 50 | Brute-force attempt in progress |
| International calls/day | Your baseline | > 3x baseline | Possible toll fraud |
| After-hours call volume | < 5 | > 20 | Unauthorized call generation |
| Active channels (off-hours) | 0-2 | > 10 | Compromised system making calls |
| New PHP files in web root | 0 | > 0 | Web shell deployment |
| Admin panel login failures/hour | < 5 | > 15 | Panel brute-force attempt |
| Unique outbound destinations/hour | < 20 | > 100 | Call generation bot active |
My take: Most security articles tell you to "enable logging." That's useless without someone (or something) actually reading the logs. Automated monitoring with threshold-based alerts is the only approach that works. You're not going to SSH into your PBX at 3 AM to check logs. But an alert at 3 AM about 200 international calls will wake you up.
Step 4: Build a Security Dashboard
Individual checks are useful, but a dashboard gives you a single view of PBX health and security.
What Your Dashboard Should Show
Real-time panel:
- —Active channels count (with after-hours highlighting)
- —Failed auth attempts (last hour, trending)
- —International/premium-rate call volume
- —Unusual destination countries
Daily summary:
- —Total calls vs. 30-day average
- —International call ratio
- —Top destinations (flag new countries)
- —Failed SIP registrations by source IP
- —Admin panel access log
Weekly audit:
- —Module versions vs. latest available
- —File integrity check (new/modified PHP files)
- —Fail2Ban block statistics
- —CDR anomaly trend
Using Astervis for PBX Security Monitoring
You can build all of this manually with cron scripts, custom SQL queries, and a Grafana instance. That's about 40 hours of setup, ongoing maintenance, and no mobile access.
Or you can install Astervis in 5 minutes and get:
- —Real-time CDR analytics - see every call as it happens, with automatic anomaly detection
- —30+ pre-built charts - including call volume trends, destination analysis, and after-hours activity
- —Operator tracking - know which extensions are generating unexpected traffic
- —Trunk monitoring - detect SIP trunk abuse before the bill arrives
- —Heatmaps - visualize call patterns and spot anomalies instantly
Astervis connects directly to your Asterisk CDR database. It's self-hosted (your data stays on your server), installs with one command, and gives you the monitoring visibility that could have prevented every compromised instance in the CVE-2025-64328 campaign.
-> Start your 14-day free trial
The Bigger Picture: Why PBX Security Monitoring Matters
CVE-2025-64328 won't be the last FreePBX vulnerability. Before it, there was CVE-2025-57819 (CVSS 10.0) - an unauthenticated admin access flaw exploited since August 2025. Before that, similar vulnerabilities in Elastix and older FreePBX versions.
The pattern is consistent:
- —Vulnerability disclosed
- —Patch released
- —Most admins don't apply the patch for weeks or months
- —Threat groups exploit the window
- —Admins discover the breach only when the phone bill arrives
The only thing that breaks this cycle is monitoring. If you have real-time visibility into your PBX activity, you detect anomalies within hours - not months. You see the spike in failed auth attempts before the attacker finds valid credentials. You see the first fraudulent international call before it becomes a thousand.
Security Checklist: FreePBX Hardening After CVE-2025-64328
Use this as your action plan:
- — Immediate: Check for web shells in
/var/www/html - — Immediate: Audit CDR for international calls you don't recognize
- — Immediate: Check for unauthorized cron jobs under the asterisk user
- — Today: Update Endpoint Manager to version 17.0.3+
- — Today: Restrict admin panel access to trusted IPs only
- — Today: Change all admin passwords (FreePBX, SSH, MySQL)
- — This week: Configure Fail2Ban for FreePBX and Asterisk
- — This week: Disable unused FreePBX modules
- — This week: Set up CDR anomaly alerts (script or monitoring tool)
- — This week: Enable Asterisk security logging
- — This week: Block international dialing by default in dialplan
- — Ongoing: Monitor CDR daily for volume and destination anomalies
- — Ongoing: Review Fail2Ban blocks weekly
- — Ongoing: Check for FreePBX module updates monthly
- — Ongoing: Run file integrity checks on the web root
Conclusion
900+ compromised FreePBX instances is not a statistic - it's 900+ organizations that lost control of their phone system. Some are still compromised right now, running web shells they don't know about, generating calls they'll pay for.
The fix isn't just patching CVE-2025-64328. It's changing the fundamental approach from "set up the PBX and forget it" to "monitor the PBX continuously." Every other piece of infrastructure in your network has monitoring - servers, networks, applications. Your PBX handles your company's phone calls. It deserves the same visibility.
Start with the checklist above. Check for compromise, patch, harden, and then set up monitoring that runs 24/7. Your phone bill - and your security team - will thank you.
Astervis provides real-time call center analytics for Asterisk-based PBX systems. Self-hosted, one-command install, 30+ charts, and the monitoring visibility your PBX needs. Try it free for 14 days - no credit card required.
Stop guessing. Start monitoring.
See your Asterisk call center's real performance — queue wait times, agent activity, trunk usage, and 30+ charts. Self-hosted on your server. Install in 5 minutes. No credit card required.
From $119/mo flat. Unlimited operators. 14-day free trial.
