那些年php编程犯过的错(1) -- 字符串相等

  1. 云栖社区>
  2. 博客>
  3. 正文

那些年php编程犯过的错(1) -- 字符串相等

余二五 2017-11-07 15:53:00 浏览469
展开阅读全文

此前在一家公司工作的时候犯了一个错,是从事编程以来犯得最严重的错,一辈子难忘呀。

听我细细道来,那时公司有一款新游戏发布,在公测前需要找一批玩家来参加内测,于是就有了发号这样一个流程。其实就是让玩家先来登记一下,然后管理人员从中筛选出一批人员,然后给他们发一个激活码。激活码通过邮箱发送给玩家后,他们再到网站上用邮件里的激活码激活他们的账号。

流程还算简单。我当时的程序是像下面这样写的:


  1. $salt = "!@#$%^&"
  2.  
  3. $user_id = !empty($_GET['uid'])?(int)$_GET['uid']:0; 
  4. $code    = !empty($_GET['c'])?$_GET['c']:0; 
  5. //echo md5($salt .'+'. $user_id); 
  6. if(md5($salt .'+'$user_id) != $code
  7.     echo("no"); 
  8. else 
  9.     echo("yes"); 

一眼看上去好像也没有什么问题吧?当时我也是这么想的。

让我们来分析一下:

程序接收两个参数,一个uid即用户ID,一个c即激活码。
然后通过salt与user_id连接后的md5值与激活码是否相等来判断用户的参数是否正确,进而完成用户的激活。

真的是没有什么技术含量,于是简单的测试了一下。

假如我们的用户ID是3,则md5($salt.'+'.3)之后的值为:


  1. e24fc053f0392e6ac322627d07a568ba

在地址栏中我们输入:


  1. localhost/test.php?uid=3&c=e24fc053f0392e6ac322627d07a568ba

访问后的输出为:yes

一切正如我所期望的那样,太完美了!

程序很快就上线运行了。一开始都工作正常,但是数小时之后,客服反馈有异常情况:一些没有资格的用户也成功激活了。

一开始我还不信,怎么可能呢?程序怎么可能被绕过呢?程序上线之前还交由测试部门测过的呀。

后来通过访问日志了解到了玩家详细的激活流程,只能感叹:劳动人民的智慧是无穷的呀!

他们是这样干的,地址如下:


  1. http://localhost/test.php?uid=3&ce24fc053f0392e6ac322627d07a568ba 

看出区别来了么?注意&后面,是的,c后面的"="没了。

这样访问后的输出结果的确是:yes。

这是怎么回事?

来分析一下吧:

当等号没有了就相当于c参数没有了,此时,程序中的$code将会默认为0。而我们知道md5的返回值是一个字符串,当一个字符串与0作比较时将会进行隐式的类型转换。杯具的字符串将会转换成0,使得if判断被绕过,进而完成了激活。

知道了问题,解决的办法就简单了,最简单的办法就是用恒等来进行判断:


  1. if(md5($salt .'+'$user_id) !== $code

当然也可以用strcmp来判断,或是将$code默认为空字符也行。

当天晚上通宵加班对程序进行了修改,直到凌晨5点成功发布上线,并确认没有bug后才回家休息。

总结:在进行字符串比较时,一定要注意类型,用恒等或strcmp来判断是最安全的。










本文转自 ustb80 51CTO博客,原文链接:http://blog.51cto.com/ustb80/1070938,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
余二五
+ 关注