Skip to content

Instantly share code, notes, and snippets.

@vpietri
Created October 21, 2015 10:59
Show Gist options
  • Save vpietri/eb61264ff85c475f9cf9 to your computer and use it in GitHub Desktop.
Save vpietri/eb61264ff85c475f9cf9 to your computer and use it in GitHub Desktop.
Magento shell script to detect and neutralize malware injection code. By now work only for guruincsite. Should be set in a cronjob task.
<?php
require_once 'abstract.php';
/**
* Magento Malware Shell Script Check
*
* This file should be save in the shell directory of Magento
* Basic usage samples:
* php malware.php
* php malware.php list
* php malware.php clean --mail XX.YY.com
*
* @author Vincent Pietri <www.vincent-pietri.fr>
*/
class Mage_Shell_Malware extends Mage_Shell_Abstract
{
protected $_malwares = array('guruincsite');
protected $_connections = array();
protected $_tablePrefix = '';
protected $_logMsg = array();
/**
* Parse string with indexers and return array of indexer instances
*
* @param string $string
* @return array
*/
protected function _parseIndexerString($string)
{
if (!empty($string)) {
$codes = explode(',', $string);
$codes = array_map('trim', $codes);
$processes = $this->_getIndexer()->getProcessesCollectionByCodes($codes);
foreach($processes as $key => $process) {
if ($process->getIndexer()->getVisibility() === false) {
unset($processes[$key]);
}
}
if ($this->_getIndexer()->hasErrors()) {
echo implode(PHP_EOL, $this->_getIndexer()->getErrors()), PHP_EOL;
}
}
return $processes;
}
/**
*
*/
protected function _getConnection($type)
{
if (empty($this->_connections[$type])) {
$this->_connections[$type] = Mage::getSingleton('core/resource')->getConnection('core_read');
}
return $this->_connections[$type];
}
/**
* Run script
*
*/
public function run()
{
if ($this->getArg('mail')) {
$mails = $this->getArg('mail');
} else {
$mails = false;
}
if ($this->getArg('admin_users')) {
$this->adminUsersNumber($this->getArg('admin_users'));
}
$this->_tablePrefix = (string)Mage::getConfig()->getTablePrefix();
if ($this->getArg('list')) {
foreach($this->_malwares as $code) {
echo $code . PHP_EOL;
}
} else if ($this->getArg('detect')) {
foreach($this->_malwares as $code) {
$method = strtolower($code).'Check' ;
if(method_exists($this, $method)) {
$this->$method();
}
}
} else if ($this->getArg('clean')) {
foreach($this->_malwares as $code) {
$method = strtolower($code).'Check' ;
if(method_exists($this, $method)) {
$this->$method(true);
}
}
} else {
echo $this->usageHelp();
return;
}
echo '---- Final report' . PHP_EOL;
if(!empty($this->_logMsg)) {
echo implode(PHP_EOL, $this->_logMsg) . PHP_EOL;
if($mails) {
$mailsArr = explode(',', $mails);
$mail = new Zend_Mail();
$mail->setFrom(Mage::getStoreConfig("trans_email/ident_general/email"),Mage::getStoreConfig("trans_email/ident_general/name"));
foreach($mailsArr as $recipient) {
$mail->addTo($recipient,$recipient);
}
$mail->setSubject("Magento malware suspected for '" . Mage::getStoreConfig("web/secure/base_url") . "'");
$body = "Warning," . PHP_EOL . PHP_EOL;
$body .= implode(PHP_EOL, $this->_logMsg) . PHP_EOL . PHP_EOL;
$body .= 'From: ' . __FILE__;
$body = str_replace(PHP_EOL, '<br/>', $body);
$mail->setBodyHtml($body);
$mail->send();
echo '-- send report to ' . $mails . PHP_EOL;
}
} else {
echo 'all seems right' . PHP_EOL;
}
}
protected function _log($message)
{
$this->_logMsg[] = $message;
}
protected function adminUsersNumber($number)
{
$readConnection = $this->_getConnection('core_read');
$query = "select count(*) from {$this->_tablePrefix}admin_user";
$count = (int)$readConnection->fetchOne($query);
if ($count>$number) {
$this->_log(sprintf('expected %s admin users and found %s. Check real number in back office.', $number, $count));
}
}
/**
* @see : https://blog.sucuri.net/2015/10/massive-magento-guruincsite-infection.html
*/
protected function guruincsiteCheck($clean=false)
{
$readConnection = $this->_getConnection('core_read');
if ($clean) {
$writeConnection = $this->_getConnection('core_write');
}
$query = "select * from {$this->_tablePrefix}core_config_data where value like '%guruincsite%' or value like '%function LCWEHH%'";
$result = $readConnection->fetchAll($query);
if ($result) {
foreach($result as $data) {
$this->_log('core_config_data infected: ' . $data['path']);
}
$query = "UPDATE {$this->_tablePrefix}core_config_data SET value = REPLACE(value, 'guruincsite', 'mykindyfallbackerrorsite') WHERE value LIKE '%guruincsite%';
UPDATE {$this->_tablePrefix}core_config_data SET value = REPLACE(value, 'function LCWEHH', 'function mykindyfallbackfunction') WHERE value LIKE '%function LCWEHH%'";
if ($writeConnection->query($query)) {
$this->_log('-- core_config_data neutralized, you should manual cleaning it (search for term "mykindyfallback").');
}
}
$query = "select * from {$this->_tablePrefix}cms_block where content like '%guruincsite%' or content like '%function LCWEHH%'";
$result = $readConnection->fetchAll($query);
if ($result) {
foreach($result as $data) {
$this->_log('cms_block infected: ' . $data['identifier']);
}
$query = "UPDATE {$this->_tablePrefix}cms_block SET content = REPLACE(content, 'guruincsite', 'mykindyfallbackerrorsite') WHERE content LIKE '%guruincsite%';
UPDATE {$this->_tablePrefix}cms_block SET content = REPLACE(content, 'function LCWEHH', 'function mykindyfallbackfunction') WHERE content LIKE '%function LCWEHH%'";
if ($writeConnection->query($query)) {
$this->_log('-- all cms_block neutralized, you should manual cleaning it (search for term "mykindyfallback").');
}
}
$query = "select * from {$this->_tablePrefix}cms_page where content like '%guruincsite%' or content like '%function LCWEHH%'";
$result = $readConnection->fetchAll($query);
if ($result) {
foreach($result as $data) {
$this->_log('cms_page infected: ' . $data['identifier']);
}
$query = "UPDATE {$this->_tablePrefix}cms_page SET content = REPLACE(content, 'guruincsite', 'mykindyfallbackerrorsite') WHERE content LIKE '%guruincsite%';
UPDATE {$this->_tablePrefix}cms_page SET content = REPLACE(content, 'function LCWEHH', 'function mykindyfallbackfunction') WHERE content LIKE '%function LCWEHH%'";
if ($writeConnection->query($query)) {
$this->_log('-- all cms_page neutralized, you should manual cleaning it (search for term "mykindyfallback").');
}
}
}
/**
* Retrieve Usage Help Message
*
*/
public function usageHelp()
{
return <<<USAGE
Usage: php -f malware.php -- [options]
list Show all malware code
detect Detect malwares
clean Clean specific malware
--mail <emails> Send email
--admin_users <nbr> Check admin users number
help This help
<emails> Comma separated emails
<nbr> Integer
USAGE;
}
}
$shell = new Mage_Shell_Malware();
$shell->run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment