当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > ASP.NET优化:Sql注入和Html注入的黑帽SEO

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

ASP.NET优化:Sql注入和Html注入的黑帽SEO


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-03-17   浏览: 239 ::
收藏到网摘: n/a

黑帽(black hat)SEO主要是指采取“不怎么道德”(暂时就这么形容吧!)的方式进行搜索引擎优化。

1. 注入攻击,包括Sql注入和Html注入。我经常能看到对Sql注入防范的谈论,但对于Html注入,很多人并没有引起足够的重视。为了展示Html注入的效果,我们模仿了一个常见的留言本功能。

首先,在页面声明中添加两个属性设置EnableEventValidation=“false” ValidateRequest=“false” ,这很关键,读者可以试一下如果不这样设置会有什么效果。

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" EnableEventValidation="false" ValidateRequest="false" %>

然后,前台页面和后台代码段分别如下:

<asp:TextBox ID="txtInput" runat="server" Height="95px" Width="405px" TextMode="MultiLine"></asp:TextBox>
        
<asp:Button ID="btnSubmit" runat="server" Text="Simple Submit"
            onclick="btnSubmit_Click" />
        
<asp:Label ID="lblShow" runat="server"></asp:Label>

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        
this.lblShow.Text = this.txtInput.Text;
    }

程序很简单,将用户输入的内容再显示出来而已。运行代码,然后输入我们的恶意代码,提交。

<p>Sanitizing <img src=""INVALID-IMAGE" onerror='location.href="http://too.much.spam/"'>!</p>

我们会发现页面自动跳转到http://too.much.spam/页面!这就是所谓的“Html注入”。当page页面render到客户端后,浏览器会按一个普通的html页面进行解析;当解析到上面的js代码时……

为了避免这种入侵,在asp.net中,我们最简单的处理方式就是对输入的内容进行“Html编码”。将后台代码改为:

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        
this.lblShow.Text = this.Server.HtmlEncode(this.txtInput.Text);
    }

现在我们再运行代码,发现源代码被原样输出显示在页面,并没有运行。为什么呢?查看输出页面的源代码:

<span id="lblShow">&lt;p&gt;Sanitizing &lt;img src=&quot;&quot;INVALID-IMAGE&quot; onerror='location.href=&quot;http://too.much.spam/&quot;'&gt;!&lt;/p&gt;</span>

整理后,我们发现如下的映射转换:

<  --  &lt;  (less than)
>  --  &gt;  (greater than)
"  --  &quot;   (quota)

所以js无法执行,但在页面显示时,我们确能看到“原汁原味”的js内容。

但问题并没有结束,现实世界中,输入的内容除了恶意代码以外,还可能有如下的内容:

<span style=" color:blue">黑帽</span>(black hat)SEO主要是指采取<span style=" color:blue">“不怎么道德”</span>(暂时就这么形容吧!)的方式进行搜索引擎优化。

我们希望显示蓝色的文字,但经过编码后,显然无法达到我们的效果。为此,我们还需要进行更精确的过滤。这也是为什么之前我们要设置EnableEventValidation=“false” ValidateRequest=“false”的现实原因。

其实我最先想到的方案是:首先对整个内容进行编码,然后把我们允许使用的html标签再替换回来。这样是相当保险的,但是在具体的操作中,遇到了很多问题,这个郁闷啊~~~(如果有谁有这种实现的实现代码,千万要拿出来大家分享一下呀)。

我先介绍另一种方案:

首先要取出标签,如,<span style=“ color:blue”>、</span>和<script >,我们的替换范围仅局限于标签 < > 之间的内容。

然后获取所有的标签名称、属性的名称和值,如果有禁止出现的内容,就替换掉。可能的恶意代码形式如下所示:

标签的名称: <script </script

标签里的属性:<span onclick

属性的值:<img onerror=“javascript:'

最后,我们对所有的“恶意单词”进行替换:

using System;
using System.Text.RegularExpressions;

/// <summary>
/// Sanitize contains functionality to remove unaccepted tags or attributes
/// </summary>
public static class Sanitize
{
  
// list of accepted/harmeless tags (in lower case)
  private static string[] allowedTags =     
    { "p""h1""b""i""a""ul""li""pre""hr""blockquote""img" };

  
// list of attributes that need to be sanitized
  private static string badAttributes =
    
"onerror|onmousemove|onmouseout|onmouseover|" +
     
"onkeypress|onkeydown|onkeyup|javascript:";

  
// sanitizes the HTML code in $inputHTML
  public static string FixTags(string inputHtml)
  {
    
// define the match evaluator
    
// MatchEvaluator 是一个委托,它调用fixTag方法
    MatchEvaluator fixThisLink = new MatchEvaluator(Sanitize.fixTag);

    
// process each tags in the input string
    string fixedHtml = Regex.Replace(inputHtml,         //需要替换的字符串
                                     "(<.*?>)",         //正则表达式:注意“?”的使用   --贪婪模式
                                     fixThisLink,       //委托“实例”做参数
                                     RegexOptions.IgnoreCase);
    
//整句代码的意思就是:将输入字符串inputHtml中能匹配上"(<.*?>)"的部分(也就是被<  >包裹的标签)用fixThisLink方法进行处理

    
// return the "fixed" input string
    return fixedHtml;
  }

  
// remove tag if is not in the list of allowed tags
  private static string fixTag(Match tagMatch)
  {
    
string tag = tagMatch.Value;

    
// extrag the tag name, such as "a" or "h1"
    Match m = Regex.Match(tag,
                          
@"</?(?<tagName>[^\s/]*)[>\s/]",       
                          RegexOptions.IgnoreCase);
    
string tagName = m.Groups["tagName"].Value.ToLower();

    
// if the tag isn't in the list of allowed tags, it should be removed
    if (Array.IndexOf(allowedTags, tagName) < 0)
    {
      
return "";
    }

    
// remove bad attributes from the tag
    string fixedTag = Regex.Replace(tag,
                        
"(" + Sanitize.badAttributes + @")(\s*)(?==)",    // 注意"?=="的意思  --正向预查
                        "SANITIZED", RegexOptions.IgnoreCase);

    
// return the altered tag
    return fixedTag;
  }
}

注意代码中两处正则表达式的高级用法,贪婪模式和正向预查,详细可参考贪婪模式和正向预查

这里我们就可以看到正则表达式说起到的强大作用——操作字符串的无上利器啊!

2. 除了注入攻击,另一种必须使用的技术是nofollow。因为Google的链接价值算法,我们都希望能有高价值的链接能指向我们的网站,以提高我们网站的等级。一种简单的方式就是到其他网站(如新浪)申请一个博客,然后在博客里添加一条链接,指向自己的网站即可。但如果我们自己是新浪,我们当然不愿意有其他人这样做(毕竟我们不知道其他人链接指向的网站究竟是好是坏,如果是一个垃圾网站,会牵连到我们自己的)。但是呢,我们也不愿意完全禁止掉链接的使用(比如简单的对链接进行编码,让链接失去作用),因为毕竟很多链接或许只是内部链接,而且一个能直接点击的链接能带来更好的用户体验。

为了解决这个问题,Google给出了一个方法,在链接中加上关键字nofollow,如下所示:

<a rel=“nofollow” href=“http://too.much.spam”>cool link</a>

这样,链接能直接点击,但不会带来链接价值——即Google不会认为你认可或推荐了该链接指向的网站。看看博客园有没有这样做,……,呵呵,好像没有,很大度哟。不过据说Google也会逐步降低链接价值的作用,谣言了,随他去吧……

就直接上代码了:

using System;
using System.Text.RegularExpressions;

/// <summary>
/// NoFollow contains the functionality to add rel=nofollow to unstusted links
/// </summary>
public static class NoFollow
{
  
// the white list of domains (in lower case)
  private static string[] whitelist =     
     { "seoasp""www.seoegghead.com""www.cristiandarie.ro" };

  
// finds all the links in the input string and processes them using fixLink
  public static string FixLinks(string input)
  {
    
// define the match evaluator
    MatchEvaluator fixThisLink = new MatchEvaluator(NoFollow.fixLink);

    
// fix the links in the input string
    string fixedInput = Regex.Replace(input,
                                      
"(<a.*?>)",
                                      fixThisLink,
                                      RegexOptions.IgnoreCase);

    
// return the "fixed" input string
    return fixedInput;
  }

  
// receives a Regex match that contains a link such as
  
// <a href="http://too.much.spam/"> and adds ref=nofollow if needed
  private static string fixLink(Match linkMatch)
  {
    
// retrieve the link from the received Match
    string singleLink = linkMatch.Value;

    
// if the link already has rel=nofollow, return it back as it is
    if (Regex.IsMatch(singleLink,
                      
@"rel\s*?=\s*?['""]?.*?nofollow.*?['""]?",
                      RegexOptions.IgnoreCase))
    {
      
return singleLink;
    }

    
// use a named group to extract the URL from the link
    Match m = Regex.Match(singleLink,
                          
@"href\s*?=\s*?['""]?(?<url>[^'""]*)['""]?",
                          RegexOptions.IgnoreCase);
    
string url = m.Groups["url"].Value;

    
// if URL doesn't contain http://, assume it's a local link
    if (!url.Contains("http://"))
    {
      
return singleLink;
    }

    
// extract the host name (such as www.cristiandarie.ro) from the URL
    Uri uri = new Uri(url);
    
string host = uri.Host.ToLower();

    
// if the host is in the whitelist, don't alter it
    if (Array.IndexOf(whitelist, host) >= 0)
    {
      
return singleLink;
    }

    
// if the URL already has a rel attribute, change its value to nofollow
    string newLink = Regex.Replace(singleLink,
             
@"(?<a>rel\s*=\s*(?<b>['""]?))((?<c>[^'""\s]*|[^'""]*))(?<d>['""]?)?",
             
"${a}nofollow${d}",
             RegexOptions.IgnoreCase);

    
// if the string had a rel attribute that we changed, return the new link
    if (newLink != singleLink)
    {
      
return newLink;
    }

    
// if we reached this point, we need to add rel=nofollow to our link
    newLink = Regex.Replace(singleLink, "<a"@"<a rel=""nofollow""",
                            RegexOptions.IgnoreCase);
    
return newLink;
  }
}