
TP-Link Omada SSL VPN에서 OpenVPN 사용자 이름 인젝션을 통해 root 권한으로 임의 명령을 실행하는 인증되지 않은 명령 인젝션 취약점 CVE-2026-19586을 익스플로잇하는 Python PoC입니다.
TP-Link Omada SSL VPN 인증되지 않은 RCE (CVE-2026-19586)
TP-Link Omada 게이트웨이 펌웨어의 SSL VPN 인증 경로에 존재하는 명령 주입 취약점(CWE-78)으로, 인증되지 않은 공격자가 root 권한으로 임의 명령을 실행할 수 있습니다. OpenVPN 기반 SSL VPN 서버가 활성화되면, OpenVPN은 접속하는 클라이언트가 제출한 사용자 이름을 auth-user-pass-verify 지시문에 연결된 스크립트인 /usr/sbin/checkpsw.sh로 전달합니다. 해당 스크립트는 사용자 이름을 따옴표 없이 awk 프로그램에 삽입하기 때문에, 큰따옴표가 포함된 사용자 이름은 붙여넣어진 awk 문자열 리터럴을 닫아버리고 나머지 부분이 awk 소스로 파싱됩니다.
awk의 BEGIN 블록은 입력의 첫 번째 줄을 읽기 전에 한 번 실행되므로, 주입된 system() 호출은 제출된 비밀번호가 무엇과 비교되기도 전에 root 권한으로 실행됩니다.
이 서버는 클라이언트 인증서를 요구하지 않고 tls-auth 또는 tls-crypt 키도 사용하지 않으며, CA 인증서는 펌웨어 이미지에 하드코딩되어 있습니다. 이 저장소의 ca.crt가 바로 그 인증서이며, 영향을 받는 펌웨어를 실행하는 모든 장치에서 동일하므로, VPN 포트에 접근할 수 있는 공격자는 자격 증명이나 장치에 대한 사전 접근 없이도 TLS 핸드셰이크를 완료하고 주입 지점에 도달할 수 있습니다.
사용자 이름에는 리터럴 공백이 포함될 수 없습니다. 셸이 따옴표 없는 확장을 awk가 보기 전에 별도의 인수로 분리하기 때문입니다. 대신 ${IFS}를 사용하세요. system()에 의해 호출된 셸이 이를 다시 공백으로 확장합니다. OpenVPN은 사용자 이름을 128바이트로 제한하며, 페이로드 골격이 그중 22바이트를 사용하므로 명령을 위해 106바이트가 남습니다.
이 Proof of Concept(PoC)는 TP-Link Omada ER7212PC v2(펌웨어 6.1.0.19)를 대상으로 테스트되었습니다. 취약한 스크립트는 Omada 게이트웨이 라인 전반에 공유되며, 경로, 줄 번호, 동작은 다른 모델이나 펌웨어 버전에서 다를 수 있습니다.
이 PoC는 대상 장치에서 root 권한으로 실행되는 사용자 이름 페이로드를 전달합니다. 이 문제는 TP-Link에 보고되었으며 권고문에 나열된 펌웨어 버전에서 수정되었습니다. 본인이 소유하거나 명시적으로 테스트 권한을 부여받은 하드웨어에 대해서만 실행하세요.
$ sudo python3 cve-2026-19586.py <target> -c '<command>'
openvpn 클라이언트가 필요하며, tun 장치를 생성하기 위해 CAP_NET_ADMIN이 필요하므로 root 권한으로 실행해야 합니다. 이는 대상이 아닌 로컬 OpenVPN 클라이언트의 요구 사항입니다.
실행 예시:
$ sudo python3 cve-2026-19586.py 10.0.0.100 -c 'id>/tmp/proof'
TP-Link Omada SSL VPN Unauthenticated RCE (CVE-2026-19586) - OpenVPN Username Injection
Target : 10.0.0.100:1194/udp
CA cert : ca.crt
Command : id>/tmp/proof
Username : x";BEGIN{system("id>/tmp/proof")};#
[*] Running: openvpn --client --dev tun --proto udp --remote 10.0.0.100 1194 --resolv-retry 1 --nobind --ca ca.crt --remote-cert-tls server --cipher AES-256-CBC --data-ciphers-fallback AES-256-CBC --reneg-sec 0 --auth-user-pass /tmp/ovpn_creds_m0ycjowy.txt --auth-nocache --verb 3
[openvpn client output]
명령은 인증이 완료되기 전에 장치에서 실행되므로, OpenVPN 클라이언트 자체는 연결되지 않습니다. 인증 시도가 실패하고 클라이언트가 종료되는데, 이는 예상된 동작입니다.
| 인수 | 설명 |
|---|
target | 대상 장치 IP 또는 호스트 이름 |
-c, --command | 대상에서 root 권한으로 실행할 명령. 공백 대신 ${IFS}를 사용하세요 |
-p, --port | SSL VPN UDP 포트 (기본값: 1194) |
--ca | 펌웨어에서 추출한 CA 인증서 (기본값: ca.crt) |