MSsQL库N多字段被批量插入恶意JS代码,清除方法如下:
最佳方式:整库清理!!!
declare @delStr varchar(8000)
set @delStr=''
set nocount on
declare @tableName nvarchar(100),@columnName nvarchar(100),@tbID int,@iRow int,@iResult int
declare @sql nvarchar(500)
set @iResult=0
declare cur cursor for
select name,id from sysobjects where xtype='U'
open cur
fetch next from cur into @tableName,@tbID
while @@fetch_status=0
begin
declare cur1 cursor for
--xtype in (231,167,239,175,99) 为char,varchar,nchar,nvarchar,ntext类型
select name from syscolumns where xtype in (231,167,239,175,99) and id=@tbID
open cur1
fetch next from cur1 into @columnName
while @@fetch_status=0
begin
set @sql='update [' + @tableName + '] set ['+ @columnName +']= replace(cast(['+@columnName+'] as varchar(8000)),'''+@delStr+''','''') where ['+@columnName+'] like ''%'+@delStr+'%'''
--update tablename set fieldA=replace(cast(fieldA as varchar(8000)) ,'aa','bb')这样的语句。
exec sp_executesql @sql
set @iRow=@@rowcount
set @iResult=@iResult+@iRow
if @iRow>0
begin
print '表:'+@tableName+',列:'+@columnName+'被更新'+convert(varchar(10),@iRow)+'条记录;'
end
fetch next from cur1 into @columnName
end
close cur1
deallocate cur1
fetch next from cur into @tableName,@tbID
end
print '数据库共有'+convert(varchar(10),@iResult)+'条记录被更新!!!'
close cur
deallocate cur
set nocount off
第一种:适用于挂马字段不多,或MSSQL权限不高的用户,需要逐个表逐个字段去清理,每次清理一个字段
update 表名 set 字段=replace(字段,'恶意代码','')
第二种:批量整库清理
DECLARE hCForEach CURSOR GLOBAL
FOR
Select N'update '+QUOTENAME(o.name)
+N' set '+ QUOTENAME(c.name) + N' = replace(' + QUOTENAME(c.name) + ',''《script src=http://hack.hackeye.com/cn.js》《/script》'','''')'
FROM sysobjects o,syscolumns c,systypes t
Where o.id=c.id
AND OBJECTPROPERTY(o.id,N'IsUserTable')=1
AND c.xusertype=t.xusertype
AND t.name IN('varchar','nvarchar','char','nchar','text')
EXEC sp_MSforeach_Worker @command1=N'?'
其中《script src=http://hack.hackeye.com/cn.js》《/script》为要查找的插入的js内容
------------------------------
当你想用SQL语句处理ntext型字段的时候会提示错误:参数数据类型 ntext 对于 replace 函数的参数 1 无效。
你可以用下面的方法解决:
1、varchar和nvarchar类型是支持replace,所以如果你的text不超过8000可以先转换成前面两种类型再使用replace。
update 表名
set 字段名=replace(convert(varchar(8000),字段名),'要替换的字符','替换成的值')
2、如果你的text大于8000,可以用下面的方法:
--测试数据
CREATE TABLE tb(col ntext)
INSERT tb VALUES(REPLICATE( '0001,0002,0003,0004,0005,0006,0007,0008,0009,0100,'
+'220000001,302000004,500200006,700002008,900002120,',800))
DECLARE @p binary(16)
SELECT @p=TEXTPTR(col) FROM tb
UPDATETEXT tb.col @p NULL 0 tb.col @p
GO
--替换处理定义
DECLARE @s_str nvarchar(1000),@r_str nvarchar(1000)
SELECT @s_str='00' --要替换的字符串
,@r_str='0000' --替换成该字符串
DECLARE @p varbinary(16)
DECLARE @start int,@s nvarchar(4000),@len int
DECLARE @s_len int,@step int,@last_repl int,@pos int
--替换处理参数设置
SELECT
--用于要判断每次截取数据,最后一个被替换数据位置的处理
@s_len=LEN(@s_str),
--设置每次应该截取的数据的长度,防止REPLACE后数据溢出
@step=CASE WHEN LEN(@r_str)>LEN(@s_str)
THEN 4000/LEN(@r_str)*LEN(@s_str)
ELSE 4000 END
--替换处理的开始位置
SELECT @start=PATINDEX('%'+@s_str+'%',col),
@p=TEXTPTR(col),
@s=SUBSTRING(col,@start,@step),
@len=LEN(@s),
@last_repl=0
FROM tb
WHERE PATINDEX('%'+@s_str+'%',col)>0
AND TEXTVALID('tb.col',TEXTPTR(col))=1
WHILE @len>=@s_len
BEGIN
--得到最后一个被替换数据的位置
WHILE CHARINDEX(@s_str,@s,@last_repl)>0
SET @last_repl=@s_len
+CHARINDEX(@s_str,@s,@last_repl)
--如果需要,更新数据,同时判断下一个取数位置的偏移量
IF @last_repl=0
SET @last_repl=@s_len
ELSE
BEGIN
SELECT @last_repl=CASE
WHEN @len<@last_repl THEN 1
WHEN @len-@last_repl>=@s_len THEN @s_len
ELSE @len-@last_repl+2 END,
@s=REPLACE(@s,@s_str,@r_str),
@pos=@start-1
UPDATETEXT TB.col @p @pos @len @s
END
--获取下一个要处理的数据
SELECT @start=@start+LEN(@s)-@last_repl+1,
@s=SUBSTRING(col,@start,@step),
@len=LEN(@s),
@last_repl=0
FROM tb
END
GO
--显示处理结果
SELECT datalength(col),* FROM tb
DROP TABLE tb
上面说的是针对ntext字段的替换处理,如果要处理text字段,只需要先转换成ntext字段然后保存在临时表里面,处理完以后再从临时表写回text就行了。
其实一般象text,ntext字段这些都是抓到程序里面去处理的。