FreePBX is a web-based GUI for managing the Asterisk VoIP phone system. The application is easily set up on a local network and is built on PHP. The ability to access this would result in the interception/stealing of phone calls, voicemails, etc.
In August 2025, a FreePBX user started getting strange error messages in their access logs. A day later, a user found a file called .clean.sh on their box that was cleaning up after an exploit. This is a serious problem! This clearly indicated a remote code execution vulnerability. The WatchTower team had previously reported a post-auth RCE bug to the developers, who didn't care. This time they did. Why?
This appeared to be an unauthenticated RCE vulnerability. Upon reviewing the vulnerability summary, it had to do with bad input validation. Command injection? SQL injection? Still not sure. But, they had a clue to go off of - the issue was in the Endpoint module. This was a plugin for FreePBX that simplified many aspects of the provisioning and management process.
At first, they were looking for SSRFs because requests made from localhost bypassed authentication, but this did not work. After trying to call various modules with a single quote in the parameter, they were greeted with a nice SQL error! This led to a SQL injection that was obviously quite bad. This was still post auth though.
Out of curiosity for the attacker, they set up a honeypot. After waiting for a little bit, a shiny new backdoor appeared on the system! This was calling /admin/ajax.php without authentication. But how?
FreePBX contains a module/extension system to add to your PBX instance. To do this, the module parameter alongside the command is used for routing. Using reflection logic, it will determine if a class exists via class_exists in PHP. This will attempt to load a custom class from risk, in the case of a local system like this.
In the custom PHP autoloader implementation, the function fpbx_framework_autoloader attempts to load the code. This will do some black magic to find the proper file to execute. In practice, this code allows for the execution of any PHP file with the appropriate part of an install. Specifying the module as FreePBX\\modules\\Endpoint\\install results in the install command to run, for instance.
With the authentication bypass, it's not possible to exploit the SQL injection to gain access to the device! This results in a complete authentication bypass for some modules. In the patch, it was only the SQL injection that was fixed and not the authentication issue. This is a design-level issue that likely requires significant effort to resolve.