1

My sites got infected with some bad malware that has inserted malicious code on at least 3135 files (all my wordpress sites).

This is one of the files infected: http://pastebin.com/FXU1ht4R

And here is my desired output: http://pastebin.com/YPJwjiWH

I have no idea about Unix commands, besides some simple find and grep commands.

After some research I found about the sed command but I don't know how to use it in my case.

As you can see from the above code, the general pattern is that the code is inserted at the top of each file, meaning before the original <?php tag (which means now the original <?php tag is second.

So I thought I could find all the files containing cnajwp = and remove everything before the second <?php tag.

I can find the files containing cnajwp by using

find * -type f -name "*.php" -exec grep -l "cnajwp =" {} \;

but I don't know how to replace everything before the second <?php tag on these occurrences.

Could anybody here give me a helping hand?

5
  • Which part do you exactly want to be deleted? Many stuff can be deleted before the second occurrence! Put your desired output in your question, so we can help you more easily.
    – user172564
    Aug 7, 2016 at 14:12
  • 1
    specifically, this is the infected file: pastebin.com/FXU1ht4R and I want it to look like this: pastebin.com/YPJwjiWH which is basically to remove all the obfuscated code that was added at the top. (can't put more than 2 links on the original post because of low reputation on this forum - im new here).
    – user183533
    Aug 7, 2016 at 14:17
  • 2
    You can't remove malware just by removing visibly infected files. There's a very high chance that there are parts of the malware that you don't see, and if you only clean the visible parts, your machine will still be infected and serve more malware, participate on botnets, send out your user database etc. Nuke it from orbit, it's the only way to be sure. Aug 7, 2016 at 21:15
  • @Gilles obviously I know that, but since these are not critical sites, I could live with that doubt instead of having to build everything from scratch.
    – user183533
    Aug 7, 2016 at 21:26
  • @cas, I fail to see in which way that is a duplicate of that other answer. Aug 8, 2016 at 16:13

3 Answers 3

0

This uses your command to find the infected files, and gives the list to xargs, which runs an expression on the first line.

find * -type f -name "*.php" -exec grep -l "cnajwp =" {} \; |
xargs sed -i -E '1s/^(<\?php) \$ocnajwp =.*$/\1/'

According to your input-file sample, this should do the trick.

Since in the meantime you have found files, where the infection was placed slight differently, and you have ended up with some files, where both first lines contain <?php, you could run the following to clean up those files:

find * -type f -name "*.php" -exec \
gawk -i inplace 'NR==2 && /^<\?php$/ {next} 1' {} \;
3
  • wow that was magic (with a few exceptions) - in some files it left the first <?php in there so the output ended up being <?php <?php which would then give error on some of my page. Specifically this file pastebin.com/Tcxa9LBD ended up like this: pastebin.com/FYbxkdYR if that would be fixed also, it would be perfect. Any thought? Thnx
    – user183533
    Aug 7, 2016 at 14:52
  • @AlboBest, That file has a whole another <?php ... ?> code block on the first line, which breaks the assumption here that the first line only contains the to-be-removed code and the opening <?php marker. You might want something like sed -E '1s/^<\?php \$ocn.*\?>//' instead to delete up to the ?>` ending marker. (didn't test)
    – ilkkachu
    Aug 7, 2016 at 15:28
  • @ilkkachu there's no ?> ending marker, instead there are just two opening markers <?php <?php in two separate lines, one of them must be removed. If I understood you correctly, I tried find * -type f -name "*.php" -exec grep -l "cnajwp =" {} \; | xargs sed -E '1s/^<\?php \$ocnaj.*\?>//' which didn't do anything.
    – user183533
    Aug 7, 2016 at 15:39
0

This solution accommodates a case where the malicious script spans more than one line and will use the in-place edit to change the files directly on the server.

find /base/path/here -type f -name "*.php" -exec \
sed -Ei '/<\?php/{:l1;/.*\?><\?php/!{N;bl1};s/<\?php.*\?>(<\?php)/\1/}' {} \;

Hope this fits the requirement.

7
  • nope, that gives the following error find: missing argument to '-exec I'm still left broken :)
    – user183533
    Aug 7, 2016 at 17:11
  • @AlboBest : Sorry I forgot a \; at the end of the command just before the ending single quote, corrected and this should work
    – sjsam
    Aug 7, 2016 at 17:14
  • I still get the exact same error. I tried a few other different combinations but without any luck. sorry, I feel lost with linux commands :)
    – user183533
    Aug 7, 2016 at 17:38
  • still the same exact error. perhaps I should add grep and xargs in that? I tried doing that also without luck (blindly);
    – user183533
    Aug 7, 2016 at 17:54
  • @AlboBest : That was me at my worst forgot the closing single quote of sed added just before {} and removed the trailing single quote
    – sjsam
    Aug 7, 2016 at 17:55
0

From what I could see, all the malicious code you want to delete is put in line 1. But be aware that your <?php tag is put in that line either, so you should change the whole first line to <?php instead of deleting it.

All you need is to use the command below:

sed -i '1 s/^.*$/<?php/g' yourFile.php

-i option will change the file in-place.

So for your find command you've used:

find * -type f -name "*.php" -exec sed -i '1 s/^.*$/<?php/g' {} \;

For files that contain two <?php tags on both first and second lines, you need to run the command below, after running the above find command:

find * -type f -name "*.php" -exec perl -ni -e 'print if $. < 1 or $. > 3 or !$seen{$_}++' {} \;

So it will delete duplicate lines met from line 1, to line 3. -i option will change the file in-place.

11
  • How can you be sure that the entire script is contained in first line?
    – sjsam
    Aug 7, 2016 at 14:28
  • Mate, before downvoting, check the file he sent for me in comments!
    – user172564
    Aug 7, 2016 at 14:29
  • You can't just delete the first line. The infection prependes itself before the original opening <? php tag in the first line. So, you have to cut until the second php tag in the first line. (See the pastebin-link). Your answer will "break" the php files. Aug 7, 2016 at 14:34
  • @AlexStragies Thanks a million, now it's fixed and won't break the php files.
    – user172564
    Aug 7, 2016 at 14:50
  • Thsnk you. This produces the same output as the command @AlexStrategies wrote. Quote: ------------------ in some files it left the first <?php in there so the output ended up being <?php <?php which would then give error on some of my page. Specifically this file pastebin.com/Tcxa9LBD ended up like this: pastebin.com/FYbxkdYR if that would be fixed also, it would be perfect. Any thought? Thnx
    – user183533
    Aug 7, 2016 at 14:58

You must log in to answer this question.