谢谢大家的关注

关于web应用程序安全的思考(序)中我曾提到﹕web应用程序的安全不应该依赖于客户端的请求信息。

众所周知﹐http协议是开放的﹐因此谁都能向网络上公开的web服务器发送request请求﹐要求一个URL(Uniform Resource Locator 统一资源定位符)

所谓request﹐不过是符合http协议(即遵守http请求语法)的一大段字符串而已﹕

下面是一个aspx的请求示例﹕

GET /FrameWorkService/TestRequest.aspx HTTP/1.1
Connection: Keep
-Alive
Accept: 
*/*
Accept
-Encoding: gzip, deflate
Accept
-Language: zh-tw
Host: localhost
User
-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)
UA
-CPU: x86

 

 

下面是一个web service的请求示例﹕

POST /testwssecurity/service2.asmx HTTP/1.1
Content
-Length: 288
Content
-Type: text/xml; charset=utf-8
Expect: 
100-continue
Host: localhost
User
-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.42)
SOAPAction: 
"http://tempuri.org/HelloWorld"

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><HelloWorld xmlns="http://tempuri.org/" /></soap:Body></soap:Envelope>

 

相信大家基本上能理解上述字符串的意义。这表明我们只要组织类似的字符串﹐然后发往相应的web服务器﹐就可以请求到某个URL了﹐也就是说web请求不依赖浏览器(其实web也不依赖服务器﹐它只依赖http协议)

下面的这个程序是C#写的通过socket直接向web服务器发送http请求的示例﹕

 

 1关于web应用程序安全的思考(一)using System;
 2关于web应用程序安全的思考(一)using System.Text;
 3关于web应用程序安全的思考(一)using System.IO;
 4关于web应用程序安全的思考(一)using System.Net;
 5关于web应用程序安全的思考(一)using System.Net.Sockets;
 6关于web应用程序安全的思考(一)
 7关于web应用程序安全的思考(一)public class server
 8}

 

 相關的aspx.cs程序如下﹕

关于web应用程序安全的思考(一)using System;
关于web应用程序安全的思考(一)
using System.Data;
关于web应用程序安全的思考(一)
using System.Configuration;
关于web应用程序安全的思考(一)
using System.Collections;
关于web应用程序安全的思考(一)
using System.Web;
关于web应用程序安全的思考(一)
using System.Web.Security;
关于web应用程序安全的思考(一)
using System.Web.UI;
关于web应用程序安全的思考(一)
using System.Web.UI.WebControls;
关于web应用程序安全的思考(一)
using System.Web.UI.WebControls.WebParts;
关于web应用程序安全的思考(一)
using System.Web.UI.HtmlControls;
关于web应用程序安全的思考(一)
using System.IO;
关于web应用程序安全的思考(一)
关于web应用程序安全的思考(一)
public partial class TestRequest : System.Web.UI.Page
}

aspx頁面:

>

 

由上可知﹐web服务器对于请求方的识别能力是很低的。因此作为web应用程序安全管控的唯一依据就只能是request的url了﹐因为只有它才是真实的﹐而我们进行安全管控的最终目的也就是

判断这个请求方是否拥有这个url的权限(即授权)

这就是我抽象出来的web安全管控的本质﹐依据这点﹐我们就可以把web安全管控和业务系统进行解耦。即在request到达其请求的url之前﹐先对这个url和请求方进行权限验证﹐如果通过﹐我们就放它过去﹐什么都不做﹐如果不通过﹐我们就可以向客户端发送相关的拒绝信息﹐并不让web服务器真正执行到那个url﹐完成安全管控。

 web安全管控中﹐授权的除了要识别授权的客体(URL)之外﹐我们还必须识别授权的主体﹐即请求方的认定﹐也就是常说的认证机制。

 由于http协议无状态的特点﹐每次request时﹐web服务器都无法识别这个请求是否和上次的请求是否相同。因此认证机制在某种程度上来说其实相当困难。

曾经遇到过通过IP来认证的﹐先不说这种机制对于web可以anywhere访问是一种倒退﹐单是那种IP更改﹐欺骗或通过Proxy访问就无法适用了。

现在最多的做法还是通过cookiesession来完成的。

不过最好还是清楚一下cookiesession的原理﹕

Cookiecookie其实也是http request header的一部分﹐我们可以把任何值当作cookie发给web服务器。

至于Session,不知道大家有没有看过.netsession实现机制﹐每次请求后﹐.net会写入一个session_idcookie到客户端﹐这样在下次客户再请求时﹐提取这个cookie来识别。剩下的就和cookie一样了。


大家可以看一下我上面這個例子﹐在那支request請求的程式中加入相關的session_id的cookie﹐你會發現程式是無法識別是不是真正的session的 

曾经有人设计过这样一个系统﹐要我尝试攻入其中某个已管控的页面中。

它是这样做的﹐在每个要权限的aspx页面的page_load中判断Session["userid"]是否为null,如果不是﹐则转向登录页面。

 

在我截获了网络上某个已登录用户和web服务器通讯的requestresponse之后﹐提取其cookie信息﹐交将它放入我的request请求中﹐我就以那个登录用户的身份执行了那支程序了。

 

但是这并不是说就不能使用cookiesession来作为认证的机制﹐我的意思是﹐web应用程序的安全也是相对的﹐必须建立在基本的网络安全和用户安全防范意识之上。可以采取包括加密会关键页面(如登录页面)的会话(例如使用https)或要求用户每次使用完系统后注销或关闭浏览器﹐以及尽可能多的对cookiesession做更多验证等。

 

在认证和授权的原理讲完后﹐要在asp.net应用程序中要完成上述的安全管控其实非常简单﹐设计一个httpmodule﹐然后捕获相关的事件﹐在这个事件中进行权限判断即可。

下面是一些框架代碼﹕

 1    }

最后我們只要將這個類封裝成一個單獨的DLL﹐然后在每個web.config的httpmodules節中配置即完成了安全管控

后面的文章我會講如何設計這些模塊達到最好擴展性

 

分类:

技术点:

相关文章: