FreePBX15 - JUBAVOIP Malware (ajax.php & juba.php)

Last week I noticed some “new” files in my html root folder which looked suspicuos.

I opened the file in a text editor and noticed they were base64encoded, after which i was sure this is malware. I used ChatGPT to analyse and fix the issue. Below is a summary written by ChatGPT on how we fixed the error.

The 2 files that I noticed were ajax.php and jubba.php in the /var/www/html folder.

I’m running a fully up to date Official Distro of FreePBX 15 running Asterisk 13.83.3

In addition to whats written below, I found an “administrator” user called MagicJuba as well - which i obviously went ahead and deleted. Haven’t found anything else yet.

Didn’t find anything under “Asterisk Manager Users”, neither any new extensions or anything under “User Management”

Wondering what else should I do in order to make sure my system isn’t compromised. I do plan to migrate to either FreePBX 16 or 17 during the next few months for security.

Also should i share the malicous files here? I did save 2 of them in order to figure out what they were up to.

Here’s the heading for one of the pages

THEY CALL ME JUBAVOIP 2025 :)


Malware cleanup notes: ajax.php keeps reappearing (FreePBX)

Symptoms

  • Malicious ajax.php reappeared after deletion in these paths:

    • /var/www/html/ajax.php

    • /var/www/html/admin/modules/ajax.php

    • /var/www/html/admin/modules/core/ajax.php


1) Verify if core OS binaries were tampered

In our case rpm -V showed mismatches like S.5…T. for coreutils files (example: /usr/bin/ls, /usr/bin/cp, /usr/bin/cat).

rpm -V coreutils | head -n 200
rpm -qf /usr/bin/ls
sha256sum /usr/bin/ls /bin/ls

Fix: reinstall coreutils (and any other packages that show verification issues)

yum -y reinstall coreutils
rpm -V coreutils | head -n 50   # should return nothing for coreutils now

We also reinstalled a few “high risk / commonly targeted” packages to be safe:

yum -y reinstall coreutils bash openssh-server openssh-clients php httpd sudo util-linux

(Then optionally) run a broader check:

rpm -Va > /root/rpm-verify.txt
egrep '^\S' /root/rpm-verify.txt | head -n 200

2) Stop the process that was restoring the malware

For us, it was incrond doing filesystem-triggered restores (not Apache, not FreePBX, not cron).

systemctl stop httpd
systemctl stop incrond

3) Watch file recreation (optional but recommended)

Use auditd to log who recreates files if they come back:

auditctl -D
auditctl -w /var/www/html -p wa -k WWW_W
auditctl -w /var/www/html/admin/modules -p wa -k MOD_W
auditctl -w /var/www/html/admin/modules/core -p wa -k CORE_W

4) Delete the malicious files and confirm they don’t return

rm -f /var/www/html/ajax.php \
      /var/www/html/admin/modules/ajax.php \
      /var/www/html/admin/modules/core/ajax.php

for i in {1..120}; do
  if [[ -e /var/www/html/ajax.php || -e /var/www/html/admin/modules/ajax.php || -e /var/www/html/admin/modules/core/ajax.php ]]; then
    echo "REAPPEARED at second $i"
    break
  fi
  sleep 1
done

If they stop reappearing once incrond is stopped, you’ve likely broken persistence.


5) Identify / disable the incron rule (if applicable)

Check incron rules, especially anything that watches Asterisk/FreePBX dirs and executes a helper:

ls -la /etc/incron.d /etc/incron.*
grep -RIn "incron\|IN_" /etc/incron* /etc/incron.d 2>/dev/null

If you find a rule that triggers restores, disable incrond until you fully verify the system:

systemctl disable incrond

Outcome

  • After reinstalling tampered RPM packages and stopping incrond (the persistence mechanism), the malicious ajax.php files stopped reappearing and stayed gone.

Additional Findings & Cleanup Steps (Important)

This malware was not being recreated by Apache, FreePBX, cron, or systemd services.

1) Persistence via incrond

The malicious files (ajax.php, juba.php, etc.) were being silently recreated by incrond.

Stopping incrond immediately stopped the reappearance of the files:

systemctl stop incrond
systemctl disable incrond

Anyone facing recurring file re-creation should check incrond explicitly, as it may be enabled without being obvious.


2) Auditd showed ls – not a trojan

During investigation, auditd logs showed ls as the process “creating” the file.

This was not a trojaned ls.

Explanation:

  • The file was recreated between filesystem events

  • ls appeared in audit logs because it was stat’ing the file, not writing it

This was confirmed by verifying and reinstalling coreutils.


3) System binaries were verified and reinstalled

RPM verification showed modified system binaries and configs.

All affected packages were verified and reinstalled, including (but not limited to):

  • coreutils

  • bash

  • php

  • httpd

  • openssh-server

  • openssh-clients

  • sudo

Verification process:

rpm -Va > /root/rpm-verify.txt
egrep '^\S' /root/rpm-verify.txt
yum -y reinstall coreutils bash php httpd openssh-server openssh-clients sudo

After reinstalling, RPM verification returned clean for system binaries.


4) FreePBX admin account compromise

In addition to filesystem persistence, I found a malicious FreePBX administrator account named MagicJuba, which was deleted.

Anyone dealing with this malware should:

  • Audit FreePBX Admin users

  • Remove unknown or suspicious accounts immediately


5) FreePBX-only fixes are not sufficient

Reinstalling FreePBX modules or running fwconsole reload does not remove this malware.

The persistence mechanism operates at the OS level, not within FreePBX itself.


Summary

To fully clean this infection:

  1. Stop and disable incrond

  2. Remove malicious PHP files

  3. Audit and remove malicious FreePBX admin users

  4. Verify all system binaries with RPM

  5. Reinstall modified OS packages

  6. Confirm files do not reappear over time

Follow-up: juba user with UID 0 (root equivalent)

One additional finding worth calling out separately:

I discovered a local Linux user named juba that was assigned UID 0, making it effectively equivalent to the root account:

juba:x:0:0::/home/juba:/bin/bash

Because it shared UID 0, the user:

  • Could not be removed or modified normally (userdel / usermod failed)

  • Appeared “in use by process 1”

  • Had full root privileges

No persistence mechanism or active malware was tied to this user, but any non-root account with UID 0 is a serious security risk and should be addressed immediately.


Minimal Fix Strategy

Immediate containment

passwd -l juba
usermod -s /sbin/nologin juba

\Permanent cleanup (after maintenance window / reboot)

  • Either change the user to a non-privileged UID/GID

  • Or remove it entirely if not required

Example:

userdel -r juba

(Only after confirming no running processes rely on it.)


In our case, the juba UID-0 user was fully removed by manually deleting its entries from /etc/passwd, /etc/shadow, and /etc/group, followed by a daemon re-exec and service restarts.

Did you see the :spiral_calendar: Courtesy Reminder that FreePBX v15 is EOL Starting 1 October 2025 ?

From your nice write-up :slight_smile: it looks pretty nasty, so checking that you hold on to back-ups saved externally from before the infection is probably wise.

:+1: why wait ?

No, please don’t, but good question, as this is currently not explicitly covered in the FAQ, although there is a clause about posting stuff that is not your own that includes some legalese on not breaking laws, etc. Generally, it does seem reasonable that the forums should not be used to distribute malware. To aid users in scanning their systems for infection, it is sufficient to post the hashes of the sick files. (As an aside, we offer a pastebin.freepbx.org as well, in case you have curious logs to share.)

1 Like

I did read the EOL noticed, been busy so havent had the time plus was (falsely) worried about loosing my integrations due to a change in AMI

Estou com esse problema por aqui no meu FreePBX 17.

Porem, no meu caso, o malware criou dezenas de usuários root.

[root@freepbx ~]# getent passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
asterisk:x:999:1000::/home/asterisk:/bin/bash
tcpdump:x:72:72::/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:998:998:User for polkitd:/:/sbin/nologin
openvpn:x:997:997:OpenVPN:/etc/openvpn:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
unbound:x:996:996:Unbound DNS resolver:/etc/unbound:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mongodb:x:184:994:MongoDB Database Server:/var/lib/mongodb:/sbin/nologin
chrony:x:995:992::/var/lib/chrony:/sbin/nologin
redis:x:994:991:Redis Database Server:/var/lib/redis:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
radiusd:x:95:95:radiusd user:/var/lib/radiusd:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
saslauth:x:993:76:Saslauthd user:/run/saslauthd:/sbin/nologin
haproxy:x:188:188::/var/lib/haproxy:/sbin/nologin
newfpbx:x:0:0::/home/newfpbx:/bin/bash
cmoamz:x:0:0::/home/cmoamz:/bin/bash
tpmulb:x:0:0::/home/tpmulb:/bin/bash
centos:x:0:0::/dev/null:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:x:0:0::/dev/null:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:x:0:0::/dev/null:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:x:0:0::/dev/null:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:x:0:0::/dev/null:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:x:0:0::/dev/null:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
gcznpq:x:0:0::/home/gcznpq:/bin/bash
otcdsz:x:0:0::/home/otcdsz:/bin/bash
vsrboj:x:0:0::/home/vsrboj:/bin/bash
xgurcl:x:0:0::/home/xgurcl:/bin/bash
nhwocx:x:0:0::/home/nhwocx:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
klbrwf:x:0:0::/home/klbrwf:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
qtyycq:x:0:0::/home/qtyycq:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
ltokxx:x:0:0::/home/ltokxx:/bin/bash
centos:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
admin:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
support:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
issabel:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
sangoma:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash
emo:jH3MqYYmrpM55P.AWD2U1:0:0:root:/root:/bin/bash

Alguem tem ideia se é possível excluir esses usuários? Estou com receio de remover e as aplicações pararem.