magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.45k stars 9.29k forks source link

Unprotected/insecure create customer API #37374

Open mischabraam opened 1 year ago

mischabraam commented 1 year ago

Preconditions and environment

Steps to reproduce

  1. Create a new customer with unprotected POST REST API. As test body you can use the following.
POST http://www.magento2.test/rest/all/V1/customers
{
    "customer": {
        "group_id": 0,
        "email": "testing@spammers.com",
        "firstname": "Test",
        "lastname": "Spammer",
        "gender": 0,
        "store_id": 1,
        "website_id": 1
    }
}

Expected result

The customer is not created, you should get an error like "auth is missing".

Actual result

The customer is created blindly with some attributes having default values. This makes it possible for spammers to create customers endlessly. See the following screenshots as proof of this insecure behavior.

public-create-customer-1 public-create-customer-2 public-create-customer-3

What confuses me is that the GET and PUT API's seem to be secure. But why not the POST?

Additional information

No response

Release note

No response

Triage and priority

m2-assistant[bot] commented 1 year ago

Hi @mischabraam. Thank you for your report. To speed up processing of this issue, make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, Add a comment to the issue:

m2-assistant[bot] commented 1 year ago

Hi @engcom-Bravo. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

engcom-Bravo commented 1 year ago

@magento give me 2.4-develop instance

magento-deployment-service[bot] commented 1 year ago

Hi @engcom-Bravo. Thank you for your request. I'm working on Magento instance for you.

magento-deployment-service[bot] commented 1 year ago

Hi @engcom-Bravo, here is your Magento Instance: https://436b8cf6150d63d7a4efa837a3ebefa8.instances-prod.magento-community.engineering Admin access: https://436b8cf6150d63d7a4efa837a3ebefa8.instances-prod.magento-community.engineering/admin_5a9e Login: 4fa3bbdb Password: b2f5ad0b1669

engcom-Bravo commented 1 year ago

Hi @mischabraam,

Thank you for reporting and collaboration.

Verified the issue on Magento 2.4-develop instance and Magento 2.4.6 instance and the issue is reproducible,But it is an expected behaviour of Magento.Kindly refer the screenshots.

Screenshot 2023-04-17 at 4 27 41 PM

Kindly check this doc https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security/. As per this doc

The following APIs remain accessible to anonymous users. Most of these must remain accessible to support the checkout and add-to-cart Ajax functionalities.Preventing anonymous access to these endpoints could cause third-party integrations to fail.

Screenshot 2023-04-17 at 5 24 16 PM

Kindly let us know if you are still facing any issue.

Thanks.

mischabraam commented 1 year ago

Preventing anonymous access to these endpoints could cause third-party integrations to fail.

Very true. If you would secure this API by adding a resource in webapi.xml this will be not backwards compatible. However, that should not be a reason to not change it. :)

I think it's weird to force a bearer token (older versions) or oauth token for getting a customer, changing them, changing products, adding products, bot NOT for creating a customer. I can easily create thousands of spam customer accounts, reset their passwords and place fake orders with these fake accounts, fun fun fun for spammers. Don't you agree at least this is weird (despite what the docs state)?

engcom-Bravo commented 1 year ago

Hi @mischabraam,

Thanks for your update.

We are considering this as Feature request as it is an existing behaviour of Magento.

Thanks.

maghamed commented 1 year ago

@magento give me 2.4-develop instance

magento-deployment-service[bot] commented 1 year ago

Hi @maghamed. Thank you for your request. I'm working on Magento instance for you.

magento-deployment-service[bot] commented 1 year ago

Hi @maghamed, here is your Magento Instance: https://436b8cf6150d63d7a4efa837a3ebefa8.instances-prod.magento-community.engineering Admin access: https://436b8cf6150d63d7a4efa837a3ebefa8.instances-prod.magento-community.engineering/admin_cdf6 Login: 8fea0ff4 Password: 258e6f80da2b

DuckThom commented 1 year ago

@mischabraam

I think if you want to protect such routes from spammers you would need to look into using (re)captcha: https://developer.adobe.com/commerce/webapi/rest/use-rest/protected-endpoints/#recaptcha

I think it's weird to force a bearer token (older versions) or oauth token for getting a customer, changing them, changing products, adding products, bot NOT for creating a customer.

Correct me if I'm wrong but if an auth token was enforced on the create customer API, wouldn't that block the registration flow for things like standalone frontends that communicate with Magento using the REST API?

As for the creation and updating of products, there's also a difference between admin/integration tokens and customer tokens. For example, customer tokens cannot do such actions whereas admin/integration tokens have access to basically anything you can do in the admin panel (assuming the permissions for the token are set correctly).

mischabraam commented 1 year ago

Correct me if I'm wrong but if an auth token was enforced on the create customer API, wouldn't that block the registration flow for things like standalone frontends that communicate with Magento using the REST API?

I haven't built a stand alone front-end myself (yet). But theoretically, no. In your stand alone front-end you'll have to make several API calls to Magento. Most of them require a token (bearer or oauth-v1). To create a customer you currently omit the token. This omit would be the only change in your stand alone front-end.

Diving more into this (and reading the docs, thankyou) I've found other API's I can easily exploit to get information. The "isEmailAvailable" is also unprotected and public. I've created a quick patch, see below.

GITHUB-37374_customer_disallow_anonymous_apis.composer.patch

DuckThom commented 1 year ago

I agree that from an integration perspective it makes sense to require some sort of token to those endpoints, yes.

However, I still don't think it would work for standalone frontends if the token is always required.

Let's say a token was required for the createCustomer call. When you submit a registration form directly to the Magento REST API, you'd also need send that token from the browser to Magento. This token could easily be read via the dev tools in the browser and could then be used to automate/spam requests once more (or worse, if it's an admin token, access the admin endpoints).

I think a solution could be to have a toggle or setting in the Magento admin panel which can be used to allow or disallow anonymous API's.

When disallowed, a standalone frontend could still be used, though you'd need something like NextJS where you could add the token via an API route: browser > NextJS api route to add token > Magento API. And even then, a bot could abuse the API route to still make the calls to Magento.

mischabraam commented 1 year ago

You would have to built in logic to accomplish that I guess, instead of a change in the webapi.xml. But if you think that's necessary, then yeah ok, sounds good. I would suggest then that the "disallowed" option would be the default? But I'm open for your opinion.

DuckThom commented 1 year ago

The default value kind of depends on if it should be a breaking change or not I suppose.

If the default will be disallowed then it would mean that, without changing the configuration during an upgrade, the currently anonymous API routes will no longer be accessible.

Personally I think making it opt-in (so with allowed as default value) would be better/more upgrade friendly.

mischabraam commented 1 year ago

Correct, just like when the deprecated bearer token by default changed to not-accepted, unless you configure it manually to use it. That's my basis to suggest it here also.