Find And Replace Script

by Anatoliy Dimitrov

This short but powerful perl script searches files recursively and substitutes text. If your site has been compromised and there is malicious code added, that's exactly what you are looking for.

#!/usr/bin/perl
# A simple recursive find and replace tool
# Copyright (C) 2010 Anatoliy Dimitrov, website-security.info

#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see .

#If used escape these characters . * ? + [ ] ( ) { } ^ $ | \ ;
#The 's' RE modifier makes it work on more than one line by default.

use strict;
use warnings;
use File::Find;
use Cwd;

my $changefrom = 'code to be replaced\n'; #leave \n at the end to avoid blank lines left
my $changeto = ''; #usually empty unless you want to place something
my $extensions = '.php';
my $path = cwd; #usually the current working directory

#do not change anything below this line

sub matchPattern {

    my $file = $File::Find::name;

    if ($file =~ /$extensions/) {
        open INPUT, '<', $file or warn;
        my @input_array=<INPUT>
        close(INPUT);
        my $file_code=join("",@input_array);
        $file_code =~ s#$changefrom#$changeto#sg;
        open OUTPUT, '>', $file or warn;
        print(OUTPUT $file_code);
        close(OUTPUT);
    }

}

find (\&matchPattern, $path);

The two interesting variables above are $changefrom and $extensions. In most cases $extensions will be only '.php' for php files. Though  $changefrom is a bit more tricky to be set and here are some examples:

You've got a similar code added to each of your php files:

<script type="text/javascript">
alert("Are you serious about website security?")
</script>

In this case your variable will be:

my $changefrom ='<script.*serious.*cript>\n';

This script can be also found on Github.

As previously mentioned, the Regular Expression modifier 's' ignores the new lines when searching for a match. This might not be always desired especially when you take into consideration that it performs a greedy match. Thus you may decide to remove the 's' and use '\n' for each new row.

You may wonder why we add '\n' at the end of the regular expression. The answer is that if we don't add it there will be a blank row. This is quite nasty if malicious code has been added at the end of php files after the closing php tag. Then you will end up with premature end of script headers...

The above is a simple example but usually real life situations are close to it. If you have troubles with it drop me a line at our contact page.

blog comments powered by Disqus