PHP 探测任意网站密码明文/加密手段办法: md5('240610708') == md5('QNKCDZO')

2015-05-04 15:51:31 +08:00
 est
var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
var_dump('0010e2' == '1e3');
var_dump('0x1234Ab' == '1193131');
var_dump('0xABCdef' == ' 0xABCdef');

感觉这个不科学啊

https://news.ycombinator.com/item?id=9484757
26974 次点击
所在节点    PHP
79 条回复
Jaylee
2015-05-04 23:57:03 +08:00
@est 不管是不是wordpress基础差,至少我能看出是PHP弱类型导致的。再说,这也不过是一个小bug而已,有必要往这里发?
bdnet
2015-05-04 23:58:56 +08:00
除了用 === ,还可以用 strcmp ,返回 0 是相等
bdnet
2015-05-05 00:02:34 +08:00
PHP是世界上最好的语言

2333
iyaozhen
2015-05-05 01:22:19 +08:00
@est 不是一般都数据库查询比较吗?SELECT count(*) FROM user WHERE username = '$username' AND password = '$password';
czb
2015-05-05 04:42:23 +08:00
evlos
2015-05-05 05:40:38 +08:00
看到 #44 我好像突然知道为什么很多网站连密码都有格式限制了。。。
rwalle
2015-05-05 06:02:30 +08:00
44楼。。。
djyde
2015-05-05 08:04:17 +08:00
作为一个 JavaScripter,我表示用 === 是个良好的习惯
lincanbin
2015-05-05 08:13:01 +08:00
@iyaozhen 你这样写要注入了……
kfll
2015-05-05 08:53:21 +08:00
@iyaozhen 如果要告诉用户用户名不存在还是密码错误的话,
hahastudio
2015-05-05 10:04:25 +08:00
太可怕
HN 的这条回复很能说明问题:
They're comparing two things of the same type: two strings!
chaucerling
2015-05-05 10:10:43 +08:00
语言设计上的坑太多233
fashioncj
2015-05-05 10:35:08 +08:00
作为一个渗透学习者最喜欢44楼这样的程序猿了~
66beta
2015-05-05 10:57:28 +08:00
44楼处世未深,你们别欺负他
tuoxie007
2015-05-05 11:04:38 +08:00
PHP是世界上最好的语言 +1
yxzblue
2015-05-05 11:05:56 +08:00
看来dz生成一个随机的salt值进行二次加密再保存,果然是要好一些啊。
gDD
2015-05-05 11:22:23 +08:00
@est 一开始我以为 (string) == (string) 是绝对以字符串形式做对比的,但是查了 PHP Manual 之后,发现If you compare a number with a string **or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically**. 确实也业余了一把,简直宇宙最大坑!xD -- http://php.net/manual/en/language.operators.comparison.php

说几个相关项目:

Laravel 4 的时候也爆出过一个更直接的漏洞,直接传入 'true' 就足够。 -- http://barryvdh.nl/laravel/2015/02/21/csrf-protection-in-laravel-explained/

jQuery 的规范里规定了 Strict equality checks (===) must be used in favor of abstract equality checks (==). The only exception is when checking for undefined and null by way of null. -- https://contribute.jquery.org/style-guide/js/

而 PHP 的 == 比 JavaScript 的 == 更散漫,本身 PHP 里 null 和 false 就是要用 === 来判断的,这回 OP 的问题一受到重视,连 (string) 也必须强制 === 了。
zhengkai
2015-05-05 12:06:51 +08:00
上午研究了一下这个问题,根本原因是科学计数法这个 feature

php > var_dump('0e1' == '0e2');
bool(true)

“数字 e 数字”格式的字符串有时被作为数字,有时被作为字符串



php > echo intval('1e10');
1
php > echo '1e10' + 0;
10000000000

但是混蛋就混蛋在 (string) == (string) 时也会做这个转换,这就没法搞了(更何况都是字符串还要这么转换,也会降低性能)

比方说 switch((string)$s) { 的时候就完全没法规避这个问题

前同事从源码里看到这个判断的函数叫 zendi_smart_strcmp

下一个补丁应该能修正这个问题(纯字符串比较不做转换),但是这个问题感觉还是挺伤的
bravecarrot
2015-05-05 12:45:48 +08:00
@est 脑洞大,蛮有道理
iyaozhen
2015-05-05 13:26:13 +08:00
@evlos
@rwalle
@lincanbin
@66beta
@fashioncj
汗。。。求说清楚呀,我感觉我老板要开除我了。
肯定不直接拼sql,我也知道一点 sql 注入,但是一直浮于表面,求指点。
$password 拼 sql 之前肯定会 $password = sha1/md5($password+$salt) 。
账号($username)的话一般有限制只能数字或者字母,然后自我安慰 mysql_real_escape_string() 一下(老感觉这个不靠谱)。
当然这样就只能提示账号或密码错误(不匹配)。

要看账号是不是存在,SELECT count(*) FROM user WHERE username = '$username'; 这样?看来账号也不能明文存。是不是可以可逆加密或者简单的 base64 编码一下。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/188364

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX