惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
N
News and Events Feed by Topic
D
DataBreaches.Net
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
T
Tailwind CSS Blog
博客园_首页
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
A
About on SuperTechFans
I
InfoQ
S
Securelist
Last Week in AI
Last Week in AI
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
腾讯CDC
大猫的无限游戏
大猫的无限游戏
S
Security @ Cisco Blogs
博客园 - 三生石上(FineUI控件)
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
美团技术团队
aimingoo的专栏
aimingoo的专栏
G
Google Developers Blog
罗磊的独立博客
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Cloudflare Blog
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Latest news
Latest news
Recent Announcements
Recent Announcements
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LINUX DO - 热门话题
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队

博客园 - Janpoem

PHP的Session托管机制容易造成漏洞 关于PHP的Session处理的问题 Eclipse 3.5汉化包打包下载 [转]Benchmarking magic [转]重新发现HTML表格 [转]在网页中嵌入任意字体的解决方案 50款优秀而又实用的PHP工具 博文阅读密码验证 - 博客园 [转]NetBeans 6.5 界面美化与字体设置 [转帖]为 PHP 应用提速、提速、再提速! 昨日换了Ubuntu 8.10 10 SEO elements all websites should have 终于成功安装yaws和erlyweb了 笔记本CPU正常温度是多少? 不知不觉就一年了 谁把AIG拖垮了[转] asp.net MVC更新到preview 5了 什么样的女人值得叫老婆[转] 卸载windows服务
关于php session被保存在数据库中的一个小问题
Janpoem · 2008-11-12 · via 博客园 - Janpoem

session保存在数据库,关于性能方面可查看的资料不多。从以往的经验来说,将Session保存在数据库中,初步上是会觉得性能比File要略降。然而就数据库的特点来说,其本质也是二进制文件,所以,从大流量、广义上来说,保存在数据库,反而提高了性能和稳定性。加上Mysql可优化的地方很多,以及实现数据库保存后,将增加分站部署,安全监控等等诸多便利之处,所以长期来说,一个框架还是应该以提供将Session保存到数据库为基础方法的。

对于php保存到session的细节,网络上可搜罗的资料不多,来去都是基本介绍的方法,我手上几本关于php的书,也都是蜻蜓点水。根据最近的实际测试结果表明,仅仅实现session存储到数据库中,仍不足以保障其安全,关键点在php对于session的gc控制。这个在phpchina.com有很翔实的说明,通过设定:session.gc_probability和session.gc_divisor,可以控制gc执行的几率。

然而我们会发现,问题的关键不在于何时执行gc,因为无论是基于数据库还是File,面向更广的应用时,操作的数量都会呈几何增长,增加系统的gc执行率,无疑增加了系统的负担。那么不执行gc会导致什么问题发生呢?比如我们考虑以下的基本session模式:

session表的基本字段:sid,value,expire,session控制方法(请参照一些最基本的示范,我这里就不罗嗦了),实现最基本的open, close, find, write, destory, gc。

大多数的教程中,会建议我们,在find的方法中执行类似以下的一个SQL CMD:

select value from sessions where sid  = ? and expire > ?

那么,我们可以通过一些办法设置expire是否过期,比如,getExpire()返回一个具体的有效期。现在问题的关键是,大多数的教程告诉我们,我们应该这样去搜索session表,可是当expire过期的那些session呢?他仍然存放在session表中,而且他还保存了上一次会话的value。当然,这些过期的session并不会让value生效,但对于很多逻辑不够严谨的程序来说,却会造成一个致命的判断漏洞,比如一个图片验证码的实例:

在显示验证码的页面,我们给客户端的链接标识了一个$_SESSION['auth'] = 'xxxx',也许用户打开页面以后,忙别的事情去了,结果产生了session id,并且也将session id和auth的值写入到session表了。也许你设置的有效期是10分钟,也许是更长,但不管怎么样用户的操作是非线性的,总会打破你的预计。在有效期之外,他回到了需要验证码的页面,并且执行了某些程序,触发了后台的验证,那么程序本应该按照我们上面所设定的,执行find方法,并且取出auth的值去比对。然而这时候,php会很残酷的告诉你,没有auth这个索引所对应的值,因为find对于超过有效期外的session,就返回了一个false,或者一个null,或者别的什么了,总之,他没有返回你预期的结果。

也许,你后台验证码检验的代码是这么写的:

if ($_SESSION['auth'] === xxxx)

这时,假如你开启了报错,php会抛出一个警告,然后略过这部分,自顾自的执行下面的程序去。假如很不幸的你没开启报错,结果用户又一次巧妙的“溜”了过去。

这问题的严重性还在于,假如你并没有对php的gc处理设置一个合适的比率,他似乎不会执行去destory,那么这条过期的session一直会存在于你的session表中,用户会一次又一次的从这验证中“溜”过去。

有些介绍的文章,在session执行close的时候执行gc程序,我也对此方法进行的实验,但从整个非线性分布的情况来推测,每个客户端访问都会激活gc清理,gc的清理是以expire > ?为条件进行搜索的,也就是不管是也不是,总要来回一趟,而且一旦有符合条件的,还是批量删除,放在非线性的环境中,实在不敢估量。

我觉得,session的gc清理,可以被作为系统的进程来执行,比如类似RoR的做法。或者可放在网站的后台,进行人为的操作。而尽量减少php执行过程所消耗的时间(毕竟是动态语言,省一分是一分)。

而对于session,其实也仅仅是针对当前sid产生的,我将find的方法进行了一点修改:

select value,expire from sessions where sid = ?

sid一般都会被作为主键和索引,搜索的效率也相对较高。

接着进行判断:

if ($ses['expire'] > getExpire()) # 表示为有效
  return $ses['value'];
else { # 表示为无效
  # 这里执行destory方法
  return false;
}

也许方法早有人想到并提出来,不过可能鄙人水平有限没搜索到,也许还有更好的方法,欢迎指正。