这样情况下,因为example.orge的服务器通过PHPSESSID来辨认对应的用户的,所以服务器错把攻击者当成了合法的用户。

  整个过程的描述,请看下面的示例图:

   当然这种攻击的方式,前提条件是攻击者必须通过某种手段固定,劫持或者猜测出某个合法用户的PHPSESSID。虽然这看起来难度很高,但是也不是不可能的事情。

  安全性的加强

  有很多技术可以用来加强Session的安全性,主要思想是要使验证的过程对于合法用户来说,越简单越好,然后对于攻击者来说,步骤要越复杂越好。当然,这似乎是比较难于平衡的,要根据你应用程序的具体设计来做决策。

  没有时间写下去,待续。。。

  简单的居于HTTP/1.1请求包括请求行以及一些Host的头部:

  GET / HTTP/1.1

  Host: example.org

  如果客户端通过PHPSESSID传递相关的session标识符,可以将PHPSESSID放在cookie头部中进行传递:

  GET / HTTP/1.1

  Host: example.org

  Cookie: PHPSESSID=12345

  同样地,客户端也可以将session标识符放在请求的url中进行传递。

  GET /?PHPSESSID=12345

  HTTP/1.1Host: example.org

  当然,session标识符也可以包含在POST数据中,但是这对用户体验有影响,所以这种方式很少采用。

  因为来自TCP/IP信息也不一定可以完全信任的,所以,对于web开发者来说,利用TCP/IP中的信息来加强安全性也是不太合适的。 不过,攻击者也必须提供一个合法用户的的标识符,才能假扮成合法用户进入系统。因此,看起来能够有效的保护系统的措施,是尽量地隐藏 session标识符或者使之难于猜测出来。好是两者都能实施。

  PHP会自动生成一个随机的session ID,基本来说是不可能被猜测出来的,所以这方面的安全还是有一定保障的。但是,要防止攻击者获取一个合法的session ID是相当困难的,这基本上不是开发者所能控制的。

  事实上,许多情况下都有可能导致session ID的泄露。 比如说,如果通过GET数据来传递session ID的话,有可能暴露这个敏感的身份信息。因为,有的用户可能会将带有session ID的链接缓存,收藏或者发送在邮件内容中。Cookies是一种像相对来说安全一点的机制,但是用户是可以在客户端中禁止掉cookies的!在一些 IE的版本中也有比较严重的安全漏洞,比较有名的是会泄露cookies给一些有安全隐患的邪恶站点。

  因此,作为一个开发者,可以肯定session ID是不能被猜测出来的,但是还是有可能被攻击者使用某些方法获取到。所以,必须采取一些额外的安全措施来防止此类情况在你的应用程序中发生。

  实际上,一个标准的HTTP请求中除了Host等必须包含的头部,还包含了一些可选的头部.举一个例子,看下面的一个请求:

  GET / HTTP/1.1

  Host: example.org

  Cookie: PHPSESSID=12345

  User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1

  Accept: text/html;q=0.9, */*;q=0.1

  Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66

  Accept-Language: en

  我们可以看到,在以上的一个请求例子中包含了四个额外的头部,分别是User-Agent, Accept, Accept-Charset以及Accept-Language。因为这些头部不是必须的,所以完全依赖他们在你的应用程序中发挥作用是不太明智的。但是,如果一个用户的浏览器确实发送了这些头部到服务器,那么可以肯定的是在接下来的同一个用户通过同一个浏览器发送的请求中,必然也会携带这些头部。当然,这其中也会有极少数的特殊情况发生。假如以上例子是由一个当前的跟服务器建立了会话的用户发出的请求,考虑下面的一个请求:

  GET / HTTP/1.1

  Host: example.org

  Cookie: PHPSESSID=12345

  User-Agent: Mozilla/5.0 (compatible; IE 6.0 Microsoft Windows XP)

  因为有相同的session id包含在请求的Cookie头部中,所以相同的php session将会被访问到。但是,请求里的User-Agent头部跟先前的请求中的信息是不同的,系统是否可以假定这两个请求是同一个用户发出的?

  像这种情况下,发现浏览器的头部改变了,但是不能肯定这是否是一次来自攻击者的请求的话,比较好的措施是弹出一个要求输入密码的输入框让用户输入,这样的话,对用户体验的影响不会很大,又能很有效地防止攻击。

  当然,你可以在系统中加入核查User-Agent头部的代码,类似Listing 3中的代码:

  Listing 3:

  

  session_start();

  if (md5($_SERVER['HTTP_USER_AGENT']) != $_SESSION['HTTP_USER_AGENT'])

  { /* 弹出密码输入框 */ exit;

  }

  /* Rest of Code */ ?>

  当然,你先必须在第一次请求时,初始化session的时候,用MD5算法加密user agent信息并且保存在session中,类似下面listing4中的代码:

  Listing 4:

  

  session_start();

  $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);

  ?>

  虽然不一定需要用MD5来加密这个User-Agent信息,但使用这种方式以后不需要再过滤这个$_SERVER['HTTP_USER_AGENT']数据了。不然的话,在使用这个数据以前必须要进行数据过滤,因为任何来自客户端的数据都是不可信任的,必须要注意这一点。

  在你检查这个User-Agent客户端头部信息以后,做为一个攻击者必须要完成两步才能劫持一个session:

  获取一个合法的session id

  包含一个相同的User-Agent头部在伪造的请求中