闪电十六鞭
点开发现出现源码
<?php
error_reporting(0);
require __DIR__.'/flag.php';
$exam = 'return\''.sha1(time()).'\';';
if (!isset($_GET['flag'])) {
echo '<a href="./?flag='.$exam.'">Click here</a>';
}
else if (strlen($_GET['flag']) != strlen($exam)) {
echo '长度不允许';
}
else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {
echo '关键字不允许';
}
else if (eval($_GET['flag']) === sha1($flag)) {
echo $flag;
}
else {
echo '马老师发生甚么事了';
}
echo '<hr>';
highlight_file(__FILE__);
这直接就开始审计了
error_reporting(0); 可略过
require __DIR__.'/flag.php';
_DIR_是php5.3以后的一个魔术常量,用于指向当前执行的PHP脚本所在的目录
require就是文件包含函数 那意思就是包含flag.php
——————————————————————————————————————————————————————————
$exam = 'return\''.sha1(time()).'\';';
定义exam的值 其中sha1(time())表示获取当前时间的sha1散列值
(所以点击超链接后f12看一下,然后刷新你会发现每一秒的flag值都不一样)
——————————————————————————————————————————————————————————
if (!isset($_GET['flag'])) {
echo '<a href="./?flag='.$exam.'">Click here</a>';
}
isset判断flag变量是否不为空
!isset判断是否为空 为空则输出下面的代码
(所以会看到一个click here,点击就会提交一个flag的参数(按f12去看),这个flag参数取exam的值,所以会通过下一个if
但是最后一个else过不了所以会显示马老师发生什么事了)
——————————————————————————————————————————————————————————
else if (strlen($_GET['flag']) != strlen($exam)) {
echo '长度不允许';
}
判断提交的flag参数长度是否跟exam参数长度相等 相等则通过 否则提示长度不允许
——————————————————————————————————————————————————————————
else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {
echo '关键字不允许';
}
一堆正则,匹配flag的值 如果前两个if通过的话如果里面有相应的则输出关键字不允许
——————————————————————————————————————————————————————————
else if (eval($_GET['flag']) === sha1($flag)) {
echo $flag;
}
将flag的sha1散列值和flag的值进行强比较,如果相同则返回flag
eval函数用于计算或执行参数,所以里面的===才会执行
所以初始思路是找sha1的碰撞 但是flag的值要和exam的值长度相等,而且exam的值是随时变化的。
不过发现有个eval函数 这个函数会导致任意代码执行,也就是常见的一句话木马<?php eval($_POST[cmd])?>
因为echo被禁了,所以该怎么构造flag的值呢?
看了一下其他人的wp,发现可以用<?=$flag?>代替 <?php echo $flag; ?>
因为传的exam的长度是49,所以构造payload的长度也要是49 (这个看上面的按f12那步,数一下长度就行)
然后不要出现被正则的内容就行。
于是可以构造
$hack=mlag;$hack{0}=f;111111111111;?><?=$$hack;?>
解释:
1.因为flag被禁了,所以可以用hack{0}=f来替换hack变量的第1个字母,所以被替换成flag
2.然后$$hack 代表$($hack)相当于$flag(因为hack变量的值后面变为flag)
3.<?=$$hack;?>代表<?=$flag;?> 就相当于<?php echo $flag; ?>
这样就输出了flag的值,最终得到了flag