php代码审计【5】代码执行漏洞

代码执行漏洞是指应用程序本身过滤不严,用户可以通过请求将代码注入到应用中执行,当应用在调用一些能将字符串转化成代码的函数(如php中的eval)时,没有考虑到用户是否能控制这个字符串,造成代码注入。

1、常见危险函数(eval和assert)


eval(),assret()将输入的字符串参数作为PHP程序代码来执行
代码1:

浏览器返回:

php代码审计【5】代码执行漏洞_第1张图片

2、常见回调函数:call_user_func()  call_user_func_array()  array_map()等

mixed call_user_func(callable $callback[,mixed $parameter[,mixed $....]])
$callback是要调用的自定义函数名称
$parameter是自定义函数的参数

浏览器返回:

php代码审计【5】代码执行漏洞_第2张图片

 3、动态执行函数

定义一个函数,将函数名(字符串)赋值给一个变量,使用变量名代替函数名动态调用函数。
代码3:

";
echo $_GET['a']($_GET['b']);//接受get请求a的参数作为一个函数,b是作为a函数里的参数'($_GET['a']
echo $cmd($ming);    //自己太菜,开始以为要字符串拼接,直接写就好了
?>
 


// 我们构造我们的payload为:id=assert&data=phpinfo()时,页面就能成功返回phpinfo页面

执行结果:

php代码审计【5】代码执行漏洞_第3张图片

4、 正则表达式(做代码审计时,会遇到正则表达式,了解正则会更容易)

";
$userinfo = "Name: PHP 
Title: Programming Language"; preg_match_all ("/(.*)<\/b>/U", $userinfo, $pat_array); print_r($pat_array[0]); echo "
"; print_r($pat_array[1]); echo "
";echo "
"; echo "-------------普通字符作为原子-----------------------
"; //普通字符作为原子 $pattern = '/abc/U'; $str = 'abcdefghijklmn'; preg_match_all($pattern,$str,$res); var_dump($res); echo "
";echo "
"; echo "-------------特殊符号的字符作为原子-----------------------
"; //特殊符号的字符作为原子 $pattern = '/\[php\]/'; $str = '0123456[php]12345[php]'; preg_match_all($pattern,$str,$res); var_dump($res); echo "
";echo "
"; echo "-------------通用字符作为原子-----------------------
"; //通用字符作为原子 $pattern1 = '/\d/'; //0-9 $pattern2 = '/\D/'; //a-zA-Z $str = '123132asaaaaa222'; preg_match_all($pattern2,$str,$res); var_dump($res); echo "
"; preg_match_all($pattern1,$str,$res); var_dump($res); echo "
";echo "
"; echo "-------------自定义原子-----------------------
"; //自定义原子 $pattern1 = '/[aj]sp/'; //匹配[aj]中任意一个字符作为原子的asp jsp $str = 'jjjjspspspasp'; preg_match_all($pattern1,$str,$res); var_dump($res); echo "
";echo "
"; echo "-------------限定符-----------------------
"; //限定符 $pattern1 = '/go*gle/'; // *匹配掐面出现原子次数0次 1次或多次 $pattern2 = '/go+gle/'; // +匹配前面出现的原子1次或多次 $pattern3 = '/g+gle/'; // +匹配前面出现的原子1次或多次 $pattern4 = '/go?gle/'; // ?匹配前面出现的原子0次或1次,前面出现一次或没有出现,则返回全部,否则为空 $str = 'goooogle'; $str1 ='gogle'; preg_match_all($pattern1,$str,$res); //goooogle var_dump($res); echo "
"; preg_match_all($pattern2,$str,$res); //goooogle var_dump($res); echo "
"; preg_match_all($pattern3,$str,$res); //没有结果 var_dump($res); echo "
"; preg_match_all($pattern4,$str1,$res); //gogle var_dump($res); echo "
";echo "
"; echo "-------------边界限定-----------------------
"; //边界限定 $pattern1 = '/^abc/'; // ^匹配输入字符开始的位置,必须是abc形式的开头 $pattern2 = '/abc^/'; // ^匹配输入字符结尾的位置,必须是abc形式的结尾 $pattern3 = '/^abc$/'; // ^$只匹配某字符 $str = 'abc2342dfads'; preg_match_all($pattern1,$str,$res); var_dump($res); echo "
"; preg_match_all($pattern2,$str,$res); var_dump($res); echo "
"; preg_match_all($pattern3,$str,$res); var_dump($res); echo "
";echo "
"; echo "-------------反向引用-----------------------
"; //反向引用 $pattern = '/\d{4}(-)\d{2}\\1\d{2}/'; // \\1代表第一个()缓冲区,这里等同于(-) $str = '2019-01-28'; preg_match_all($pattern,$str,$res); var_dump($res); ?>

浏览器页面:

php代码审计【5】代码执行漏洞_第4张图片 

5、preg_replace函数:

mixed preg_replace(mixde $pattern,mixed $replacement,mixed $subject[,int $limit = -1[,int &$count]])
$pattern 正则匹配的内容 $pattern存在/e模式修正符修饰,允许代码执行
$replacement 用于替换的字符串或字符串数组
$subject 要进行搜索和替换的字符串或字符串数组

preg_replace() 函数中用到的修饰符 /e 在 PHP5.5.x 中已经被弃用了。

  如果你的PHP版本恰好是PHP5.5.X,那你肯定就会报类似下面这样的错误:

  Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in......

修复方案:
尽量不要执行外部的应用程序或命令
使用自定义函数或函数库来替代外部应用程序或命令的功能
使用escappeshellarg函数来处理命令的参数
使用sare_mode_exec_dir来指定可执行的文件路径
将执行的参数做白名单限制,在代码或配置文件中限制某些参数

你可能感兴趣的:(php代码审计学习历程)