Flashback trojan EA

rmanly
Contributor III

I just threw this together - mostly as an excuse to play with named pipes. It will tell you if one of the big 3 browsers or non-hidden users are infected with Flashback.

*IF* I actually find it anywhere I will come up with something to remove it.

#!/bin/bash

app_list=()

mkfifo result_fifo
cat < result_fifo &
exec 3>result_fifo

echo "<result>"

while read -r -d $'�'; do
    app_list+=("$REPLY")
done < <(find / ( -iname "google chrome.app" -o -iname "safari.app" -o -iname "firefox.app" ) -print0 2> /dev/null)

for browser in "${app_list[@]}"; do
    defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null && echo "${browser} is infected" >&3
done

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
    defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null && echo "user ${username} is infected" >&3
done

exec 3>&-
unlink result_fifo

echo "</result>"

p.s. It would be REALLY awesome if the EA display in the JSS supported newlines again.

3 ACCEPTED SOLUTIONS

donmontalvo
Esteemed Contributor III

...is there a way to create a Smart Computer Group that will show any computers that are infected? This way we can set up an alert.

Don

--
https://donmontalvo.com

View solution in original post

rmanly
Contributor III

Here is what I use now. I upgraded to 8.51 so as I mentioned before there is now newlines so it makes sense to add back in the "Not infected" as some have asked for. That means you will have to change the Smart group for all of them to "like is infected" instead of just "like infected"

#!/bin/bash

app_list=()

echo "<result>"

while read -r -d $'�'; do
    app_list+=("$REPLY")
done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -0 2> /dev/null)

for browser in "${app_list[@]}"; do
    if defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null; then
         echo "${browser} is infected"
    else
        echo "${browser} is NOT infected"
    fi
done

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
    if defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null; then
        echo "user ${username} is infected"
    else
        echo "user ${username} is NOT infected"
    fi
done

echo "</result>"

Here is what the output looks like on the command line now.

<result>
/Applications/Safari.app is NOT infected
/Applications/Google Chrome.app is NOT infected
/Applications/Firefox.app is NOT infected
user bob is NOT infected
user macports is NOT infected
user ryan is NOT infected
</result>

And here is the result in the JSS

/Applications/Google Chrome.app is NOT infected
/Applications/Firefox.app is NOT infected
/Applications/Safari.app is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user rmanly_stu is NOT infected

student usernames converted to ---- and trimmed for public posting

View solution in original post

rmanly
Contributor III

RUN SOFTWARE UPDATE

https://support.apple.com/kb/HT5242

View solution in original post

44 REPLIES 44

sean
Valued Contributor

cvgs
Contributor II

Mmh, pipes!

But why not replace "find" with "mdfind" to make use of the awesome speed of spotlight? You could even leave out "-onlyin /" to search all local volumes in lightning speed...

# /usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") '
/Applications/Firefox.app
/Applications/Safari.app
/Applications/Google Chrome.app

jhalvorson
Valued Contributor

Related topic: This might grow into a bigger problem. Now I am worried about all of the websites offering scripts that promise to check and clean the Mac from the flashback trojan.

rmanly
Contributor III

@cvgs Ohh that is much faster :)

Nice.

rmanly
Contributor III

@sean I thought I had voted up on that a while ago but just did it again.

It is pretty annoying. My original script for this had an if then else statement for the checks so it would go

/Application/Safari.app is NOT infected
/Application/Firefox.app is infected
rmanly is infected

etc..but on student machines with tons of mobile accounts the result was incomprehensible without newlines so I took out all the NOTs

donmontalvo
Esteemed Contributor III

This EA is very helpful, thanks!!!

--
https://donmontalvo.com

solomonacquah
New Contributor

Has anyone found a threat yet?

solomonacquah
New Contributor

!/bin/bash

#Would this work? How would I echo back that the computer is not infected?

SAFARI_BROWSERS=$(/usr/bin/mdfind "kMDItemCFBundleIdentifier == 'com.apple.safari'")

echo "<result>"

defaults read "$SAFARI_BROWSERS"/Contents/Info LSEnvironment 2> /dev/null && echo "$SAFARI_BROWSERS" is infected"" 2>&1

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do

defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null && echo "user ${username} is infected" 2>&1

done

echo "</result>"

jwojda
Valued Contributor II

when I tried the EA with the mfind tweak all I get is

/private/tmp/extensionAttributeScript: line 25: syntax error near unexpected token `<' /private/tmp/extensionAttributeScript: line 25: `done < </usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ''

talkingmoose
Moderator
Moderator

That modified line should look like this:

done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -print0 2> /dev/null)

jwojda
Valued Contributor II

that got passed that line - but now it's returning

/private/tmp/extensionAttributeScript: line 56: syntax error: unexpected end of file

However, i went back and counted the lines in the EA - and it's only 37 lines...... unless I stretch the box out then it's 28...

talkingmoose
Moderator
Moderator

This is Ryan's script with Christoph's suggested mdfind modification. I added another check for /Users/Shared/.libgmalloc.dylib.

#!/bin/bash

app_list=()

mkfifo result_fifo
cat < result_fifo &
exec 3>result_fifo

echo "<result>"

while read -r -d $'�'; do
    app_list+=("$REPLY")
done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -print0 2> /dev/null)

for browser in "${app_list[@]}"; do
    defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null && echo "${browser} is infected" >&3
done

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
    defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null && echo "user ${username} is infected" >&3
done

if [[ -f /Users/Shared/.libgmalloc.dylib ]]; then
    echo "/Users/Shared/ is infected" >&3
fi

exec 3>&-
unlink result_fifo

echo "</result>"

Efren
New Contributor
New Contributor

First, a big "Thank you" to everyone for the script and modifications.

My question, I know how to make a policy to run this but how do I get it to report back to me on what computers are infected?

When I run it on a couple of my test computers, I have to actually view each computer's install log to see the result.

Thanks again and I apologize for the ignorant question.

golbiga
Contributor III
Contributor III

I wouldn't create a policy. Just create an Extension Attribute and recon your machines or wait for them to check in and provide an inventory. If you have Smart Group that checks the Extension Attribute for "like" infected and check off Send Email Notification on Change that should take care of it.

Efren
New Contributor
New Contributor

Thanks Golbiga....

It's a Friday... I'm forgetting everything I learned it seems.

Enjoy the weekend everyone!

jhalvorson
Valued Contributor

Thanks for crafting the scripts!

A note confirming speed improvement with using talkingmoose's script compared to the first one posted by rmanly. recon time went from 5m 04s down to 2m 34s on my test device.

So far none discovered. I am tempted figure out how to fake my test device so I know the detection is working.

jwojda
Valued Contributor II

This is great! thank you! It's completing VERY quickly now.

Is the only output should be infected? If it's clean then there is nothing output?

gregp
Contributor

@talkingmoose- Just a slight modification to your last script... shouldn't be a -print0, but a -0.

done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -0 2> /dev/null)

Unsure about elsewhere, but my few test systems don't have kMDItemCFBundleIdentifier for Safari. So, instead for that one, I'm using kMDItemFSName == "Safari.app". The other two apps have kMDItemCFBundleIdentifier.

And thanks to rmanly, talkingmoose and cvgs for the code. Really quite useful.

sean
Valued Contributor

You may get a faster response doing an onlyin, but there is nothing to say that Firefox or Chrome could be anywhere on the system.

You may also wish to check launchctl for a set environment variable "DYLD_INSERT_LIBRARIES". You could run this as a login hook

Something like:

userPID=`ps -ef | grep "loginwindow console" | grep -v grep | awk '{print $2}'`

launchctl bsexec $userPID su $3 -c 'launchctl getenv DYLD_INSERT_LIBRARIES'

Write the response to your own file, plist for example and make an EA against that and you can remove it with the unset option.

rob_potvin
Contributor III
Contributor III

@sean

Could you elaborate on what you mean on your last post? Write out the output to plist and EA that output?

Cheers

vescala
New Contributor

Thought you all would like to know that we got a positive hit over here using the original EA posted by Ryan. About to update with the version posted by William. Thank you Ryan, Christoph, and William for your work on this.

Now..any suggestions on automating removal of Flashback?

rmanly
Contributor III

Got two hits here right after lunch.

@vescala I will work on a script for removing it this afternoon.

I would have done it last Thursday but I got distracted figuring out how to disable Java in all the browsers via script.

rmanly
Contributor III

FYI here is the output of my original and how it shows up in the JSS.

Because the output of the the check on the user points to the common /Users/Shared/.libgmalloc.dylib I don't think that needs to be checked for seperately. It's existence is part of the User being infected.

https://skitch.com/feydrmm/8t377/computer-details--glenbrook-225--jssv8.51

https://skitch.com/feydrmm/8t37w/computer-details--glenbrook-225--jssv8.51

Here is the text of the second screenie.

{
"DYLD_INSERT_LIBRARIES" = "/Applications/Safari.app/Contents/Resources/.IntenetTweak.xsl";
}

sean
Valued Contributor

@rpotvin

You could just run unsetenv and forget about it. Alternatively, if you want a report on it, you need to provide an answer to it somewhere. Since you would like to know if this variable is set on each user, network or local, then you need to run this command against users when they are logged in, so you can't really just use an EA for this. Hence, run the getenv as a login script and redirect the output to a file, any file you like, so send it to the system.log, create your own log or make you own plist, text file, etc, your choice.

Create an EA that will read the above created file. If you want an immediate report from this file, then you would want to also include a jamf recon at the end of the login script.

I haven't concisely read the docs on launchd to work out if there is a way to read the users environment variables without them being logged in, but if I get a chance I will.

Sean

solomonacquah
New Contributor

Nice tool created for this FYI.

https://github.com/jils/FlashbackChecker/downloads

donmontalvo
Esteemed Contributor III

Jumping on this thread a bit late. I see a couple scripts on this page and a few suggestions...is there a final version that I can grab?

Thanks,
Don

--
https://donmontalvo.com

damienbarrett
Valued Contributor

I received a positive hit this morning using the script from "talkingmoose" posted above. However, in JSS when I view details on this "infected" computer, I see this listed for the EA's value:

/Users/Shared/.mcafeevirusenterprise.so user [username redacted] is infected

Does this make any sense to anyone? I was expecting it to tell me that Firefox or Safari were infect, not something about mcafee.

talkingmoose
Moderator
Moderator

You're actually seeing two lines but the JSS is not handling the carriage return between them.

Did you see Greg's correction just after I posted the modified script? Replace "-print0" with "-0" and see if that makes a difference. I don't think the "/Users/Shared/.mcafeevirusenterprise.so" line should be there.

damienbarrett
Valued Contributor

Ah, nope, missed that post! Thanks for the correction. I've changed the script my EA and will see what happens.

donmontalvo
Esteemed Contributor III

Ok so here is @talkingmoose's script with the edit (replace "-print0" with "-0"):

#!/bin/bash

app_list=()

mkfifo result_fifo
cat < result_fifo &
exec 3>result_fifo

echo "<result>"

while read -r -d $'�'; do
    app_list+=("$REPLY")
done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -0 2> /dev/null)

for browser in "${app_list[@]}"; do
    defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null && echo "${browser} is infected" >&3
done

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
    defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null && echo "user ${username} is infected" >&3
done

if [[ -f /Users/Shared/.libgmalloc.dylib ]]; then
    echo "/Users/Shared/ is infected" >&3
fi

exec 3>&-
unlink result_fifo

echo "</result>"
--
https://donmontalvo.com

donmontalvo
Esteemed Contributor III

...is there a way to create a Smart Computer Group that will show any computers that are infected? This way we can set up an alert.

Don

--
https://donmontalvo.com

damienbarrett
Valued Contributor

Yeah, Don, that's pretty easy. The script's output contains the words "is infected" (and no output if a machine is not infected), so you can easily create a Smart group to show any machines with this particular Extension Attribute's value set to "like" "infected".

rmanly
Contributor III
I received a positive hit this morning using the script from "talkingmoose" posted above. However, in JSS when I view details on this "infected" computer, I see this listed for the EA's value: /Users/Shared/.mcafeevirusenterprise.so user [username redacted] is infected Does this make any sense to anyone? I was expecting it to tell me that Firefox or Safari were infect, not something about mcafee.

What you are seeing is the file to check for the next steps of cleaning the virus.

If you look at my post for the User cleaner and run that against this user WHILE THE USER IS LOGGED IN TO CLEAN LAUNCHD then you will be able to get rid of it for them.

If you look at Step 10 on this page https://www.f-secure.com/v-descs/trojan-downloader_osx_flashback_i.shtml the file that is showing up in your result

/Users/Shared/.mcafeevirusenterprise.so

is the path you would fill in for "%path_obtained_in_step9% " if you were cleaning by hand.

Hope this helps.

Here is my user cleaner script.
https://jamfnation.jamfsoftware.com/discussion.html?id=4219

rmanly
Contributor III
...is there a way to create a Smart Computer Group that will show any computers that are infected? This way we can set up an alert. Don

I made 3 Smart Groups.

Like Damien I started with one that was only "like infected"

When it became apparent that I was only seeing infections in Safari and in the Users I created two additional groups for "like user" and "like safari"

And I created these:

https://jamfnation.jamfsoftware.com/discussion.html?id=4219
https://jamfnation.jamfsoftware.com/discussion.html?id=4220

rmanly
Contributor III

...and we need a way to unmark an answer cuz I totally just meant to reply and wasn't thinking/looking at the buttons

rmanly
Contributor III

...and we need a way to unmark an answer cuz I totally just meant to reply and wasn't thinking/looking at the buttons

Vote this up if you agree ;)
https://jamfnation.jamfsoftware.com/featureRequest.html?id=165

rmanly
Contributor III
You're actually seeing two lines but the JSS is not handling the carriage return between them. Did you see Greg's correction just after I posted the modified script? Replace "-print0" with "-0" and see if that makes a difference. I don't think the "/Users/Shared/.mcafeevirusenterprise.so" line should be there.

If you upgrade to 8.51 you will get newlines in EA display again *WOOT!*

Also, the output SHOULD be there as it tells you what to do next in the F-Secure steps for manual removal.

The reason it is there scripting wise is because of the way I chose to do the redirection.

For example in this line:

defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null && echo "${browser} is infected" >&3

the stderr of the defaults command gets redirected to /dev/null with "2>" but the stdout is not redirected. Then the echo is redirected file descriptor 3.

What I intended to do in the first version, which is send everything to 3 would require command grouping with {}. But ultimately none of that is really necessary.

p.s. I actually am watching tutorials on how to use git now because I have been making improvements since posting this and not posting the changes...like after realizing all the fifo nonsense was stupid and unnecessary... :P

rmanly
Contributor III

Here is what I use now. I upgraded to 8.51 so as I mentioned before there is now newlines so it makes sense to add back in the "Not infected" as some have asked for. That means you will have to change the Smart group for all of them to "like is infected" instead of just "like infected"

#!/bin/bash

app_list=()

echo "<result>"

while read -r -d $'�'; do
    app_list+=("$REPLY")
done < <(/usr/bin/mdfind -onlyin / ' (kMDItemCFBundleIdentifier == "com.apple.Safari") || (kMDItemCFBundleIdentifier == "com.google.Chrome") || (kMDItemCFBundleIdentifier == "org.mozilla.firefox") ' -0 2> /dev/null)

for browser in "${app_list[@]}"; do
    if defaults read "${browser}"/Contents/Info LSEnvironment 2> /dev/null; then
         echo "${browser} is infected"
    else
        echo "${browser} is NOT infected"
    fi
done

for username in $(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }'); do
    if defaults read /Users/"${username}"/.MacOSX/environment DYLD_INSERT_LIBRARIES 2> /dev/null; then
        echo "user ${username} is infected"
    else
        echo "user ${username} is NOT infected"
    fi
done

echo "</result>"

Here is what the output looks like on the command line now.

<result>
/Applications/Safari.app is NOT infected
/Applications/Google Chrome.app is NOT infected
/Applications/Firefox.app is NOT infected
user bob is NOT infected
user macports is NOT infected
user ryan is NOT infected
</result>

And here is the result in the JSS

/Applications/Google Chrome.app is NOT infected
/Applications/Firefox.app is NOT infected
/Applications/Safari.app is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user ---- is NOT infected
user rmanly_stu is NOT infected

student usernames converted to ---- and trimmed for public posting

rmanly
Contributor III

RUN SOFTWARE UPDATE

https://support.apple.com/kb/HT5242