1

One of my sites got infected with some malicious code. The code is only added to the first line of all PHP files and is as follows:

<?php $ulhmjwklj = '#-#O#-#N# .......xqxe-1; ?> /*BEGIN LEGIT CODE HERE*/ <?php....

The malicious code is thousands of characters long with lots of special characters and spacing, so I tried creating a script to remove it:

for i in $(find . -name \*.php); do
  sed -i -E "s/<\?php\s$ulhmjwklj.*\?>//" $i;
  echo $i;
done;

This sed command will correctly remove the malicious code while leaving legitimate code on the first line, but then in all subsequent lines it removes all <?php ... ?> tags. So I tried altering the sed command to only search/replace on the first line:

for i in $(find . -name \*.php); do
  sed -i -E "1s/<\?php\s$ulhmjwklj.*\?>//" $i;
done;

Now the sed command will only run on the first line of each file, but it also removes any legitimate PHP tags which are appended to the first line directly after the malicious code.

Can someone please explain where I'm going wrong here?

miken32
  • 42,008
  • 16
  • 111
  • 154
blazebro
  • 13
  • 2
  • Is the length of the malicious code fixed in all the files? Or is it varying from file to file? – anacron Feb 16 '17 at 18:43
  • Also, how many PHP files do you have in total? Are all of them affected? – anacron Feb 16 '17 at 18:43
  • the `.*` is greedy... – clt60 Feb 16 '17 at 18:57
  • Bash is going to be looking for a variable named `$ulhmjwklj`. And if you escape it, then sed will be looking at `$` as an end of line. Will need to be double escaped, or don't use double quoted string. – miken32 Feb 16 '17 at 19:00
  • Yep all PHP files are infected, and the malicious code is a fixed number of characters in each file. I was thinking about going through this route next... – blazebro Feb 16 '17 at 20:22

1 Answers1

0

The results of find should not be put through a loop. And, as I mentioned in the comments, $ is a special character for both Bash and a regular expression so has to be dealt with appropriately.

Finally, as jm666 mentioned in comments, .* is greedy, so .*? limits the search to be as small as possible. But this won't work in sed so we need to use perl instead:

find . -name '*.php' -print -exec perl -p -i -e 's/<\?php \$ulhmjwklj.*?\?>//' {} \;
Community
  • 1
  • 1
miken32
  • 42,008
  • 16
  • 111
  • 154
  • Thanks so much for your response. Unfortunately this did not do the trick, first I had to add the sed "-i -E" parameters separately instead of combined like you suggested, otherwise each PHP file was appended with a "E" at the end of the filename. Once I fixed this, the above find/replace query results in the same problem as before where legitimate PHP tags and any content within at the end of line 1 are also removed. :-/ So weird.. – blazebro Feb 16 '17 at 20:25
  • See my updated answer. As in `sed`, the `-i` option to `perl` enables inline file editing, and can be removed to do a "dry run" without changing the files. – miken32 Feb 16 '17 at 20:35
  • SUCCESS!!! Thank you so much. I wish sed would have given me back some indication that .*? would not work. – blazebro Feb 16 '17 at 20:45