自能生羽翼,何必仰云梯
代码:
1 |
|
error_reporting(0) 关闭所有PHP错误报告
session_start() 初始化session
highlight_file(__FILE__) 对当前文件进行语法高亮显示
开头先包含了一个 flag.php 文件进来,然后通过 GET 传入 id 赋值给 login 变量
1 | include "flag.php"; |
判断,如果 login 里没有 cookie 这个参数,或者 cookie 参数不等于 md5 后的 session flag 值 ,满足一个条件,就直接 die
1 | if(!@isset($login['cookie'])||$login['cookie'] != @md5($_SESSION['flag'])){ |
满足这个条件很简单,cookie 设置 flag=123456 ,然后把 123456 进行 md5 加密后传给cookie

走进 else 里面
1 | mt_srand(substr($login['cookie'],17,7)); |
把传入的 cookie 值从第17位起,后面的7位截取出来做种子(我这里截取出来就是 9800998 ),然后传给 mt_srand() 函数做种子
mt_scand(seed) 这个函数分发种子,然后再通过 mt_rand() 函数来生成随机数
这个题的核心考点也就是关于这个函数使用不当产生的漏洞利用:同一个种子下生成的随机数值是相同的
网上有大佬做的实验:
设置固定种子后,后面每次执行,随机数也都相同,这证明了破解随机种子的可行性

再往下
1 | $content = "<?php \$flag="."'".$flag."'"."?>"; |
写入内容赋值给 content 变量里,变量 flag 应该是包含开头的 flag.php文件里面的
然后 filename 等于一个 mt_rand() 生成的随机数,使用我们的种子(9800998)生成一个随机数看看

生成的第一个随机数是:1160121479,证明我们生成的文件名应该就是 1160121479.php

然后就是把第一行的内容写入到第二行的文件里面,生成文件
继续往下
1 | mt_srand(mt_rand()); |
发现又使用了新的种子,我们在本地也模拟一下

发现使用新的种子生成的随机数是 954576979 1277894509 …
得出后续的随机数后,继续往下跟
1 | if ($_POST['key'] == mt_rand()) |
判断POST里面的 key 需要等于 mt_rand() 随机值,我们把新种子生成的第一个随机数 954576979 传进去

成功走进 if 里面,然后下面就是一个动态变量覆盖,不过他的值又需要下一个随机数,我们上面已经算出来了,下一个随机数是1277894509
然后我们把变量 filename 传给他,他可以直接请求到变量文件里面的 flag
最后一个语句就类似变成了 file_get_contents($filename) ,把 flag 文件给我们读取出来了
