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?

  • 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. – FarazX Aug 7 '16 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 '16 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. – Gilles 'SO- stop being evil' Aug 7 '16 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 '16 at 21:26
  • @cas, I fail to see in which way that is a duplicate of that other answer. – Stéphane Chazelas Aug 8 '16 at 16:13

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' {} \;
| improve this answer | |
  • 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 '16 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 '16 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 '16 at 15:39

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.

| improve this answer | |
  • nope, that gives the following error find: missing argument to '-exec I'm still left broken :) – user183533 Aug 7 '16 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 '16 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 '16 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 '16 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 '16 at 17:55

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.

| improve this answer | |
  • How can you be sure that the entire script is contained in first line? – sjsam Aug 7 '16 at 14:28
  • Mate, before downvoting, check the file he sent for me in comments! – FarazX Aug 7 '16 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. – Alex Stragies Aug 7 '16 at 14:34
  • @AlexStragies Thanks a million, now it's fixed and won't break the php files. – FarazX Aug 7 '16 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 '16 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy