Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

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

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

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-5061 — Consul Template은 템플릿 평가 중 심볼릭 링크가 가리키는 위치를 검증했지만, 이후 의존성 페치(fetch)에서는 원래 경로를 읽었습니다. 두 작업 사이에 링크를 재지정함으로써 샌드박스 내부 파일 참조가 샌드박스 외부 파일 노출로 바뀌었습니다. | Kitploit
도구/GitHubGitHub/0xmrma/cve-2026-5061
Vulnerability AnalysisCode AnalysisExploitationData ExfiltrationLearning & Education
GitHub0xmrma/cve-2026-5061

CVE-2026-5061

Consul Template은 템플릿 평가 중 심볼릭 링크가 가리키는 위치를 검증했지만, 이후 의존성 페치(fetch)에서는 원래 경로를 읽었습니다. 두 작업 사이에 링크를 재지정함으로써 샌드박스 내부 파일 참조가 샌드박스 외부 파일 노출로 바뀌었습니다.

저장소 보기
131개월 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-5061

Consul Template는 템플릿 평가 중 심볼릭 링크가 가리키는 위치를 검증했지만, 이후 의존성 페치는 원래 경로를 읽었습니다. 두 작업 사이에 링크를 다시 지정하면 샌드박스 내부 파일 참조가 샌드박스 외부 파일 공개로 바뀌었습니다.

소개

저는 HashiCorp Consul Template를 검토하면서 아주 구체적인 보안 질문 하나를 염두에 두고 이 문제를 발견했습니다:

sandbox_path가 템플릿 평가 중 심볼릭 링크를 검증한다면, 이후의 파일 읽기는 그 검증된 동일한 대상에 바인딩된 상태로 유지될까요?

이 경우 답은 '아니요'였습니다.

file 템플릿 헬퍼는 경로를 해석하고 템플릿 평가 중 설정된 샌드박스를 적용했습니다. 하지만 그 검사 이후에는 원래의 원시 경로를 사용하여 파일 의존성을 생성했습니다.

그 의존성은 나중에 페치되었습니다.

공격자가 검증과 의존성 페치 사이의 틈에서 심볼릭 링크를 다시 지정하면, Consul Template는 샌드박스 외부 파일을 읽을 수 있었습니다. 링크가 다음 렌더링 전에 복원되면 샌드박스 검증이 다시 통과했고 캐시된 외부 콘텐츠가 여전히 렌더링되었습니다.

그 문제가 CVE-2026-5061이 되었습니다.

HashiCorp 공지: HCSEC-2026-12
IBM 공지: CVE-2026-5061 security bulletin
CVE: CVE-2026-5061
수정 버전: 0.42.0

photo0


공격 체인

attacker-controlled in-sandbox symlink -> sandbox validation resolves to safe target -> dependency stores original raw path -> attacker retargets link outside sandbox -> dependency fetch reads external file -> attacker restores safe link -> next validation passes -> cached external content is rendered


Consul Template의 역할

Consul Template는 Consul 및 Vault 데이터를 위한 템플릿 렌더링 도구입니다.

지속적으로 실행되고, 의존성의 변경을 감시하며, 데이터를 애플리케이션이 사용할 수 있도록 파일이나 환경 변수로 렌더링할 수 있습니다.

file 템플릿 헬퍼는 로컬 파일을 읽고 그 내용을 렌더링된 출력에 삽입합니다.

로컬 파일 읽기는 프로세스가 읽을 수 있는 비밀을 노출할 수 있기 때문에, Consul Template는 이 헬퍼의 경계로 sandbox_path를 제공합니다.

문서화된 보안 속성은 명확합니다:

  • file에 전달되는 경로는 설정된 샌드박스 안에 있어야 합니다
  • 상대 경로는 샌드박스를 벗어나면 안 됩니다
  • 링크된 대상은 허용된 경로를 외부 파일 읽기로 바꿔서는 안 됩니다

이로써 sandbox_path는 실제 보안 경계가 됩니다.

중요한 질문은 경로가 샌드박스 안에 있는 것처럼 보이는지가 아니었습니다.

진짜 질문은 다음과 같았습니다:

읽히는 파일이 샌드박스 검증을 통과한 바로 그 파일로 유지되는가?

취약한 버전에서는 그렇지 않았습니다.


이 공격 표면을 살펴볼 가치가 있던 이유

파일시스템 샌드박스는 경로 검증과 파일 접근 사이의 틈에서 자주 실패합니다.

일반적인 패턴은 다음과 같습니다:

  • 경로를 검증한다
  • 제어권을 파일시스템에 되돌려준다
  • 나중에 그 경로를 다시 사용한다
  • 여전히 동일한 객체를 가리킨다고 가정한다

공격자가 두 작업 사이에 심볼릭 링크 또는 이에 상응하는 파일시스템 리디렉션을 수정할 수 있다면 그 가정은 안전하지 않습니다.

Consul Template는 템플릿 평가와 의존성 페치가 별도의 단계였기 때문에 이 공격 표면을 특히 흥미롭게 만들었습니다.

그 분리는 올바른 보안 질문을 만들어냈습니다:

의존성 페치는 검증된 대상에 바인딩되어 있는가, 아니면 공격자가 제어하는 경로를 다시 해석하는가?

그것이 제가 집중한 경계였습니다.


근본 원인

근본 원인은 다음 사이의 TOCTOU(time-of-check to time-of-use) 불일치였습니다:

  • template/funcs.go의 샌드박스 검증
  • dependency/file.go의 이후 의존성 읽기

테스트한 리비전에서 fileFunc()는 다음과 같이 동작했습니다:

root@kitploit:~
normalized := strings.TrimSpace(s)
err := pathInSandbox(sandboxPath, normalized)
if err != nil {
    return "", err
}

d, err := dep.NewFileQuery(s)

검증 헬퍼는 포함 여부를 확인하기 전에 심볼릭 링크를 올바르게 해석했습니다:

root@kitploit:~
sandboxResolved, err := filepath.EvalSymlinks(filepath.Clean(sandbox))
targetResolved, err := filepath.EvalSymlinks(filepath.Clean(path))

rel, err := filepath.Rel(sandboxResolved, targetResolved)
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
    return fmt.Errorf("'%s' is outside of sandbox", path)
}

따라서 샌드박스 검사 자체는 해석된 대상을 이해하고 있었습니다.

하지만 그 해석된 대상은 버려졌습니다.

NewFileQuery()는 대신 원래 문자열을 저장했습니다:

root@kitploit:~
return &FileQuery{
    stopCh: make(chan struct{}, 1),
    path:   s,
}, nil

그런 다음 이후의 의존성 페치가 그 경로를 다시 읽었습니다:

root@kitploit:~
data, err := os.ReadFile(d.path)

그것이 전체 취약점입니다.

코드는 하나의 파일시스템 해석을 검사한 뒤, 나중에 다른 해석을 사용했습니다.

악용 가능한 이유

심볼릭 링크는 변경 가능하기 때문입니다.

공격자는 샌드박스 외부 대상을 pathInSandbox()를 직접 통과시킬 필요가 없습니다.

검증 이후 Fetch()가 읽기를 수행하기 전에, 이미 승인된 원시 경로가 해석되는 대상을 바꾸기만 하면 됩니다.

절차는 다음과 같습니다:

  • pathInSandbox() 중 링크가 안전한 파일로 해석됩니다
  • 검증이 성공합니다
  • FileQuery가 원시 링크 경로를 기록합니다
  • 링크가 외부 파일로 교체되거나 다시 지정됩니다
  • os.ReadFile(d.path)가 링크를 다시 해석합니다
  • 외부 파일이 읽힙니다
  • 페치된 값이 템플릿 브레인에 캐시됩니다
  • 다음 템플릿 평가 전에 링크가 복원됩니다
  • 검증이 다시 성공합니다
  • 캐시된 외부 콘텐츠가 반환되고 렌더링됩니다

마지막 단계가 중요합니다.

안전한 링크를 복원해도 이미 페치된 비밀은 의존성 캐시에서 제거되지 않았습니다.


단순한 파일시스템 경쟁 조건이 아니라 보안 문제인 이유

중요한 차이는 명시적 보안 통제의 우회입니다.

이것은 단순히 다음과 같은 것이 아니었습니다:

"Consul Template가 파일을 감시하는 동안 파일이 변경되었다"

파일 변경을 감시하는 것은 예상된 동작입니다.

실제 문제는 다음과 같습니다:

문서화된 샌드박스 제한을 통과한 경로가 나중에 그 샌드박스 외부의 파일을 읽는 데 사용될 수 있다

이것은 직접적인 신뢰 경계 실패입니다.

애플리케이션은 이미 보안 결정을 내렸습니다:

  • 이 대상은 샌드박스 안에 있다
  • 따라서 등록하고 페치해도 안전하다

하지만 이후의 페치는 그 결정을 정당화한 대상에 연결되어 있지 않았습니다.

그것이 평범한 파일시스템 가변성을 취약점으로 바꾼 것입니다.


개념 증명(PoC)

저는 정확한 평가 및 의존성 페치 시퀀스를 중심으로 독립형 재현기를 구축했습니다.

통제된 구성은 다음을 사용했습니다:

  • 설정된 샌드박스 디렉터리
  • 샌드박스 안의 안전한 파일
  • 샌드박스 외부의 비밀 파일
  • 샌드박스 안의 감시 대상 심볼릭 링크 경로
  • 의존성 페치 시점의 결정적 링크 교체

재현 흐름은 다음과 같습니다:

  1. 감시 대상 심볼릭 링크를 샌드박스 안의 안전한 파일로 지정합니다.
  2. file 헬퍼를 평가하여 샌드박스 검증이 성공하고 원시 경로가 의존성으로 등록되게 합니다.
  3. 의존성 페치 전에 감시 대상 심볼릭 링크를 외부 비밀 파일로 다시 지정합니다.
  4. 의존성 페치를 실행하여 os.ReadFile(d.path)가 리디렉션된 링크를 통해 읽게 합니다.
  5. 페치된 값을 템플릿 캐시에 저장합니다.
  6. 심볼릭 링크를 샌드박스 안의 안전한 파일로 복원합니다.
  7. 템플릿을 다시 평가합니다.
  8. 샌드박스 검증이 여전히 성공하는지 확인합니다.
  9. 렌더링된 출력에 이전에 페치된 외부 비밀이 포함되어 있는지 확인합니다.

관찰된 동작은 다음과 같습니다:

  • 초기 샌드박스 검증이 통과했습니다
  • 의존성이 원래 링크 경로를 유지했습니다
  • 링크가 변경된 후 페치가 샌드박스 외부 파일을 읽었습니다
  • 다음 렌더링 전에 안전한 대상이 복원되었습니다
  • 다음 샌드박스 검사가 통과했습니다
  • 렌더링된 출력이 SHA-256 기준으로 외부 비밀과 정확히 일치했습니다

그 해시 비교가 중요했습니다.

최종 렌더링 값이 오래된 안전 콘텐츠, 파일 이름 아티팩트, 또는 오류 경로 부작용이 아님을 증명했습니다.

그것은 샌드박스 외부 파일의 바이트 단위 정확한 내용이었습니다.


PoC를 이렇게 구성한 이유

TOCTOU 문제에 대한 가장 강력한 증명은 타임라인을 통제해야 합니다.

심볼릭 링크가 샌드박스 외부를 가리킬 수 있다는 것을 단순히 보여주는 것은 더 약한 증명입니다. pathInSandbox()는 외부 대상을 관찰하면 이미 거부했기 때문입니다.

보안 주장은 다음 상태를 순서대로 모두 증명하는 데 의존했습니다:

  • 검증 시점에 안전
  • 페치 시점에 안전하지 않음
  • 렌더링 시점에 다시 안전
  • 외부 콘텐츠가 여전히 캐시에서 소비됨

그래서 재현기는 템플릿 검증, 의존성 페치, 링크 복원, 그리고 다음 렌더링을 명시적으로 분리했습니다.

PoC는 무작위 타이밍이나 반복적인 추측에 의존하지 않았습니다.

취약한 수명 주기를 결정적으로 구동했습니다.

그 덕분에 근본 원인과 영향을 훨씬 더 쉽게 입증할 수 있었습니다.


악용 요구 사항 및 범위

이 문제는 로컬 파일시스템에 대한 영향력을 요구합니다.

공격자는 취약한 시간 창 동안 관련 심볼릭 링크 또는 이에 상응하는 연결 경로를 생성, 교체, 또는 다시 지정할 수 있는 충분한 접근 권한이 필요합니다.

Consul Template 프로세스는 또한 다음을 충족해야 합니다:

  • 외부 대상을 읽을 권한이 있어야 합니다
  • 공격자의 영향을 받은 경로를 사용하는 템플릿을 평가해야 합니다
  • 렌더링된 결과를 공격자가 회수하거나 그 사용에 영향을 줄 수 있는 곳에 노출해야 합니다

이러한 요구 사항은 중요합니다.

이것은 기본 배포에서 인증 없이 원격으로 임의 파일을 읽을 수 있는 취약점이 아니었습니다.

하지만 영향을 받는 로컬 신뢰 모델 내에서 그 영향은 실질적이었습니다:

  • 문서화된 sandbox_path 제한 우회
  • 샌드박스 외부 로컬 파일 공개
  • Consul Template 프로세스가 읽을 수 있는 비밀 노출 가능성

프로세스가 민감한 자격 증명, 서비스 구성, 토큰 또는 개인 키에 접근할 수 있는 상태로 실행되면 위험이 증가합니다.


심각도 및 분류

HashiCorp는 이 문제를 다음과 같이 분류했습니다:

  • CWE-59: 파일 접근 전 부적절한 링크 해석
  • CVSS 3.1:
root@kitploit:~
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N

게시된 기본 점수는 다음과 같습니다:

root@kitploit:~
4.7 / Medium

이 점수는 실제 제약 조건을 반영합니다:

  • 로컬 공격 벡터
  • 경로에 영향을 주는 데 필요한 낮은 권한
  • 관련 수명 주기 창 동안 링크가 변경되어야 하므로 높은 공격 복잡성
  • 피해자 상호 작용 불필요
  • 민감한 프로세스 읽기 가능 파일이 페치되면 높은 기밀성 영향

이는 합리적인 분류입니다.

이 문제는 공격자 전제 조건이 좁지만, 샌드박스 우회와 그로 인한 파일 공개는 모두 구체적입니다.


영향을 받는 버전

HashiCorp 공지에는 다음과 같이 나열되어 있습니다:

root@kitploit:~
Affected: consul-template up to 0.41.4
Fixed:    consul-template 0.42.0

수정은 2026년 4월 15일 0.42.0 릴리스에 포함되었습니다.


수정 분석

수정은 작았고 깨진 바인딩을 직접 해결했습니다.

패치된 코드는 해석된 대상을 검증한 다음 원시 입력에서 의존성을 만드는 대신, 해석된 경로를 반환하고 그 경로를 NewFileQuery()에 전달합니다:

root@kitploit:~
resolvedPath, err := resolveSandboxedPath(
    sandboxPath,
    strings.TrimSpace(s),
)
if err != nil {
    return "", err
}

d, err := dep.NewFileQuery(resolvedPath)

보안 속성은 다음에서:

  • 해석된 대상 검증
  • 해석된 대상 폐기
  • 나중에 원시 경로를 통한 페치

다음으로 변경되었습니다:

  • 해석된 대상 검증
  • 해석된 대상 유지
  • 검증된 경로를 통한 페치

이는 보고된 심볼릭 링크 재지정 경로를 차단합니다. 원래 링크를 변경해도 의존성이 저장한 경로가 더 이상 변경되지 않기 때문입니다.

패치는 또한 정확한 시퀀스를 다루는 집중된 회귀 테스트를 추가했습니다:

  • 검증 중 안전한 심볼릭 링크
  • 페치 중 외부 심볼릭 링크
  • 다음 호출 전에 복원된 안전한 심볼릭 링크
  • 캐시된 외부 비밀이 반환되지 않아야 함

이것이 이런 버그에 대해 원하는 유형의 수정입니다:

  • 깨진 검증/사용 바인딩 수정
  • 샌드박스 동작 유지
  • 전체 경쟁 수명 주기에 대한 회귀 테스트 추가

공개

저는 2026년 3월 20일에 이 문제를 HashiCorp 보안팀에 비공개로 보고했습니다.

보고서에는 다음이 포함되었습니다:

  • 소스 수준 근본 원인 분석
  • 검증에서 페치까지의 TOCTOU 시퀀스
  • 독립형 결정적 재현기
  • 런타임 출력
  • 렌더링된 데이터가 외부 비밀과 일치함을 보여주는 SHA-256 증거
  • 영향을 받는 리비전 세부 정보

HashiCorp는 0.42.0에서 문제를 수정하고 2026년 5월 12일에 HCSEC-2026-12를 공개했습니다.

IBM은 동일한 CVE에 대한 대응 보안 공지를 게시했습니다.

두 공식 공지 모두 보고자를 다음과 같이 인정했습니다:

Mohamed Abdelaal (0xmrma)


이 버그가 실제로 가르쳐 주는 것

핵심 교훈은 간단합니다:

이후의 파일 작업이 그 경로를 다른 객체로 해석할 수 있다면, 경로를 검증하는 것만으로는 충분하지 않습니다

이 규칙은 Consul Template를 훨씬 넘어 적용됩니다.

다음을 수행하는 모든 코드에서 중요합니다:

  • 샌드박스 검사
  • 업로드 대상 검사
  • 아카이브 추출
  • 로컬 비밀 읽기
  • 임시 파일 처리
  • 권한 분리 파일 작업

더 깊은 보안 속성은 다음과 같은 것이 아닙니다:

"경로 문자열이 한때 안전해 보였다"

그것은 다음과 같습니다:

민감한 작업에 사용되는 객체는 검증을 통과한 객체여야 한다

이 경우 Consul Template는 하나의 해석을 검증하고 다른 해석을 페치했습니다.

그 틈만으로 충분했습니다.


핵심 요점

  • sandbox_path는 명시적인 로컬 파일 보안 경계였습니다
  • pathInSandbox()는 심볼릭 링크 대상을 올바르게 해석하고 검증했습니다
  • 해석된 대상은 검증 후 폐기되었습니다
  • FileQuery는 공격자의 영향을 받은 원래 경로를 유지했습니다
  • 이후 의존성 페치가 os.ReadFile을 통해 그 경로를 다시 해석했습니다
  • 안전한 링크를 복원해도 이미 캐시된 외부 콘텐츠는 제거되지 않았습니다
  • PoC는 SHA-256으로 바이트 단위 정확한 샌드박스 외부 공개를 증명했습니다
  • 0.42.0 버전은 의존성을 해석되고 검증된 경로에 바인딩하여 버그를 수정했습니다

마지막 말

이 취약점은 문자열 접두사 검사를 우회하는 문제가 아니었습니다.

시간과 정체성에 관한 문제였습니다.

Consul Template는 템플릿 평가 중 링크가 가리키는 위치를 확인했습니다. 이후 의존성 페치는 파일시스템에 같은 질문을 다시 던졌습니다. 공격자는 그 두 순간 사이에 답을 바꿀 수 있었습니다.

그것이 이것이 CVE-2026-5061이 된 이유입니다.

consul-template 0.42.0에서 수정되었습니다.

도구 다운로드