How to delete spam customer accounts from Magento

Related Inchoo Services

We all love spam bots, don’t we? They really help us improve our sites. There was a situation with one of our clients being hit by a spam bot that generated dozens of customer accounts daily. Let us show you how to get rid of them and protect the site against future attacks.

How the problem started

One would ask:  “Why there wasn’t any validation on register form?”. Well, things were functioning smoothly for a couple of years, so there wasn’t need for one. It was happening for a few weeks until it was recognized. So, we found ourselves in situation where spam customer accounts had to be recognized, deleted and prevented from registering again.

Detailed examination

With detailed examination of customer grid, it was immediately clear this wasn’t going to be easy. There were many accounts with different names and email addresses. At the time, nearly 30000 accounts were registered. Going through the list and delete them manually was not an option. It would take too much time to open each account, examine it and decide whether it’s a spam account or a real customer. It had to be done with the script.

Recognizing possible patterns

There is no simple way of properly recognizing spam customer accounts. In order to delete them programmatically, you have to be sure you’re not going to delete a real customer. It would be very unpleasant situation for a customer to be deleted from the website. Not only the customer would be unhappy, but all connections to his/her orders would be lost.

 

So, establishing a way to recognize only spam customer accounts would be in a few steps.

1. Go through a reasonable number of spam accounts and write down most repeating similarities between them.

In this case, those would be following:

– One or two capital letters at the end of a firstname or lastname, rest of the letters are small

– all email domains ending with *.ru, *.xyz, *.ua, *.top

– Numbers in firstname or lastname

– identical first and lastname

 

Account examples:

onlinecreditufedor@qip.ru, FedorKr FedorKroM

moiseevayeq1957@mail.ru, MichaelWoxeF MichaelWoxeFLP

abellayssard@homail.top, Assingnits AssingnitsDV

meme123@ccxpnthu2.pw, Ronaldtrek RonaldtrekWI

lesha.gorodnitsyn@mail.ru, VladimirCrOp VladimirCrOpAN

maksim.sakevich@yandex.ua, DouglasPhem DouglasPhemDU

ahtd95782@gmail.com, WalterDer WalterDerXV

mretsan@mail.ru, Simfum Алексей

kuch@vitalityspace.com, MartinRoot MartinRootWK

georgina14@dlfiles.ru, zirehohamew79 Taylor

ra.um@mail.ru, Somfum Димас

gfhherejft@mail.ru, FrankieDok Bartek

srhcgiarc@007game.ru, top2017bloomingme Beson

teod.or78@mail.ru, GlennZek Vlad Stahov

admin_3@iphone-ipad-mac.xyz, Xewrtyuoipye XewrtyuoipyeBP

abcd2775y38@nod03.ru, myregobahev87 Alejandro

akilaanka@qip.ru, aseoprodwig aseoprodwig

polysten@i.ua, CharlesSCARK CharlesSCARKJE

 

Magento code is as follows:

$customers = Mage::getModel('customer/customer')
    ->getCollection()
    ->addAttributeToSelect('*')
    ->addAttributeToFilter(
        array(
            array('attribute' => 'email', 'like' => '%.ru'),
            array('attribute' => 'lastname', 'regexp' => '[a-z][A-Z]{2}'),
            array('attribute' => 'firstname', 'regexp' => '[0-9]'),
            array('attribute' => 'lastname', 'regexp' => '[0-9]')
        )
);

 

2. Try to load addresses for each account

First step should do the trick. But, to be sure that no real data will be lost from Magento, this additional step will be applied. This particular spam bot was unable to register and login to the site. It only created number of accounts. So, all of those accounts didn’t have any address associated. If there is any account with address, it shall be skipped from deleting.

foreach ($customers as $customer) {
    $customerAddresses = $customer->getAddresses();
        if ($customerAddresses) {
            continue;
        }
}

 

3. Check if there are any orders for each account.

If there is an order associated to a customer account it shall also be skipped from deleting. This is most probably the real account.

foreach ($customers as $customer) {
    $customerOrders = Mage::getModel('sales/order')
        ->getCollection()
        ->addAttributeToFilter('customer_id', $customer->getId())
        ->load();
 
        if ($customerOrders->count()) {
            continue;
        }
}

In this particular case, filters had to be very carefully set because there are real customers on the site whose names are written in capital letters. They also don’t have any address registered, therefore not having any orders either.

Before deleting customer account, it is nice to have it written in a log file. Just in case.

After all checks have been made, spam customer accounts can be deleted simply by calling $customer->delete() function in a loop.

Prevention

Most of the spam bots will be filtered out by activating Magento’s built in captcha for register form. It can be easily activated in administration under Settings->Customer->Customer Configuration->CAPTCHA. There are several options, as well as forms to be activated on.

As a custom solution and probably the best protection available, a Google’s reCAPTCHA can be implemented on register form. No bots shall pass then.

Conclusion

There are number of different spam bots out there, so there is no simple and certain way of deleting accounts from the website once they are registered. They must be examined manually and pattern shall be defined accordingly. There is no need to cover all of them. It’s impossible. After majority has been deleted, rest of the spam accounts are not so difficult to delete manually.

8 comments

  1. when we run this code show the error

    Fatal error: Uncaught Mage_Core_Exception: Cannot complete this operation from non-admin area.

  2. what is the full scrip then ? as you defined only idea on how to do it.

    $customers = Mage::getModel(“customer/customer”)
    ->getCollection()
    ->addAttributeToFilter(’email’, array(‘like’ => ‘%ru.%’));

    foreach ($customers as $customer) {
    $customer->delete();
    }

  3. Hi Damir Serfezi!

    Thank you for the detailed explanation of issue and countermeasures. Can you pls also suggest as to where use the above mentioned code in Magento?

    I understand everything except where to use the code chunk.

    Thanks much.
    Abhishek

  4. I have same issue. I am trying to understand.. What are these bots trying to accomplish? Any security issue?

  5. // Extra Magento POST variables
    if ( false !== strpos( $request_path, '/customer/account/createpost' )
        && ( isset( $_POST['birthyear'] ) ||  isset( $_POST['sYear'] ) || isset( $_POST['year'] ) )
    ) {
        return 'bad_request_post_magento_vars';
    }

    Could be caught easily as fake registrations use vast amount of extra POST vars.
    I patched my WordPress WAF.

  6. I can’t agree using Google reCapcha is the solution. I had a similar issue with leaving a long Russian advertisement within first name field while Google reCaptcha was enabled. Apparently, disabling JavaScript in the browser, he/she can bypass the Google reCaptcha and continue register. So, I enabled Magento native reCaptcha since it checks at the back-end and some extra check like non-English language, the number in the name field, and URL in the name field at the back-end.

  7. Be careful when using this if your MySQL database is in a case-insensitive collation. If it is something like latin1_swedish_ci, then the regex “[a-z][A-Z]{2}” will return all last names with at least three characters. The way to get around this in MySQL is to cast the value as binary, but I’m not sure how to do that in Magento.

  8. Heh… I was solving this exact issue on two magento1.x instances… like a month ago 🙂 That Russian guys… can’t they use mailchimp for spamming, like everybody else 😀 hehe

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.