1
ywisax 2015-05-04 15:59:28 +08:00 2
观察下最终的hash就明白了,都是0eXXXXXXXX 。
再加上php是弱语言,会自动判断数据类型。 零=零,明白了吧? |
2
anyforever 2015-05-04 16:01:40 +08:00
md5('240610708'); // 0e462097431906509019562988736854
md5('QNKCDZO'); // 0e830400451993494058024219903391 怎么可能这么容易碰撞 |
3
anyforever 2015-05-04 16:03:25 +08:00
var_dump(md5('240610708') === md5('QNKCDZO'));
|
4
ywisax 2015-05-04 16:04:00 +08:00 2
准确点说,是“==”对比的时候会进行数据转换,0eXXXXXXXXXX 转成0了。
了解php的“==”和“===“就更加清晰了。 |
5
yangff 2015-05-04 16:08:28 +08:00 3
|
6
aliang032 2015-05-04 16:12:56 +08:00 1
找了下手册说明贴给大家:
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行 http://php.net/manual/zh/language.operators.comparison.php |
8
xifangczy 2015-05-04 16:34:44 +08:00
卧槽 这脑洞。。太赞了
|
9
raincious 2015-05-04 16:36:13 +08:00
这是个坑没错,所以密码比较的时候需要用 ===。但,怎么用它来:
> PHP 探测任意网站密码明文/加密手段办法 ?不解。 |
10
est OP @raincious 把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的没跑。
同理,密码设置为 240610708,换密码 QNKCDZO 登录能成功,那么密码没加盐直接md5保存的。 |
11
cat9life 2015-05-04 17:00:31 +08:00
长见识啊...
|
12
avtester 2015-05-04 17:03:44 +08:00
知道了又能如何?
|
13
bingu 2015-05-04 17:04:55 +08:00
呃,这个略迪奥
|
14
xierch 2015-05-04 17:06:20 +08:00
PHP 的大坑哈哈哈
|
15
tabris17 2015-05-04 17:07:41 +08:00
能强等的地方我都用强等的
|
16
NeoAtlantis 2015-05-04 17:09:45 +08:00 via Android 1
散列不叫加密!
要不谁给我解密看看?XD |
17
wy315700 2015-05-04 17:12:46 +08:00
收藏了 ,好牛逼的攻击
|
19
Citrus 2015-05-04 18:31:35 +08:00 via iPhone
第一次见到如此能唬人的标题党。。。看标题以为楼主完全攻破了 MD5 可以批量找碰撞了。。。
|
20
rwalle 2015-05-04 18:46:33 +08:00
PHP中的==是挺坑的
但是PHP中还有很多同样大的坑。。。 |
21
codejay 2015-05-04 18:47:30 +08:00
这不是两个字符串比较吗 为什么要转换成数字
|
23
gDD 2015-05-04 18:54:27 +08:00 via iPhone
|
24
gDD 2015-05-04 18:55:57 +08:00 via iPhone
还有判断密码,secret 等要用 hash_equals(),直接用 === 会出 Timing Attack 漏洞的。
|
26
gDD 2015-05-04 19:13:34 +08:00 via iPhone
@lincanbin 开源项目我觉得反而更容易解决,composer 一个 symfony security core 就好,里面有 hash_equals 的 shim,反而是公司内没用 composer 管理的的私有项目比较难维护。
|
27
noanti 2015-05-04 19:50:33 +08:00
这是php的feature?
php还真是最好的语言。。。 |
28
tSQghkfhTtQt9mtd 2015-05-04 19:56:19 +08:00 via Android
password_hash() 路过......
|
29
belin520 2015-05-04 20:07:33 +08:00 via Android
md5,加盐,md5,取前30位
|
30
xiaozi 2015-05-04 20:09:45 +08:00
这完全是没有 ===,如果是 ===, 根本就没办法检测吧。
|
34
invite 2015-05-04 22:02:18 +08:00
从另一方面印证了:PHP 是全宇宙最牛逼的语言。
|
35
barbery 2015-05-04 22:11:55 +08:00
官方都建议直接用password_hash加密,用md5还不加salt,我就真的没话说了
|
36
Jaylee 2015-05-04 22:16:21 +08:00
搞不懂这个贴子为啥到处都是,做PHP的人基础都这么差? 都没看过手册?
|
39
RIcter 2015-05-04 23:39:00 +08:00
|
40
kofj 2015-05-04 23:48:54 +08:00
楼主的语法有问题.fix:探测任意php网站密码明文/加密手段办法
|
41
Jaylee 2015-05-04 23:57:03 +08:00
@est 不管是不是wordpress基础差,至少我能看出是PHP弱类型导致的。再说,这也不过是一个小bug而已,有必要往这里发?
|
42
bdnet 2015-05-04 23:58:56 +08:00
除了用 === ,还可以用 strcmp ,返回 0 是相等
|
43
bdnet 2015-05-05 00:02:34 +08:00
PHP是世界上最好的语言
2333 |
44
iyaozhen 2015-05-05 01:22:19 +08:00 1
@est 不是一般都数据库查询比较吗?SELECT count(*) FROM user WHERE username = '$username' AND password = '$password';
|
46
evlos 2015-05-05 05:40:38 +08:00
看到 #44 我好像突然知道为什么很多网站连密码都有格式限制了。。。
|
47
rwalle 2015-05-05 06:02:30 +08:00
44楼。。。
|
48
djyde 2015-05-05 08:04:17 +08:00
作为一个 JavaScripter,我表示用 === 是个良好的习惯
|
51
hahastudio 2015-05-05 10:04:25 +08:00
太可怕
HN 的这条回复很能说明问题: They're comparing two things of the same type: two strings! |
52
chaucerling 2015-05-05 10:10:43 +08:00
语言设计上的坑太多233
|
53
fashioncj 2015-05-05 10:35:08 +08:00
作为一个渗透学习者最喜欢44楼这样的程序猿了~
|
54
66beta 2015-05-05 10:57:28 +08:00
44楼处世未深,你们别欺负他
|
55
tuoxie007 2015-05-05 11:04:38 +08:00
PHP是世界上最好的语言 +1
|
56
yxzblue 2015-05-05 11:05:56 +08:00
看来dz生成一个随机的salt值进行二次加密再保存,果然是要好一些啊。
|
57
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) 也必须强制 === 了。 |
58
zhengkai 2015-05-05 12:06:51 +08:00 2
上午研究了一下这个问题,根本原因是科学计数法这个 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 下一个补丁应该能修正这个问题(纯字符串比较不做转换),但是这个问题感觉还是挺伤的 |
59
bravecarrot 2015-05-05 12:45:48 +08:00 via iPad
@est 脑洞大,蛮有道理
|
60
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 编码一下。 |
61
Daniel65536 2015-05-05 13:33:00 +08:00 via iPad
@iyaozhen username= " ' or 1=1 or ' "
|
62
iyaozhen 2015-05-05 13:41:50 +08:00
@Daniel65536 这个我知道,一般账号也只允许字母或数字。而且分号会被mysql_real_escape_string过滤掉吧。
我的本意是若网站使用 SELECT count(*) FROM user WHERE username = '$username' AND password = '$password'; 这种方式的话“把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的没跑。”就不能说明网站是明文保存呀。 |
63
lincanbin 2015-05-05 13:42:33 +08:00
|
64
lincanbin 2015-05-05 13:46:36 +08:00
@iyaozhen 引号过滤然后直接拼接SQL语句是个不推荐的做法了,现在PHP官方建议使用PDO类或者mysqli类来替代mysql系列函数。
也就是参数绑定,这样做的话,SQL命令与参数会分两次传到MySQL的socket,MySQL根据接收顺序就可以识别出命令和参数,从而避免在参数中构造命令(也就是SQL注入)。 PDO的话可以参考这个 https://github.com/lincanbin/PHP-PDO-MySQL-Class |
65
est OP |
66
iyaozhen 2015-05-05 14:00:08 +08:00
@lincanbin 嗯,谢谢。这个我了解过。产品线上是使用mysqli类或者框架自身的参数绑定的方式。拼 sql 的方式几年前已经交过学费了,不过感觉学费还是交的不够。。。
|
68
WKPlus 2015-05-05 14:39:18 +08:00
@est
把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的没跑。 这句话补充是不是这样: 1. 把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的且密码对比的时候用的是php的==符号 2. 但是如果密码比较的时候用的是===,那么就算是明文保存的,上述探测手段也是发现不了的 |
69
est OP |
70
WKPlus 2015-05-05 19:50:59 +08:00
@est 如果1193131是万能密码的话,你“把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的没跑”这句话就不成立了呀
我的那两句解释只是想把你原来那句话的隐含意思说出来 |
71
est OP @WKPlus 这不很容易解决么。把密码改成任意密码,如果1193131也能登录,那么说明1193131就是万能密码。
准确的说,顶楼给出的几个密码对,可以衍生展开,如果尝试几组都符合特征,那么可以得到明文密码/md5无盐加密的结论。 |
73
gDD 2015-05-05 22:57:17 +08:00
@RemRain 天……上面的帖子你都白看了吗?最次最次用 "$pass1" === "$pass2" 或者 strcmp(),最好用 hash_equals() 啊。
|
75
mahone3297 2015-05-07 22:08:33 +08:00
这个帖子很赞,学习了。。。
|
76
mingyun 2015-05-11 21:40:00 +08:00
果真脑洞打开,不过'240610708' ,'QNKCDZO'这种字符是怎么发现的?
|
77
fhefh 2015-10-17 21:48:14 +08:00
学习了 mark~~
|
78
wusuopuBUPT 2015-10-17 23:58:51 +08:00
@est 原来如此!
|
79
Kratoshy 2015-12-08 15:16:31 +08:00
var_dump(md5('240610708') === md5('QNKCDZO'));
这个是 false 吧? |