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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2025-68621 — CVE-2025-68621에 대한 교육용 PoC 및 분석, Trilium Notes 동기화 로그인에 대한 타이밍 공격입니다. 네트워크 타이밍 사이드 채널을 통한 HMAC 해시 복구를 시연하며, 근본 원인, 수정 사항 및 완화 방법에 대한 세부 정보를 포함합니다. | Kitploit
도구/GitHubGitHub/sivaadityacoder/cve-2025-68621
Vulnerability AnalysisExploitationWeb SecurityCryptographyPapers & ResearchLearning & Education
GitHubsivaadityacoder/cve-2025-68621

CVE-2025-68621

CVE-2025-68621에 대한 교육용 PoC 및 분석, Trilium Notes 동기화 로그인에 대한 타이밍 공격입니다. 네트워크 타이밍 사이드 채널을 통한 HMAC 해시 복구를 시연하며, 근본 원인, 수정 사항 및 완화 방법에 대한 세부 정보를 포함합니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2025-68621 — Trilium Notes 타이밍 공격 on /api/login/sync

심각도: HIGH (CVSS 7.4) 영향받는 소프트웨어: TriliumNext/Trilium < 0.101.0 취약점 유형: CWE-208 – 관찰 가능한 타이밍 차이 수정 버전: Trilium 0.101.0 (PR #8129) 공개일: 2026-02-06 | 예약일: 2025-12-19


목차

  1. 내 접근 방식
  2. 근본 원인
  3. 영향
  4. 수정
  5. 핵심 시사점
  6. 타임라인
  7. 참고 자료

내 접근 방식

Trilium Notes란 무엇인가?

Trilium Notes는 대규모 개인 지식 기반 구축을 위해 설계된 오픈 소스, 크로스 플랫폼, 계층형 메모 애플리케이션입니다. 다음을 지원합니다:

  • 여러 클라이언트가 동기화할 수 있는 자체 호스팅 서버
  • 풍부한 노트 유형 (텍스트, 코드, 캔버스, 다이어그램)
  • 강력한 스크립팅 API

동기화 기능을 통해 Trilium 클라이언트가 Trilium 서버에 인증하여 노트를 여러 장치에서 동기화 상태로 유지합니다. 이 동기화 엔드포인트가 CVE-2025-68621의 진입점입니다.

타이밍 공격이란?

타이밍 공격은 공격자가 시스템이 다양한 입력을 처리하는 데 걸리는 시간을 측정하여 비밀 정보를 알아내는 부채널 공격입니다.

전형적인 예는 문자열 비교입니다:

root@kitploit:~
"correct_password" !== "aorrect_password"   → 0번째 위치에서 실패 → 빠름
"correct_password" !== "cXrrect_password"   → 1번째 위치에서 실패 → 약간 느림
"correct_password" !== "correct_password"   → 완전 일치 → 가장 느림

대부분의 프로그래밍 언어는 문자열을 문자별로 비교하고 불일치가 발견되는 즉시 중단합니다 (조기 종료). 즉:

  • 첫 번째 바이트가 일치하는 추측은 즉시 불일치하는 추측보다 약간 더 오래 걸립니다.
  • 수천 번의 추측을 보내고 응답 시간을 평균화함으로써 공격자는 통계적으로 어느 바이트가 올바른지 위치별로 결정하여 전체 비밀을 복구할 수 있습니다.

수정 방법은 불일치가 발생하는 위치와 관계없이 항상 모든 바이트를 검사하는 상수 시간 비교 함수를 사용하는 것입니다.

취약점 발견 방법

이 취약점은 Trilium의 인증 로직에 대한 수동 코드 검토를 통해 발견되었습니다. 연구원은 apps/server/src/routes/api/login.ts의 동기화 로그인 흐름을 살펴보고 loginSync() 함수(약 111번째 줄)에서 다음과 같은 패턴을 발견했습니다:

root@kitploit:~
const documentSecret = options.getOption("documentSecret");
const expectedHash   = utils.hmac(documentSecret, timestampStr);
const givenHash      = req.body.hash;

if (expectedHash !== givenHash) {          // ← 취약한 줄
    return [400, { message: "Sync login credentials are incorrect..." }];
}

위험 신호는 JavaScript의 기본 !== 연산자를 HMAC 해시 비교에 사용한다는 점입니다. !== 연산자는 상수 시간이 아닙니다 — 다른 문자를 발견하는 즉시 종료됩니다. 비교가 일반 문자열(암호학적으로 안전한 비교 함수 사용하지 않음)에서 이루어지기 때문에 응답 시간을 통해 공격자의 추측 중 몇 바이트가 올바른지에 대한 정보가 유출됩니다.

연구원은 다음과 같이 질문했습니다:

"이 작은 타이밍 차이를 네트워크를 통해 충분히 증폭시켜 전체 44자 Base64 인코딩 HMAC 해시를 복구할 수 있을까?"

답은 예였습니다 — 충분한 반복 측정과 통계 분석을 통해 신호가 노이즈 위로 올라옵니다.

공격 알고리즘

Trilium 클라이언트가 동기화하려면 다음과 같은 JSON 본문으로 POST /api/login/sync를 호출합니다:

root@kitploit:~
{
  "timestamp":   "2025-12-19T10:00:00.000Z",
  "syncVersion": 34,
  "hash":        "<HMAC-SHA256 of documentSecret + timestamp, Base64-encoded>"
}

바이트 단위 복구는 다음과 같이 작동합니다:

root@kitploit:~
For position = 0 to 43:
    For each candidate character c in charset (A-Z, a-z, 0-9, +, /, =):
        Send SAMPLES requests with hash = known_prefix + c + padding
        Record average response time
    Best character = candidate with highest average time
    Append best character to known_prefix

44회 반복(Base64 문자당 한 번) 후 전체 44자 HMAC 해시가 복구됩니다.

실제 요구 사항:

  • >100,000 총 HTTP 요청 (50개 샘플 × 65개 문자 집합 × 44개 위치 ≈ 143,000)
  • >1,000개의 다른 소스 IP 주소 (Trilium의 속도 제한으로 인해 프록시 로테이션 또는 봇넷 필요)
  • 공격자와 서버 간 낮은 네트워크 지터 (LAN 또는 안정적인 클라우드 연결이 가장 좋음)
  • 고정밀 타이머 (Python의 time.perf_counter()는 나노초 해상도 제공)

개념 증명

완전히 주석 처리된 Python PoC는 poc.py를 참조하세요.

PoC가 수행하는 작업에 대한 간략한 요약:

  1. HMAC 해시의 44개 Base64 문자 위치를 모두 반복합니다.
  2. 각 위치에 대해 Base64 문자 집합(A–Z, a–z, 0–9, +, /, =)의 모든 문자를 시도합니다.
  3. 각 후보에 대해 50개의 HTTP POST 요청을 /api/login/sync로 보내고 중간 응답 시간을 측정합니다.
  4. 중간 응답 시간이 가장 높은 후보를 올바른 문자로 선택합니다.
  5. 44개 문자를 모두 복구한 후 복구된 해시로 인증합니다.

면책 조항: 이 PoC는 교육 목적과 책임 있는 보안 연구를 위해서만 제공됩니다. 소유하지 않거나 명시적 서면 허가를 받지 않은 시스템에 대해 사용하지 마십시오.


근본 원인

JavaScript의 !== (그리고 ===) 연산자는 사전식, 조기 종료 비교를 수행합니다. apps/server/src/routes/api/login.ts의 취약한 줄:

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

조기 종료 동작으로 인해 일치하는 바이트당 측정 가능한 타이밍 차이가 발생합니다:

추측 대 예상비교된 바이트 수시간
0번째 바이트 오류1~T
0번째 바이트 정확, 1번째 바이트 오류2~T + δ
0-1번째 바이트 정확, 2번째 바이트 오류3~T + 2δ
………
44개 바이트 모두 정확44~T + 43δ

일치하는 바이트가 추가될 때마다 약간의 추가 CPU 시간 δ가 소모됩니다. 수천 개의 샘플을 통해 "올바른 바이트 N" 추측의 평균 응답 시간이 "잘못된 바이트 N" 추측보다 측정 가능하게 길어지며, 이는 전체 HMAC 해시를 한 문자씩 복구할 수 있을 만큼 정보를 유출합니다.

CVSS 점수 분석

지표값이유
기본 점수7.4 HIGH
공격 벡터Network (N)인터넷을 통해 악용 가능
공격 복잡성High (H)많은 요청 + 안정적인 타이밍 필요
필요한 권한None (N)계정 불필요
사용자 상호작용None (N)피해자가 아무것도 할 필요 없음
범위Unchanged (U)Trilium 서버만 영향받음
기밀성High (H)전체 노트 베이스 읽기 가능
무결성High (H)공격자가 노트 생성/수정 가능
가용성None (N)서비스 거부 요소 없음

벡터 문자열: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N


영향

성공적인 악용 시 공격자는 다음을 얻습니다:

  • 모든 노트에 대한 완전한 읽기 액세스, 암호화된 노트 메타데이터 포함
  • 완전한 쓰기 액세스 — 공격자가 노트를 생성, 수정 또는 삭제할 수 있음
  • 지속적 액세스 — 복구된 해시는 (타임스탬프 기간 내에서) 재사용 가능

이는 Trilium 지식 베이스에 민감한 개인 데이터(비밀번호, 개인 문서, 일기 항목)를 저장하는 사용자에게 특히 심각합니다.


수정

수정은 상수 시간이 아닌 !== 비교를 Node.js 내장 crypto.timingSafeEqual()로 대체합니다:

수정 전 (취약):

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

수정 후 (안전):

root@kitploit:~
import * as crypto from "crypto";

const expectedBuffer = Buffer.from(expectedHash);
const givenBuffer    = Buffer.from(givenHash ?? "");

if (expectedBuffer.length !== givenBuffer.length ||
    !crypto.timingSafeEqual(expectedBuffer, givenBuffer)) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

crypto.timingSafeEqual()는 항상 모든 바이트를 비교하므로 실행 시간이 일치하는 바이트 수에 의존하지 않습니다. 타이밍 신호가 사라집니다.

병렬 코드 예제는 vulnerable.ts와 fix.ts를 참조하세요.

업데이트 방법

자체 호스팅 Trilium 서버를 실행 중인 경우 즉시 버전 0.101.0 이상으로 업그레이드하십시오.

root@kitploit:~
# Docker 예제
docker pull zadam/trilium:0.101.0

핵심 시사점

  1. 비밀 비교에 === / !==를 절대 사용하지 마십시오. JavaScript의 동등 연산자는 상수 시간이 아닙니다. === / !==를 사용한 HMAC, 토큰 또는 비밀번호의 모든 비교는 잠재적인 타이밍 오라클입니다.

  2. Node.js에서는 항상 crypto.timingSafeEqual()을 사용하십시오 (또는 해당 언어/런타임의 동등한 함수). 이 작업을 위해 특별히 설계된 표준 API입니다.

  3. 타이밍 공격은 네트워크를 통해 실현 가능합니다. 나노초 차이가 인터넷을 통해 감지 불가능해 보일 수 있지만, 통계 기술과 충분한 샘플은 잡음이 많은 측정에서도 명확한 신호를 추출할 수 있습니다 — 특히 지터가 낮은 환경에서 더욱 그렇습니다.

  4. 속도 제한만으로는 충분한 완화책이 아닙니다. IP당 속도 제한이 있더라도 로테이팅 프록시나 봇넷에 접근할 수 있는 공격자는 타이밍 차이를 악용할 만큼 충분한 샘플을 축적할 수 있습니다.

  5. HMAC 검증은 비밀번호 비교와 동일한 주의를 기울여야 합니다. HMAC 해시는 비밀입니다. 비밀 값의 모든 비교는 타이밍 부채널이 악용될 수 있는 것으로 취급하십시오.

  6. 암호화 패턴에 대한 코드 검토는 필수입니다. 이 취약점은 수동 검토를 통해 발견되었습니다 — 단 한 줄의 코드가 무해해 보였지만 심각한 보안 영향을 가졌습니다. 전용 암호화/보안 감사는 이러한 문제를 조기에 발견하는 데 도움이 됩니다.


타임라인

날짜이벤트
2025-12-19CVE-2025-68621이 GitHub Security에 의해 예약됨
2025-12-21수정 PR #8129 열림
2025-12-25PR 병합; Trilium 0.101.0 출시
2026-02-06CVE 공개
2026-02-09CISA ADP 강화 추가됨

참고 자료

자료링크
GitHub Security AdvisoryGHSA-hxf6-58cx-qq3x
수정 Pull RequestTriliumNext/Trilium#8129
CVE 레코드 (CVEProject)CVE-2025-68621.json
CWE-208관찰 가능한 타이밍 불일치
Trilium Notes 저장소TriliumNext/Trilium

이 저장소는 책임 있는 공개 원칙에 따라 교육 및 연구 목적으로 유지됩니다.

도구 다운로드