MySQL strip_tag Function

A client came to us with over 10,000 posts on their WordPress website that had been infected with malicious Javascript …

<noindex><script id=”wpinfo-pst1″ type=”text/javascript” rel=”nofollow”>eval( … )</script></noindex>

So to remove this script from each post manually would take forever and reverting to a backup wasn’t possible as the client hadn’t realised this had happened and the compromise pre-dated any backup still held.

Unfortunately on the client’s version of MySQL REGEXP_REPLACE() does not exist so we created the following stored procedure …

DROP FUNCTION strip_tag;
 CREATE FUNCTION strip_tag(content LONGTEXT, tag TINYTEXT) RETURNS LONGTEXT CHARSET utf8 DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER BEGIN 
   DECLARE tagstart, tagend INT DEFAULT 0; 
   SET tagstart = LOCATE(CONCAT('<', tag), content);   IF (!tagstart) THEN     RETURN content;   END IF;   SET tagend = LOCATE(concat(tag, '>'), content, tagstart + LENGTH(CONCAT('<', tag)));   IF (!tagend) THEN     SET tagend = LOCATE('>', content, tagstart + LENGTH(CONCAT('<', tag)));   ELSE     SET tagend = tagend + LENGTH(concat(tag, '>'));
   END IF;
   IF (!tagend) THEN
     RETURN content;
   ELSE
     SET tagend = tagend + 1;
   END IF;
   IF (tagstart = 1) THEN
     RETURN SUBSTRING(content, tagend);
   ELSE
     RETURN CONCAT(SUBSTRING(content, 1, tagstart - 1), SUBSTRING(content, tagend));
   END IF;
 END

This function can then be used as follows to remove all instances of this malicious JavaScript …

UPDATE wp_posts SET post_content=strip_tag(post_content, 'noindex') WHERE post_content LIKE '%<noindex%';

Make sure you backup your database before doing anything, though. Just in case something goes wrong.