Feb 10, 2026·5 min read·2 visits
The FroshPlatformAdminer plugin for Shopware (< 2.2.1) exposed the Adminer database management tool to unauthenticated users. The route was configured with `auth_required => false`, allowing anyone to access the database login UI. While database credentials were still required, this exposed critical infrastructure to brute-force attacks and potential Adminer-specific exploits.
A classic case of 'explicitly insecure configuration' found in the FroshPlatformAdminer plugin for Shopware. Developers explicitly disabled authentication checks on the primary Adminer route to make things 'easier', inadvertently exposing the entire database management interface to the public internet without a login prompt from the application.
Adminer is the darling of PHP developers everywhere. It's a single-file database management tool that is lighter than phpMyAdmin and arguably cleaner. Naturally, in the ecosystem of Shopware (a Symfony-based e-commerce platform), someone built a plugin to integrate it directly into the admin panel. Enter FroshPlatformAdminer.
Here is the premise: You are a Shopware administrator. You want to tweak a row in the database without opening an SSH tunnel or firing up a desktop client. You install this plugin, click a tab, and boom—you are in Adminer. It uses an iframe or a proxy to render the tool inside your existing session.
But here is the catch. To make this integration seamless, the developers had to bypass the standard Shopware authentication middleware for the specific route serving Adminer. Why? Likely because Adminer manages its own sessions, or the iframe context made passing the Shopware session token tricky. Regardless of the intent, the result was akin to installing a high-security steel door on your house but leaving the cat flap unlocked—and making the cat flap the size of a garage door.
This wasn't a complex buffer overflow or a subtle race condition. This was a logic error born from configuration. In Symfony (and by extension, Shopware), routes are guarded by attributes. You tell the framework who is allowed to go where.
The developers of FroshPlatformAdminer explicitly told Shopware to ignore authentication for the Adminer route. They didn't just forget to lock the door; they unscrewed the lock and put it in a drawer.
> [!NOTE]
> The Smoking Gun: The route definition explicitly included defaults: ['auth_required' => false].
When a request hit https://target.store/admin/adminer, the Shopware kernel looked at the route, saw the flag saying "No Auth Needed," and happily passed the request to the AdminerController. The controller assumed that if you made it this far, you must be trustworthy. It then immediately require'd the Adminer.php file, rendering the interface to the world.
Let's look at the code before the fix. This is from src/Controller/AdminerController.php. Note the Route attribute.
// VULNERABLE CODE (Pre-2.2.1)
#[Route(path: '/%shopware_administration.path_name%/adminer',
name: 'administration.frosh_adminer',
defaults: ['auth_required' => false, '_routeScope' => ['administration']],
methods: ['GET', 'POST'])]
public function index(): Response
{
chdir(__DIR__ . '/../Adminer');
unset($_POST['auth']);
// The gate is wide open here
require __DIR__ . '/../Adminer/Adminer.php';
return new Response('');
}There is zero logic inside index() to verify who the user is. It simply loads the Adminer script.
Now, let's look at the fix in commit c4dd6c3462af178b3a7d146d3c651c2c253e902b. The developers had to implement a "sidecar" session because they presumably couldn't use the main Shopware session easily within the Adminer context.
// PATCHED CODE (v2.2.1)
public function login(Request $request): JsonResponse
{
// This method IS protected by standard Shopware auth
// ... (checks context) ...
// Set a manual PHP session flag
$_SESSION['frosh_adminer_authenticated'] = true;
// ...
}
public function index(): Response
{
// Manually start the specific session
session_cache_limiter('');
session_name('adminer_sid');
session_start();
// The new gatekeeper
if (empty($_SESSION['frosh_adminer_authenticated'])) {
return new Response('Forbidden', Response::HTTP_FORBIDDEN);
}
chdir(__DIR__ . '/../Adminer');
// ... load Adminer ...
}They essentially built a custom checkpoint. You must first hit the login endpoint (which requires Shopware auth) to set a flag in a raw PHP session. Only then does the index method let you through.
Exploiting this is trivially easy. It requires no special tools, no packet manipulation, and no complex payload construction. It is a GET request.
Step 1: Reconnaissance
First, we need to know where the administration panel is. By default, Shopware uses /admin, but security-conscious admins often change this. However, if we assume the default:
curl -I https://victim-shopware.com/admin/adminerStep 2: Verification
If the server responds with HTTP/1.1 200 OK and headers indicating a PHP session or Adminer content, we win. We open that URL in a browser.
Step 3: Post-Access Attacks "But wait," you say, "You still need the database password!" Correct. This is not unauthenticated RCE yet. However, having access to the Adminer login interface allows for:
LOAD DATA LOCAL INFILE) or scan internal ports.While CVSS gives this a 6.9 (Medium), the real-world risk depends heavily on your database configuration.
If your database user has a weak password, this is a Critical vulnerability. It leads to full database compromise, customer data theft, and potential RCE (via SELECT ... INTO OUTFILE if file permissions allow).
If your database is restricted to localhost and you have strong passwords, the risk is lower—primarily Denial of Service (resource exhaustion on the login form) or SSRF if you allow outbound connections from the web server.
The primary failure here is the violation of defense-in-depth. The application layer explicitly opted out of security, leaving the database layer as the only line of defense.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
FroshPlatformAdminer FriendsOfShopware | < 2.2.1 | 2.2.1 |
| Attribute | Detail |
|---|---|
| CWE | CWE-306 (Missing Authentication) |
| CVSS v4.0 | 6.9 (Medium) |
| Attack Vector | Network (AV:N) |
| Privileges Required | None (PR:N) |
| User Interaction | None (UI:N) |
| Exploit Complexity | Low (AC:L) |
The software does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.