Protect your Magento installation from password guessing

This is a great article from Magento:

All of the content below is from Magento’s article written by the Magento Security Team.

We’ve recently become aware of brute-force password guessing attacks on Magento installations worldwide. In some cases, these attacks have resulted in unauthorized admin panel access. We highly recommend that you take the following steps to protect your store against such attacks.

Please note that in a typical Magento 1 installation (e.g. Magento Enterprise Edition 1.14.2), locations /admin (or a custom name you have chosen for admin) and /downloader need to be protected. In the case of Magento 2, only the admin panel location (the location is generated automatically during installation) should be protected.

Before you proceed in making any changes, please take the following steps:

  1. Review all admin users in System->Permissions->Users. Remove any unused entries or entries you do not recognize. This should be done at least once a month or when any employee leaves.
  2. Ensure your password and the password of any other employee using the admin panel is strong. Remember that longer, complex passwords are much harder to guess.  For examples on how to create a secure password, please visit:HTTP://SUPPORT.GOOGLE.COM/ACCOUNTS/ANSWER/32040?HL=EN. Your password should be updated every three months.
  3. Consider changing the username to something less common – do not use admin or administrator.
  4. Ensure that you have all the patches installed, which are available for download onMY ACCOUNT for Enterprise Edition customers and on the COMMUNITY EDITION DOWNLOAD PAGE for Community Edition.

IP Whitelisting

The best way to protect access to admin and downloader locations is to enable access only for users coming from a specified IP address or network. This works best if you always access the store backend from the same location and computer or computers. To find your IP address you can use Google:HTTPS://WWW.GOOGLE.COM/SEARCH?Q=WHAT+IS+MY+IP. It should show an address like 111.222.333.444 . This solution will not work properly if you are using dynamic IP addresses or accessing the backend through a mobile device. If your company has a remote workforce, it is important to add their IP addresses as well to ensure that they have access to the network.


If You Are Using Apache Web Server

Modify the existing .htaccess file in /downloader. Add the following at the end:

order deny,allow

deny from all

allow from x.x.x.x

You can use multiple allow statements to allow access for more machines or locations.

If You Are Using Nginx Web Server


If you have full access to your server, you can modify the Nginx configuration yourself, following instructions posted at HTTPS://WWW.NGINX.COM/RESOURCES/ADMIN-GUIDE/RESTRICTING-ACCESS/


The admin panel is accessible through /admin and /index.php/admin URLs (or custom paths that you can choose), but it is not a real directory on the server and therefore needs to be protected differently. The same holds true for admin RSS feeds such as low stock notification or order status updates.

The way to protet the admin panel and RSS feeds is to redirect requests coming from unknown IP addresses to the main page. This can be done by editing the .htaccess file in the root Magento folder and adding the following just right after rewrite rules for mobile user agents, which is located just before a section called “always send 404 on missing files in these folders”.




RewriteCond %{REQUEST_URI} ^.*/RSS/ORDER [NC]

RewriteCond %{REMOTE_ADDR} !^

RewriteCond %{REMOTE_ADDR} !^

RewriteRule ^(.*)$ http://%{HTTP_HOST}/ [R=302,L]

If You Are Using Nginx Web Server


If you have full access to your server, you can modify the Nginx configuration yourself, following instructions posted at HTTPS://WWW.NGINX.COM/RESOURCES/ADMIN-GUIDE/RESTRICTING-ACCESS/

Fail2Ban Adaptive Filtering

Note: this section is based on information from created by the authors of

If you have full access to your server, you can install fail2ban software which can limit or stop guessing attacks. An example configuration for Nginx is shown below. Note: this configuration does not block access to RSS feeds. Please work with your system administrator or hosting provider to implement fail2ban properly.

Code to add to /etc/fail2ban/jail.local


# Only ban after multiple retries.

# Use this for “soft” bad behaviour.

port = http,https

filter = hn-nginx-retry-ban

logpath = /var/log/nginx/access.log

bantime = 7200

maxretry = 10

Code to add to /etc/fail2ban/filter.d/hn-nginx-retry-ban.conf:


# Use this for “soft” bad behaviour, as the source will only be banned after multiple retries.

failregex = ^<HOST> .+”POST \S+(/downloader/|/downloader/index.php\?A=loggedin|/admin/index/|/admin/)\s

ignoreregex =

In the line listing locations, you can add your custom admin path with |/custompath/.

Change the Location of the Admin Panel and Magento Connect Manager

Password guessing attacks assume typical admin panel locations like /admin, /backend, /manage, /control and similar and the default location of Magento Connect Manager: /downloader. Changing the location of the admin panel and downloader can reduce the likelihood of being targeted by a generic attack. However, it does not protect against targeted attacks as the attacks might try to guess the location first with multiple requests.

Note: some Magento hosting providers have specific security rules that apply to default locations. Please ask your hosting provider if they recommend changing the location before making this update.

Note: if you are not planning on installing extensions from Magento Connect you can delete or fully block access to the downloader directory.

Change the Name of the Admin Panel (Magento 1 Only)

Changing the name of the admin panel can also help to protect it from attacks. To change the name, first log into the admin panel and navigate to System -> Cache Management.

Then you will need to edit file app/etc/local.xml in your Magento installation and change the name in section admin -> routers -> adminhml -> args -> frontName.

After this change you need to clear all the caches and then log out and log in again using the new URL.

Change the Name of Magento Connect Manager (/Downloader) (Magento 1 Only)

Another approach is to change the name of the Magento Connect Manager. Once you have made this change, it will no longer be possible to open Magento Connect Manager from the Magento admin panel. It must be accessed directly using the new URL.

To change the name of Magento Connect Manager, simply change the folder name from downloader to something unique.

In summary, there are several approaches you can take to help protect your store from brute-force password guessing attacks. We recommend that you quickly review these approaches with your Solution and Hosting Partners and implement the ones that are best suited to your unique situation.


<=> PHP7 and Magento (M)


I finally installed PHP7 this weekend and ran some Magento local dev sites. The speed increase is impressive! It’s so much faster that it should be a mandatory requirement.

There’s only a couple of minor quirks, like not having dl() support which killed a couple of the extensions that had copy-protection on one site.  There’s a couple of small things to do to make PHP7 work but it’s covered below.  If you’re ready to take the Magento/PHP7 plunge and are using Ubuntu then this is how you can do it.

First, you have to remove your php5 install.

Remove php5

Warning: This will remove php5 from your system completely. 

sudo apt-get purge php5-*

Add the PHP7 repository

sudo add-apt-repository ppa:ondrej/php

sudo apt-get update

Install PHP7

sudo apt-get install php7.0

Install PHP7 components

sudo apt-get install php7.0-cli php7.0-common libapache2-mod-php7.0 php7.0 php7.0-mysql php7.0-fpm php7.0-curl php7.0-json php7.0-cgi php7.0-mcrypt

sudo service php7.0-fpm restart

sudo service apache2 restart

The Magento PHP7 Fix

Inchoo has this ready in an easy to install extension:

You may also need:

sudo apt-get install php7.0-intl php7.0-xsl php7.0-gd

(Thanks to Dave Moore for the tip)


Common problems with Magento after installing PHP7

If Apache is dumping plain text php instead of rendering it then be sure that you’ve installed libapache2-mod-php7.0.

sudo apt-get install libapache2-mod-php7.0

sudo service php7.0-fpm restart

sudo service apache2 restart

Getting a white page or error about mcrypt in Magento?

sudo apt-get install php7.0-mcrypt

sudo service php7.0-fpm restart

sudo service apache2 restart



Magento Certified Solution Specialist



I passed the Magento Certified Solution Specialist on July 9, 2015. If you’re thinking about taking this one then be sure to study your e-commerce terms and get very familiar with Magento’s admin.  This study guide helped me the most:  Thanks Demac Media!

Magento Certified Developer Facebook Group



I started this Facebook group several years ago to discuss becoming a Magento Certified Developer. Since then I’ve passed the exam and there have been over 1,700 people added to the group.

If you’re interested in one of Magento’s certifications or if you’re already certified then you should join today!


Admin Grid in Magento with frame_callback

Recently on, someone asked a Magento question about how to pull data into a Magento admin grid (See:  I’ve seen this come up a lot and it seems that not a lot of people know that it is possible to pull data into the Admin grid without a lot of complex joins.  You will need the joins to search and sort a custom column, but not to simply display data in the row.

For example, to get all of the SKUs in the order, you could use frame_callback to look up the SKUs for the order in a separate function.

In the Order Grid.php _prepareColumns() function, the following code will add a SKU column:


$this->addColumn('sku', array(
'header' => Mage::helper('sales')->__('SKU'),
'index' => 'increment_id',
'frame_callback' => array($this, 'callback_skus')

This looks like a normal addColumn with the exception of the parameter ‘frame_callback’.  Notice that I’m passing an array with $this and a function named ‘callback_skus’.

Add  the new function below named callback_skus somewhere in your Grid.php.

public function callback_skus($value, $row, $column, $isExport) {
$increment_id = $value;
$_order = Mage::getModel('sales/order')->loadByIncrementId($increment_id);
$_items = $_order->getAllItems();
foreach ($_items as $item) {
$skus .= $item->getSku()."<br/>";
return $skus;

The frame_callback function passes $value, $row, $column and $isExport.  The $value will be the data returned in the ‘index’ of the addColumn.  In this example, $value equals the increment_id from the table.  We can then use that increment_id to pull the entire order object and iterate through getAllItems() to retrieve all of the SKUs in that order.  By returning this value, the column in the Order Grid will now have all of the SKUs listed.

This can work just about any data that is associated with any other data that can be passed to the order grid.  You can also use frame_callback to re-style/reformat your output and pass it back to the Order Grid.

Unless the data you’re passing back to the Grid matches the data in the ‘index’, you will not be able to search or sort it.  To accomplish that, we need to do the following:

Using the same example of returning SKUs in the order Grid, update the _prepareCollection() to this:

protected function _prepareCollection()

$collection = Mage::getResourceModel($this->_getCollectionClass())
'skus' => new Zend_Db_Expr('group_concat(`sales/order_item`.sku SEPARATOR ",")'),
return parent::_prepareCollection();

This join adds the SKUs to the Grid Collection which makes the column able to be searched and sorted.

We’ll have to make a small modification to the addColumn.  We need to add the parameter filter_condition_callback and pass an array containing $this and the function name ‘filter_skus’.


$this->addColumn('sku', array(
'header' => Mage::helper('sales')->__('SKU'),
'index' => 'increment_id',
'frame_callback' => array($this, 'callback_skus'),
'filter_condition_callback' => array($this, 'filter_skus'),

The new call to filter_condition_callback adds the where condition necessary to make the search function.

The new function filter_skus() accepts $collection and $column.  We can modify the collection with a getSelect() to add a new where condition.

public function filter_skus($collection, $column) {
if (!$value = $column->getFilter()->getValue()) {
return $this;

"sku like ?"
, "%$value%");

return $this;


This new where passes the $value from the column search.  You can now search for individual SKUs in an order from the Sales Order Grid.

This can be adapted to work on any Grid in the Magento admin to retrieve just about any type of data into a column or to reformat existing data in the Grid.


Who is the Magento “Flaunt Yourself” girl?

Anyone who has worked with Magento has seen her.   She’s the “Flaunt Yourself” girl you see after a successful install of Magento, but who is she?



Using, I was able to track the stock photo to

There’s two more shots of her available:

The pictures were taken by Studioxil at   I e-mailed the photographer to ask if she had a public profile or fan page.  I received a prompt and friendly reply from Alexey Ivanov.

The model’s name is Olesya Malinskaya.  Here is her fan page on Facebook:

Thank you Alexey!