php session应用与安全问题解决办法
当然使用 Session 还有很多优点,比如控制容易,可以按照用户自定义存储等,存储于数据库,我这里就不多说了.
Session 在 php.ini 是否需要设置呢?一般不需要的,因为并不是每个人都有修改 php.ini 的权限,默认 Session 的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍.
开始介绍如何创建 Session,非常简单,启动 Session 会话,并创建一个 $admin 变量:
- // 启动 Session
- session_start();
- // 声明一个名为 admin 的变量,并赋空值。
- $_SESSION["admin"] = null;
如果你使用了 Seesion,或者该 PHP 文件要调用 Session 变量,那么就必须在调用 Session 之前启动它,使用 session_start() 函数,其它都不需要你设置了,PHP 自动完成 Session 文件的创建.
执行完这个程序后,我们可以到系统临时文件夹找到这个 Session 文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是 32 位编码后的随机字符串,函数bool session_set_save_handler(callback open,callback close,callback read,callback write,callback destroy,callback gc)就是提供给我们解决这个问题的方案.
该函数使用的6个函数如下:
1. bool open() 用来打开会话存储机制,
2. bool close() 关闭会话存储操作.
3. mixde read() 从存储中装在session数据时使用这个函数
4. bool write() 将给定session ID的所有数据写到存储中
5. bool destroy() 破坏与指定的会话ID相关联的数据
6. bool gc() 对存储系统中的数据进行垃圾收集
例子见php手册session_set_save_handler() 函数,如果用类来处理,代码如下:
- session_set_save_handler(
- array('className','open'),
- array('className','close'),
- array('className','read'),
- array('className','write'),
- array('className','destroy'),
- array('className','gc'),
- )
关于session安全问题
攻击者通过投入很大的精力尝试获得现有用户的有效会话ID,有了会话id,他们就有可能能够在系统中拥有与此用户相同的能力.
http协议时无状态的,所以通常网站都会用session来标示一个用户,session在客户端就是一个保存一个特殊令牌的cookie,关键的信息是存放在服务器端的,但因为令牌是保存在客户端,并且要经过传输,所以还是很不安全的.
1、会话终止,但令牌仍处于活动状态
情景:当用户退出时,程序只是删除了令牌(例如,通过发布一个清空令牌的Set-Cookie指令),然而并没有删除服务器端的数据,如果用户继续使用该令牌,仍然可以使用.
解决方法:退出后删除服务器端的数据。
测试方法:退出后,仍然使用该令牌,如果活动正常,这该令牌仍然有效,使用Firefox的web developer 插件就可以.
2、令牌可以通过url传输
情景:如果可以通过url传输,攻击者使用攻击者站点上的链接,可以轻松的固定受害人的会话标识符,比如:http://www.example.com/index.php?PHPSESSID=fixed_session_id。假使受害者还没有一个example.com站点会话标识符的cookie,那么会话固定就成功了。一旦受害者使用了攻击者指定的会话标识符,那么攻击者就能劫持受害者的会话,并模仿受害者的用户代理,试图假装成受害者。
解决方法:在PHP中设置 use_only_cookies 的值 1,在php中默认就是 1,可以不修改.
3、在网络上泄露了令牌
情景:网络以非加密方式传输会话令牌,则处在适当位置的监听者可以截取此令牌。
a、当用户登录时是使用http非安全通道时,用户与服务器间传输的所有的数据都是可以截获的。 这时登录者对于监听者是没有什么秘密可言的。这时候,如果截获的数据不足以执行第二次登录 (例如,一些银行系统会要求登录者提交不断变化的验证码)。如果攻击者想执行任何操作,就必须劫持他窃听的会话。
b、一些程序在一些HTTP页面就发送一个令牌,然后再登录页面开始使用https教程,并且登录时也不修改此令牌,结果最初并未通过验证的用户会话在登录后被升级为通过验证的会话。窃听者可以在登录前就拦截到这个令牌。所以为了提高安全性,程序可以在登录的时候发送令牌或发送一个新令牌。
c、程序容许通过HTTP登录,如果攻击者成功将用户的链接降级为HTTP,他仍然能够拦截这个令牌。
d、如果所有的页面都是用HTTPS,但图片和一些js,css教程等的静态文件是使用HTTP传输。这时如果静态文件和登录等页面时在同一个域下,令牌也会通过HTTP泄露。所以将静态文件使用别的域好处是很多的。
其他解决方法:
a、如果应用程序使用HTTP Cookie传送会话令牌,应确认其设置了secure标记,防止他们通过非加密链接传送令牌。
b、不接受非安全登录
c、session和客户端的HTTP_USER_AGENT绑定,但该方法效果不是很理想,攻击者可以伪造这些数据。
4、客户端令牌易被劫持
a、网站存在跨站攻击漏洞,这样用户的令牌很容易被劫持。需要检查全站,避免出现跨站攻击,也可以设置cookie_httponly,可以在一定程度上避免脚本的攻击。具体可以参考 利用httponly提升应用程序安全性
b、攻击者可以使用其他针对用户的攻击,以不同的方式劫持用户的会话。包括实施会话固定攻击,即攻击者向一名用户发送一个已知的会话令牌,等待他们登录。
解决方法:1、可以每次登录成功后发送新的会话令牌,2、对令牌设定一个特别的格式,不接受其他格式的令牌,该方法效果并不是很好。
5、Cookie范围过于宽泛
浏览器在提交Cookie时会将Cookie提交到设定的域及其任何子域,而不提交到其他域。如果应用程序将Cookie的域设定的过于宽泛,会是程序出现各种漏洞。
6、令牌不够强大
令牌在其生成过程中,过于简单,或者有规律可循,从而使攻击者可以以常规方式预测或推断其他用户的令牌。例如,攻击者可以在A时间得到从网站正常获取一个令牌,在B时间在网站获取一个令牌,则通过分析,得到这个时间段的大量令牌样本,从而攻击。
解决方法:生成一个强大的令牌,得到足够的复杂度。但一些高强度的随机源必须采用足够的步骤获得足够的熵,这需要时间,所以通常不能满足需求。所以可以通过合并一些用户特有的数据来得到足够的,可以使用的数据:
1、一串随机数
2、来源IP地址
3、请求中的User_Agent消息头
4、请求时间
5、服务器私密的随机数
串联上面的数据,然后使用适当的散列算法(比如md5,SHA-256)等等对这个字符串处理,(将最容易变化的数据项放在散列输入的开始部分有助于最大化散列算法中的“雪崩”效应.
其他的一些增强安全的方法:
1、每页面令牌
在每个页面使用新的令牌,可以通过HTML表单传送,也可以使用Cookie传送,如果出现不匹配的情况整个会话终止.
2、在执行重要操作前,要求进行两步确认操作
安全是个大问题,细节方面是最重要的,这篇文章是我在阅读《黑客攻防技术宝典-web实战篇》记下的笔记.
- <?php
- if(!isset($_SESSION['user_agent'])){
- $_SESSION['user_agent'] =$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
- }
- /* 如果用户session ID是伪造 */
- elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] .$_SERVER['HTTP_USER_AGENT']) {
- session_regenerate_id();
- }
- ?>