现在的位置: 首页 > 综合 > 正文

关于web应用程序安全的思考(修改版)

2012年01月09日 ⁄ 综合 ⁄ 共 4582字 ⁄ 字号 评论关闭

曾经在一家公司有过这样的经历:上班第一天﹐同事在公司的内部网帮我开了一个账号﹐要我登录公司的管理系统学习一下公司的管理制度。看完这些“文件”后,我随便点了一下系统左边的"员工信息查询"菜单﹐随即右边网页的数据区域显示"您无权查看此页"的错误信息﹐本想退出﹐但发现该页面的查询条件输入区域仍在﹐而且查询按钮也只是灰掉而已﹐在查看了网页原代码后﹐抱着随便试一下的心态﹐我在浏览器的地址栏里输入了一行js代码:javascript:alert(document.all['querybtn'].disabled=false) 使查询按钮启用﹐然后单击它﹐居然真的把人事基本资料给查了出来,随后我又打开这个系统的其它页面﹐发现都只是把动作按钮给disable掉来管理权限。

 

当把人事薪资等非常敏感的资料放在web系统中时,如果只是通过上面这种方式来保证数据不被非法读取,很明显这个系统没有达到它应该达到的安全级别。

 

作为一个web系统设计师,在规划一个系统时,必然会考虑到系统的安全性。如何有效的保证系统的安全,如何规划和实现一个可重用,可扩展的安全管控方案都是在安全管控时要考虑的主题。

 

借着这个机会,笔者打算将自己从事web系统安全设计的经验和大家分享。从一个系统设计师的角度说明web系统安全管控。

1.         web运作原理,您的系统到底有多安全?

2.         权限抽象,还一个统一的权限接口

3.         管控观念转换,柳岸花明又一村。

4.         通用安全组件,从此不再苦海挣扎。

Web运作原理

 

Web是由客户端(Client)的请求(Request)和服务器(Web Server)的响应(Response)构成,同一个客户端的多次Request对于Web Server来说都一样,服务器不会将当前收到的Request和以往任何的Request联系起来,因为它们交互的依据是http协议,而此协议规定了http连接的无状态特征。

 

以下为最一个最简单的Request请求:

GET /TestWeb/test.htm HTTP/1.1

Host: localhost

Connection: close

 

它表示向localhost主机请求路径为/TestWeb/test.htmhtml网页,使用GET方法, 1.1版本的HTTP协议。

 

对此请求,WindowsIIS6.0是这样给出Response:

HTTP/1.1 200 OK

Content-Length: 12

Content-Type: text/html

Last-Modified: Wed, 05 Nov 2008 01:01:17 GMT

Accept-Ranges: bytes

Server: Microsoft-IIS/6.0

Date: Wed, 05 Nov 2008 01:01:52 GMT

Connection: close

 

Hello World!

 

包括响应状态码200body的长度,类型,所请求文件的最后修改日期等响应头(Response Header),还有简单的Hello World! 12个字符的html响应体(Response Body)

 

Request请求不依赖于浏览器,事实上您可以使用任何程序语言通过网络编程来做到,以下是一个C#发送Request的例子:

 

using System;

using System.Text;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Text.RegularExpressions;

 

public class RequestDemo

{

    //建立socket连接

    private static Socket ConnectSocket(string server, int port)

    {

        Socket s = null;

        IPHostEntry hostEntry = null;

        hostEntry = Dns.GetHostEntry(server);

        foreach (IPAddress address in hostEntry.AddressList)

        {

            IPEndPoint ipe = new IPEndPoint(address, port);

            Socket tempSocket =

                new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            tempSocket.Connect(ipe);

            if (tempSocket.Connected)

            {

                s = tempSocket;

                break;

            }

            else

                continue;

        }

        Console.WriteLine(s == null ? "" : "连接建立成功﹗");

        return s;

    }

 

    //发送request请求并接收响应字符串

    private static string SocketSendReceive(string request, string server, int port)

    {

        Byte[] bytesSent = Encoding.ASCII.GetBytes(request);

        Byte[] bytesReceived = new Byte[256];

        Socket s = ConnectSocket(server, port);

        if (s == null)

            return ("连接失败﹗");

        Console.WriteLine("正在发送请求...");

        s.Send(bytesSent, bytesSent.Length, 0);

        int bytes = 0;

        StringBuilder responsestr = new StringBuilder();

        Console.WriteLine("正在接收web服务器的回应...");

        do

        {

            bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);

            responsestr.Append(Encoding.UTF8.GetString(bytesReceived, 0, bytes));

        }

        while (bytes > 0);

        return responsestr.ToString();

    }

 

    public static void Main(string[] args)

    {

       //读取在Request.txt中的Request字符串(request.txt末尾至少要留个空行,表明Request结束)

    string requeststr = File.ReadAllText("C:\\tmp\\request.txt")

    Console.WriteLine("请求字符串如下﹕\n{0}\n", requeststr;

 

        //发送且接收Response

        string result = SocketSendReceive(requeststr, "localhost", 80);

        Console.WriteLine("\n{0}", result);

        Console.ReadLine();

    }

}

注:C:\tmp\request.txt中的内容就是前面的Request字符串。

 

程序执行的结果如下:


 

除了直接进行Request外,大部分时候,我们在网页上单击某个链接或按钮时,浏览器和web服务器也在背后进行着这样的请求和响应。

 

例如以下网页程序:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="form.aspx.cs" Inherits="form" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>测试窗体Request</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:Label ID="Label1" runat="server" Text="你的名字:"></asp:Label>

        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="送出" />

        <asp:Label ID="Label2" runat="server" ForeColor="OrangeRed"></asp:Label></div>

    </form>

</body>

</html>

 

Aspx.cs代码如下:

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

 

public partial class form : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

 

    }

    protected void Button1_Click(object sender, EventArgs e)

    {

        Label2.Text = "你输入的名字是:" + TextBox1.Text;

    }

}

 

 

当输入“小生”并按钮“送出”按钮时,实际上就是发送下面的这样一段Request

POST /TestWeb/form.aspx HTTP/1.1

Cache-Control: no-cache

抱歉!评论已关闭.