Explanation
What you described is a part of a known PHP backdoor. The main PHP code is obscured by base64 encoding so that it is not so easily detectable. The code you showed is normally hidden in the Exif header Model
and another important part (PCRE /.*/e
) is normally in the header Make
.
The code from Exif gets executed by another part of the backdoor - calling preg_replace($exif['Make'],$exif['Model'],'');
on the Exif data from the image. For details see for example Malware Hidden Inside JPG EXIF Headers or Hiding Webshell Backdoor Code in Image Files.
Solution
You can remedy the infected images by removing the relevant Exif headers. First check if the problematic strings are in the headers Make
and Model
:
exiftool file.jpg
Then you can remove the headers:
find /directory/with/images -iname '*.jpg' -exec exiftools -Make= -Model= {} +
This code will remove the two headers from all the .jpg
files regardless of the content of the headers. If you want to remove just the infected headers the code would be considerably more complicated. The script to do this is below at the end of this answer.
After checking that the results are OK you can remove the backups created by exiftool
:
find /directory/with/images -iname '*.jpg_original' -delete
Keep in mind that the other part of the backdoor whould be removed too. It is in the PHP code on the server and normally looks like:
$exif = exif_read_data('/path/to/an/image.jpg');
preg_replace($exif['Make'],$exif['Model'],'');
Script for more accurate removal
The following script detects in which Exif headers there is the code of malware. Store the code into a file e.g. rm-jpg-backdoor
then enable execution: chmod a+x rm-jpg-backdoor
. When calling the script you can pass directories of files to clean as arguments. Example: ./rm-jpg-backdoor /directory/with/images
#!/bin/sh
suff=jpg # problematic file suffix
# extended regex signatures of malware code
badregex1='eval\( *base64_decode\( *'\'
badregex2='/.+/e'
script="$0" # this script name for recursion
for f in "$@" ; do
if test -d "$f" ; then
echo "=== recursing directory $f"
find "$f" -type f -iname "*.$suff" -exec "$script" {} +
elif test -f "$f" ; then
echo "-- cleaning file $f"
hdr1="$( exiftool "$f" | grep -E ".+ +: +$badregex1" | sed -r 's/^([a-zA-Z /]*[a-zA-Z]) +: +.*$/\1/' )"
test -n "$hdr1" && { echo "removing $hdr1" ; exiftool "-$hdr1=" "$f" ; }
hdr2="$( exiftool "$f" | grep -E ".+ +: +$badregex2" | sed -r 's/^([a-zA-Z /]*[a-zA-Z]) +: +.*$/\1/' )"
test -n "$hdr2" && { echo "removing $hdr2" ; exiftool "-$hdr2=" "$f" ; }
fi
done
1Please clarify your question. What do you mean by 'catalogs'? What does the base64 decode is for? Where does the base64 encoded string come from? You probably cannot simply change/remove a string contained in an image file. – migu – 2013-10-31T09:19:34.590
I found this string in some jpg files on server. If I call image: http://host/path/to/image/image.jpg it show but when i call: http://host/path/to/image/image.jpg?zz1=myscript I can use this injection.
– Nips – 2013-10-31T09:31:20.183