We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 13137
    • 204 Posts
    My question is, would this an index.php fix only or could this be set up to check other files as well?

    A recent hack left two files (manager/includes/document.parser.class.inc.php & manager/includes/protect.inc.php) infected, and these appear to be the targets of choice, after reading the forum a bit, as well as adding an additional file as a back door.
      • 18913
      • 654 Posts
      I actually set an example up that included all the files that had been targeted. So, no, it isn’t necessarily particular to index.php What I did is checked to see if *any* of the checksums were off and if any *one* was off, all six or so php files targeted go refreshed.

      Hope that clarifies things.
      Matt
        • 13137
        • 204 Posts
        How is this ran, and would you mind sharing your version of multi-file restore?
        Is it strictly cron, or is it ran via the admin?
        This sounds like an awesome preventative measure.
          • 18913
          • 654 Posts
          I was trying to find ways of having the check done at the earliest point in execution of index.php. This is an example of the plugin code that I was playing around with. I also thought about having index.php "include" a php file that was above the root and which included the checksum comparison function. I’m not sure which - if any - approach is better than the other : mod’ing index.php, et. al. to do the calcs, including the code from a location above the root, or not touching any of the files and using the plugin. Anyway, I’d be interested in hearing this idea vetted.
          Matt

          PS Note that one could trivially change each of the relevant PHP files, thereby creating MD5 signatures that were not the same as the "out of the box" install. That would help further confuse things. And sorry if the code isn’t very efficient ...

          /*This code should be triggered by an event like OnWebPagePrerender*/
          
          		$refvalues = array();
          		$checksums = array();
          
          		$refvalues['.htaccess'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['.htaccess'] = md5_file('.htaccess');
          		
          		$refvalues['index.php'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['index.php'] = md5_file('index.php');
          		
          		$refvalues['manager/.htaccess'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['manager/.htaccess'] = md5_file('manager/.htaccess');
          		
          		$refvalues['assets/.htaccess'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['assets/.htaccess'] = md5_file('assets/.htaccess');
          		
          		$refvalues['manager/includes/protect.inc.php'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['manager/includes/protect.inc.php'] = md5_file('manager/includes/protect.inc.php');
          		
          		$refvalues['manager/includes/config.inc.php'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['manager/includes/config.inc.php'] = md5_file('manager/includes/config.inc.php');
          		
          		$refvalues['manager/includes/document.parser.class.inc.php'] = 'SOME_ACTUAL_MD5_VALUE_CALCULATED_AHEAD_OF_TIME';
          		$checksums['manager/includes/document.parser.class.inc.php'] = md5_file('manager/includes/document.parser.class.inc.php');
          
          		$backupneeded = FALSE;
          
          		foreach($refvalues as $key => $value)
          		{
          			if ($checksums[$key] != $value)
          				$backupneeded = TRUE;
          		}
          
          		if ($backupneeded === TRUE)
          		{
                      $emailmsg = 'Backup needed : '.$backupneeded;
          			$backupsucceeded = TRUE;
          			foreach($refvalues as $key => $value)
          			{
                              $emailmsg .= 'File : '.$key.'<br/>';
          					$chngdfile = chmod($key, 0755);
                              $emailmsg .= '  Made writeable : '.$chngdfile.'<br/>';
          					if ($chngdfile === TRUE)
                                  {
          						 /*PATHTOYOURBACKUPS is something like /home1/youraccount/somefolder/somesubfolder/somesubsubfolder/*/
          					     $backuprestored = copy('PATHTOYOURBACKUPS'.$key, $key);
          				         if ($key == 'manager/includes/config.inc.php')
                                          $chngdfile = chmod($key, 0600);
                                   else
                                          $chngdfile = chmod($key, 0644);
                                   $emailmsg .= '  Made readonly : '.$chngdfile.'<br/>';
          					     if ($backuprestored !== TRUE)
          						     $backupsucceeded = FALSE;
                                   $emailmsg .= '  Backup succeeded : '.$backupsucceeded;
                                  }
                              else
                              {
                                   $emailmsg .= '  Not able to make file writeable<br/>';
                              }
                              $emailmsg .= 'Backup succeeded = '.$backupsucceeded.'<br/>';
          			}
          
          			$emailaddy = 'YOUREMAIL@ADDRESS';
          			if ($backupsucceeded === TRUE)
          			{
          				$emailsubject .= MODX_SITE_URL.' Backup was needed ...';
          				mail($emailaddy, $emailsubject, $emailmsg);	
          				header('Location: .');
          			}
          			else
          			{
          				$emailsubject = MODX_SITE_URL.' Backup was needed but FAILED ...';
          				$emailmsg = 'Backup plugin was triggered for '.MODX_SITE_URL.' but FAILED on file copy.';	
          				mail($emailaddy, $emailsubject, $emailmsg);	
          			}
                  }
          
            • 13137
            • 204 Posts
            I will be checking this out soon.
            If I am to understand this, each time a file via admin is updated, it would run this plug-in?

            Also in regards to changing each of the backup files, one would have to know that this plug-in was there, and what those other files were for, before messing with those too, and my assumption is that a bot is doing most of the probing to find the original hack.
            I don’t think that this is a solution, but just one more preventative measure.

            Thanks very much.
              • 18913
              • 654 Posts
              Here was what I was thinking :
              - create a folder above the site root and store known-good copies of the relevant files there.
              - calculate MD5 (or some other checksum, if you want) for each of those
              - set up the plugin with the relevant changes to it for paths, email addresses, etc. Include
              in the plugin the calculated checksums.

              To test
              - ftp a changed copy of, say, index.php to the root, overwriting the "real" one. This test version
              could be one that just echos some text at it’s end. So you should see it if the plugin doesn’t work
              - browse to the site
              - the old file should be what is served up, i.e. you shouldn’t see your "echo" at the end of index.php,
              for example
              - you should also get an email saying that a change was detected and that files were overwritten

              If the known-good copies are above the web root, then they would need to know the location, filenames and which file gets copied where. If it does find them and changes them, then they’re also going to have to change the hardcoded values in the plugin, because their file(s) are going to be different.

              Can you help me understand what weakness you see? Thanks for your helping in checking this out.
              Matt
                • 22303 MODX Staff
                • 10,725 Posts
                Sounds interesting, but I do not think the overhead it would cause on every request to MODx is worth it IMO. This would make a great utility outside of MODx though, implemented closer to the OS/filesystem.
                  • 18913
                  • 654 Posts
                  @OpenGeek : I guess that argues for it being implemented as a cron job, with the question then becoming how does one balance off the interval of time during which a site would be hacked against the server/resource load such a job presents. (I don’t really know much about the performance nuances of cron jobs, so I’m just guessing that it’s something to consider.) Or can you suggest another way that something like this could be implemented closer to the OS/filesystem? I guess it’s fair to assume that since this sort of thing happens in a shared environment, the website owner/developer only has a limited number of tricks to employ in getting this out of MODx. A cron job is the only one I’m familiar with ...

                  Thanks again for any thoughts.
                  Matt
                    • 5340
                    • 1,624 Posts
                    how about checking the file every n hr. n is modifiable via config
                      • 34017
                      • 898 Posts
                      I know this is old. But this thread should get more play. It’s a great little idea.

                      I wonder if it would make sense to have a module that could be run to check against known vulnerabilities. It wouldnt have to be automatic.
                        Chuck the Trukk
                        ProWebscape.com :: Nashville-WebDesign.com
                        - - - - - - - -
                        What are TV's? Here's some info below.
                        http://modxcms.com/forums/index.php/topic,21081.msg159009.html#msg1590091
                        http://modxcms.com/forums/index.php/topic,14957.msg97008.html#msg97008