Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All product data public available via API #3786

Closed
PaulBoss opened this issue Mar 15, 2016 · 12 comments
Closed

All product data public available via API #3786

PaulBoss opened this issue Mar 15, 2016 · 12 comments
Assignees
Labels
bug report Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development

Comments

@PaulBoss
Copy link

Steps to reproduce

  1. Install Magento from develop branch.
  2. Enable an integration
  3. Use the following URL in your browser: http:///rest/V1/products?searchCriteria[pageSize]=10

Expected result

  1. Authentication failed

Actual result

  1. A reply with 10 products listed.
    screenshot from 2016-03-15 12 15 01
@vzabaznov vzabaznov added the MX label Mar 15, 2016
@fvschie
Copy link

fvschie commented Mar 15, 2016

Confirmed. Also shows hidden products, including future promotion prices and periods.

@gwillem
Copy link
Contributor

gwillem commented Mar 15, 2016

Here's the full list of API methods for a standard install. Most seem to be behind ACL, except for products, storeConfigs etc.

@PaulBoss
Copy link
Author

Here's a command to find all the endpoints which can be accessed without authentifcation: find . -name webapi.xml | xargs -i grep -B4 anonymous {} | grep url

Which results in this for a standard install:

<route url="/V1/store/storeViews" method="GET">
    <route url="/V1/store/storeGroups" method="GET">
    <route url="/V1/store/websites" method="GET">
    <route url="/V1/store/storeConfigs" method="GET">
    <route url="/V1/guest-carts/:cartId/gift-message" method="GET">
    <route url="/V1/guest-carts/:cartId/gift-message/:itemId" method="GET">
    <route url="/V1/guest-carts/:cartId/gift-message" method="POST">
    <route url="/V1/guest-carts/:cartId/gift-message/:itemId" method="POST">
    <route url="/V1/guest-carts/:cartId" method="GET">
    <route url="/V1/guest-carts" method="POST">
    <route url="/V1/guest-carts/:cartId" method="PUT">
    <route url="/V1/guest-carts/:cartId/order" method="PUT">
    <route url="/V1/guest-carts/:cartId/shipping-methods" method="GET">
    <route url="/V1/guest-carts/:cartId/estimate-shipping-methods" method="POST">
    <route url="/V1/guest-carts/:cartId/items" method="GET">
    <route url="/V1/guest-carts/:cartId/items" method="POST">
    <route url="/V1/guest-carts/:cartId/items/:itemId" method="PUT">
    <route url="/V1/guest-carts/:cartId/items/:itemId" method="DELETE">
    <route url="/V1/guest-carts/:cartId/selected-payment-method" method="GET">
    <route url="/V1/guest-carts/:cartId/selected-payment-method" method="PUT">
    <route url="/V1/guest-carts/:cartId/payment-methods" method="GET">
    <route url="/V1/guest-carts/:cartId/billing-address" method="GET">
    <route url="/V1/guest-carts/:cartId/billing-address" method="POST">
    <route url="/V1/guest-carts/:cartId/coupons" method="GET">
    <route url="/V1/guest-carts/:cartId/coupons/:couponCode" method="PUT">
    <route url="/V1/guest-carts/:cartId/coupons" method="DELETE">
    <route url="/V1/guest-carts/:cartId/collect-totals" method="PUT">
    <route url="/V1/guest-carts/:cartId/totals" method="GET">
    <route url="/V1/search" method="GET">
    <route url="/V1/customers" method="POST">
    <route url="/V1/customers/:customerId/password/resetLinkToken/:resetPasswordLinkToken" method="GET">
    <route url="/V1/customers/password" method="PUT">
    <route url="/V1/customers/isEmailAvailable" method="POST">
    <route url="/V1/configurable-products/:sku/children" method="GET">
    <route url="/V1/configurable-products/:sku/options/:id" method="GET">
    <route url="/V1/configurable-products/:sku/options/all" method="GET">
    <route url="/V1/guest-carts/:cartId/shipping-information" method="POST">
    <route url="/V1/guest-carts/:cartId/totals-information" method="POST">
    <route url="/V1/guest-carts/:cartId/payment-information" method="POST">
    <route url="/V1/guest-carts/:cartId/payment-information" method="GET">
    <route url="/V1/guest-carts/:cartId/set-payment-information" method="POST">
    <route url="/V1/integration/admin/token" method="POST">
    <route url="/V1/integration/customer/token" method="POST">
    <route method="GET" url="/V1/testmodule1/resource1/:itemId">
    <route url="/V1/products" method="GET">
    <route url="/V1/products/:sku" method="GET">
    <route url="/V1/products/attributes/:attributeCode" method="GET">
    <route url="/V1/products/types" method="GET">
    <route url="/V1/products/attribute-sets/sets/list" method="GET">
    <route url="/V1/products/attribute-sets/:attributeSetId" method="GET">
    <route url="/V1/products/attribute-sets/:attributeSetId/attributes" method="GET">
    <route url="/V1/products/attribute-sets/groups/list" method="GET">
    <route url="/V1/products/attributes/:attributeCode/options" method="GET">
    <route url="/V1/products/media/types/:attributeSetName" method="GET">
    <route url="/V1/products/:sku/media/:entryId" method="GET">
    <route url="/V1/products/:sku/media" method="GET">
    <route url="/V1/products/:sku/group-prices/:customerGroupId/tiers" method="GET">
    <route url="/V1/categories/:categoryId" method="GET">
    <route url="/V1/categories" method="GET">
    <route url="/V1/products/:sku/options" method="GET">
    <route url="/V1/products/:sku/options/:optionId" method="GET">
    <route url="/V1/products/links/types" method="GET">
    <route url="/V1/products/links/:type/attributes" method="GET">
    <route url="/V1/products/:sku/links/:type" method="GET">
    <route url="/V1/categories/:categoryId/products" method="GET">
    <route url="/V1/directory/currency" method="GET">
    <route url="/V1/directory/countries" method="GET">
    <route url="/V1/directory/countries/:countryId" method="GET">
    <route url="/V1/stockStatuses/:productSku" method="GET">

So in short:

  • All websites, storegroups, stores and store configuration
  • All products (including offline/disabled products, pricing info, special pricing rules, stock information and configuration (!), special pricing info per customer group, etc, e.g. ALL product information, which is a lot more then what is normally visible on the site)
  • Possible to bruteforce admin users & passwords via /V1/integration/admin/token (so the random generated admin URL is pretty mood for this case..) (this call is not rate limited)
  • The brute forcing is also possible for registered customers via /V1/integration/customer/token

Or am I being too pessimistic here?

@fvschie
Copy link

fvschie commented Mar 17, 2016

Pretty major security problem, not assigned yet. Any update?

@sshrewz
Copy link

sshrewz commented Mar 17, 2016

Thanks for reporting this issue. We have created MAGETWO-50611 and MAGETWO-50608 tickets internally.

@sshrewz sshrewz added the Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development label Mar 17, 2016
@PaulBoss
Copy link
Author

I see the issues are fixed in CE 2.0.3. Thank you for fixing this in a relative short time span.

@KrystynaKabannyk
Copy link

Hello @PaulBoss, yes, as you see the issue is fixed now. Thanks for finding and reporting the issue!

@prasanthsd
Copy link

So if im building a mobile app how do I list the products/categories on my app. What API so I use as a anonymous user or a customer?

@mackelito
Copy link

Would love to open up this discussion again.
I see no reason for the use of any kind of auth for a eg. React/Angular application as long as the default api delivers the same data as expected on a "default store". eg the data I see when loading a productpage with Luma.

@PaulBoss
Copy link
Author

It is easy to create a plugin with your own API endpoints directly based on the API endpoints that are available. This way you can make these non authenticated and only return the information your app needs. You can never know in advance for every Magento store ever which information is publicly accessible. So opening this up be default is never a good idea.

@prasanthsd
Copy link

"You can never know in advance for every Magento store ever which information is publicly accessible." Why is that? I guess any ecommerce platform has control over what is displayed on the frontend store. The same rules cant be applied on the API?

@PaulBoss
Copy link
Author

The same rules can be applied to the API, ofcourse. But it should not be open by default, which it was. And when enabling complete read only access to the product repository a user should be able to select which product properties should be visible via the API and only the visible products should be available.

If it is open by default and not meant to by the developer, developers will forget to close it, or they do not even know that it is open. And that is what happend here. I've spoken to a few companies with live Magento 2 sites and when I told them I had complete access to the complete product repository they were all amazed. They did not know this was a feature by design!

pdohogne-magento pushed a commit that referenced this issue Mar 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development
Projects
None yet
Development

No branches or pull requests

9 participants