SQL替换可变内容的查询

时间:2016-05-09 20:49:05

标签: sql sql-server

我正在寻找一个SQL查询来清理被黑客入侵的SQL Server数据库。我有一些基本的SQL知识,但我不知道如何解决以下问题。

对于我们的某个网站,我们有一个最近被黑客入侵的SQL Server数据库。成千上万的记录充满了隐藏的div,包含各种狡猾的引用。我们的ISP说数据库的内容不是他们的责任,他们不知道如何帮助我们清理数据库。没有可用的干净备份。手动浏览所有记录太过分了。

所以我现在拼命想找到一个SQL查询来从数据库中删除这些隐藏文本块。

两个有用的信息:

  1. 所有垃圾内容都包含在div标签中。标签之间的信息在每个实例中都是不同的,但它们都使用div标签打开和关闭。

  2. 我们的原始数据将包含一些HTML内容,但绝不会包含div标签。因此,如果我们能找到一种方法来删除从起始div到包括结束div的所有内容,那么我们将进行排序。

  3. 非常感谢这里的任何帮助。谢谢你的时间。

3 个答案:

答案 0 :(得分:2)

试试这个;只有在你的假设是正确的情况下才会有用。黑客的另一个假设是没有添加嵌套的DIV。是的,在运行更新之前彻底测试它。并在运行更新之前备份您的数据。

CREATE TABLE #temp(id INT IDENTITY, html VARCHAR(MAX));

INSERT #temp(html)
VALUES('<p>Some text</p><strong>other text</strong><div>added by hacker</div>')
,('<p>Some text</p><strong>other text<div>added by hacker within html tag</div></strong>')
,('<p>Some text</p><div>some other text added by <a href="http://google.com">hack</a></div><strong>other text</strong>');


SELECT html
,  CHARINDEX('<div',html) AS startPos
, CHARINDEX('</div>',html) AS endPos
, (CHARINDEX('</div>',html)+6)-(CHARINDEX('<div',html)) AS stringLenToRemove
, SUBSTRING(html, CHARINDEX('<div',html), (CHARINDEX('</div>',html)+6)-(CHARINDEX('<div',html))) AS HtmlAddedByHack
,REPLACE(html,SUBSTRING(html, CHARINDEX('<div',html), (CHARINDEX('</div>',html)+6)-(CHARINDEX('<div',html))), '') AS sanitizedHtml
FROM #temp;

--UPDATE #temp
--SET html = REPLACE(html,SUBSTRING(html, CHARINDEX('<div',html), (CHARINDEX('</div>',html)+6)-(CHARINDEX('<div',html))), '');

--SELECT  *
--FROM    #temp;

答案 1 :(得分:1)

使用PATINDEX的UDF可能会这样做。

假设

  • 所有恶意内容都在<DIV>...</DIV>部分
  • 不存在恶意内容
  • <DIV>...</DIV>个部分
  • 在将数据应用到您的实时数据库之前,您可以继续测试数据

首先使用此UDF进行模式替换,来自here

CREATE FUNCTION dbo.PatternReplace
(
   @InputString VARCHAR(4000),
   @Pattern VARCHAR(100),
   @ReplaceText VARCHAR(4000)
)
RETURNS VARCHAR(4000)
AS
BEGIN
   DECLARE @Result VARCHAR(4000) SET @Result = ''
   -- First character in a match
   DECLARE @First INT
   -- Next character to start search on
   DECLARE @Next INT SET @Next = 1
   -- Length of the total string -- 8001 if @InputString is NULL
   DECLARE @Len INT SET @Len = COALESCE(LEN(@InputString), 8001)
   -- End of a pattern
   DECLARE @EndPattern INT

   WHILE (@Next <= @Len) 
   BEGIN
      SET @First = PATINDEX('%' + @Pattern + '%', SUBSTRING(@InputString, @Next, @Len))
      IF COALESCE(@First, 0) = 0 --no match - return
      BEGIN
         SET @Result = @Result + 
            CASE --return NULL, just like REPLACE, if inputs are NULL
               WHEN  @InputString IS NULL
                     OR @Pattern IS NULL
                     OR @ReplaceText IS NULL THEN NULL
               ELSE SUBSTRING(@InputString, @Next, @Len)
            END
         BREAK
      END
      ELSE
      BEGIN
         -- Concatenate characters before the match to the result
         SET @Result = @Result + SUBSTRING(@InputString, @Next, @First - 1)
         SET @Next = @Next + @First - 1

         SET @EndPattern = 1
         -- Find start of end pattern range
         WHILE PATINDEX(@Pattern, SUBSTRING(@InputString, @Next, @EndPattern)) = 0
            SET @EndPattern = @EndPattern + 1
         -- Find end of pattern range
         WHILE PATINDEX(@Pattern, SUBSTRING(@InputString, @Next, @EndPattern)) > 0
               AND @Len >= (@Next + @EndPattern - 1)
            SET @EndPattern = @EndPattern + 1

         --Either at the end of the pattern or @Next + @EndPattern = @Len
         SET @Result = @Result + @ReplaceText
         SET @Next = @Next + @EndPattern - 1
      END
   END
   RETURN(@Result)
END

然后,使用UDF:

UPDATE ContentTable SET ContentColumn=dbo.PatternReplace('<DIV>%</DIV>', '')

答案 2 :(得分:1)

也许像这样的光标......

Declare @ColumnName sysname , @TableName sysname 
        ,@Schema sysname , @Sql Nvarchar(MAX);

Declare Cur CURSOR FOR 
Select c.name , t.name , s.name
from sys.columns c 
inner join sys.tables  t on c.object_id = t.object_id
inner join sys.types   p on p.user_type_id = c.user_type_id
inner join sys.schemas s on t.schema_id = s.schema_id
where t.is_ms_shipped = 0
and p.name in ('varchar','nvarchar', 'char', 'nchar')

OPEN Cur 

 FETCH NEXT FROM Cur INTO @ColumnName , @TableName , @Schema

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @Sql = N'UPDATE '+ QUOTENAME(@Schema) +'.' + QUOTENAME(@TableName) 
             + N' SET ' + QUOTENAME(@ColumnName) + N' = '
             + N'LEFT(' + QUOTENAME(@ColumnName) + N', CHARINDEX(''<div>'', 
                          ' + QUOTENAME(@ColumnName) + N') - 1) 
                      + SUBSTRING(' + QUOTENAME(@ColumnName) + N', 
                      CHARINDEX(''</div>'', ' + QUOTENAME(@ColumnName) + N') + 6
                      , LEN(' + QUOTENAME(@ColumnName) + N'))
                Where ' + QUOTENAME(@ColumnName) + N' IS NOT NULL 
                AND LEN(' + QUOTENAME(@ColumnName) + N') > 6' 

     Exec sp_executesql @Sql 

     FETCH NEXT FROM Cur INTO @ColumnName , @TableName , @Schema
END 

CLOSE Cur 
DEALLOCATE Cur

注意

游标遍历所有表并选择具有varchar , nvarchar, char ,nchar数据类型的列,然后创建一个更新语句以去除<div> </div>标记之间的任何字符串(如果存在),否则保留列为它是。

警告

在对实时数据库实际运行脚本之前测试脚本。