ASP.NET的SEO:SEO Hack --- Html注入和Nofollow

简介: ASP.NET的SEO:目录  黑帽(black hat)SEO主要是指采取“不怎么道德”(暂时就这么形容吧!)的方式进行搜索引擎优化。1. 注入攻击,包括Sql注入和Html注入。我经常能看到对Sql注入防范的谈论,但对于Html注入,很多人并没有引起足够的重视。

ASP.NET的SEO:目录 

 

黑帽(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 "   %>

然后,前台页面和后台代码段分别如下:
img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
         < 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:"
最后,我们对所有的“恶意单词”进行替换:
img_405b18b4b6584ae338e0f6ecaf736533.gif 代码


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也会逐步降低链接价值的作用,谣言了,随他去吧……
就直接上代码了:

img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
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;
  }
}
相关文章
|
9月前
|
Web App开发 数据采集 编解码
html/SEO:mate/百度规则下写好mate标签的重要性
html/SEO:mate/百度规则下写好mate标签的重要性
67 0
|
5月前
|
开发框架 前端开发 JavaScript
Asp.net动态加载用户自定义控件,并转换成HTML代码
Asp.net动态加载用户自定义控件,并转换成HTML代码
26 0
|
9月前
|
开发框架 前端开发 安全
ASP.NET Core MVC 从入门到精通之Html辅助标签补充及模型校验基础
ASP.NET Core MVC 从入门到精通之Html辅助标签补充及模型校验基础
93 0
|
9月前
|
开发框架 前端开发 .NET
ASP.NET Core MVC 从入门到精通之Html辅助标签(一)
ASP.NET Core MVC 从入门到精通之Html辅助标签(一)
73 0
|
XML 开发框架 前端开发
在ASP.Net Core下,Autofac实现自动注入
在ASP.Net Core下,Autofac实现自动注入
196 0
在ASP.Net Core下,Autofac实现自动注入
|
前端开发
react项目实战学习笔记-学习32-注入html
react项目实战学习笔记-学习32-注入html
56 0
react项目实战学习笔记-学习32-注入html
|
数据采集 搜索推荐 SEO
SEO中HTML代码标签对应的权重
SEO中HTML代码标签对应的权重
149 0
|
存储 开发框架 前端开发
ASP.NET MVC5----了解我们使用的@HTML帮助类
ASP.NET MVC5----了解我们使用的@HTML帮助类
241 0
ASP.NET MVC5----了解我们使用的@HTML帮助类
|
Web App开发 JavaScript 前端开发
html转义及如何防止javascript注入攻击
有的时候页面中会有一个输入框,用户输入内容后会显示在页面中,类似于网页聊天应用。如果用户输入了一段js脚本,比例:,页面会弹出一个对话框,或者输入的脚本中有改变页面js变量的代码则会时程序异常或者达到跳过某种验证的目的。
2870 0
|
JavaScript SEO
调试 SAP Spartacus 服务器端渲染 SEO HTML Tag 生成逻辑的注意事项
调试 SAP Spartacus 服务器端渲染 SEO HTML Tag 生成逻辑的注意事项
79 0
调试 SAP Spartacus 服务器端渲染 SEO HTML Tag 生成逻辑的注意事项